在学习vue的过程中,想要获取一个vue的脚手架,便于快速进行开发,选择了vue-admin-template,将该框架进行二次开发,作为vue初学者,踩了很多坑,以此记录分析和修改。
github:https://github.com/PanJiaChen/vue-admin-template
branch: tag\3.11.0
要想对已有的demo进行二次开发,首先的是要对demo进行了解,我认为要想比较快速的上手进行开发,拿出demo的某个请求进行分析,然后将该完整的请求过程换成自己所要开发的项目。在这里,我就拿出vue-admin-template的“登录”请求做分析。
既然是登录功能,那么就从登录页面开始分析。
在src\views\login\index.vue中:
除开页面基本的输入验证信息,剩下的主要方法就是登录了,如下:
handleLogin() {
this.$refs.loginForm.validate(valid => {
if (valid) {
this.loading = true
this.$store.dispatch('Login', this.loginForm).then(() => {
this.loading = false
this.$router.push({ path: this.redirect || '/' })
}).catch(() => {
this.loading = false
})
} else {
console.log('error submit!!')
return false
}
})
}
(1) this.$store.dispatch('Login', this.loginForm).then(()
该请求使用$store.diepatch调取src\store\modules里的user.js的Login方法,如下:
// 登录
Login({ commit }, userInfo) {
const username = userInfo.username.trim()
return new Promise((resolve, reject) => {
login(username, userInfo.password).then(response => {
const data = response.data
setToken(data.token)
commit('SET_TOKEN', data.token)
resolve()
}).catch(error => {
reject(error)
})
})
},
(2)login(username, userInfo.password).then(response =>
在new Promise中,通过login调用了src\api的login.js中的login方法
如下:
import request from '@/utils/request'
export function login(username, password) {
return request({
url: '/user/login',
method: 'post',
data: {
username,
password
}
})
}
(3)该方法中return request,显然调用了第一行import request对应的文件中的方法。src\utils中的request.js很重要。该方法创建axios实例、 request拦截器、response 拦截器。如下:
// 创建axios实例
const service = axios.create({
baseURL: process.env.BASE_API, // api 的 base_url
timeout: 5000 // 请求超时时间
})
在该方法中,很重要的一点是baseURL的指向。
其指向了config下的dev.env.js中的配置,如下:
module.exports = merge(prodEnv, {
NODE_ENV: '"development"',
BASE_API: '"https://easy-mock.com/mock/5950a2419adc231f356a6636/vue-admin"',
})
在后面进行二次开发时,需要将BASE_API的值修改为实际项目的接口基本地址,如http://localhost:8082。
// request拦截器
service.interceptors.request.use(
config => {
if (store.getters.token) {
config.headers['X-Token'] = getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
}
return config
},
error => {
// Do something with request error
console.log(error) // for debug
Promise.reject(error)
}
)
该拦截器主要在有request时,如果在store中存储有token则在headers中带上x-Token,实际这个拦截器中直接return config即可,
然后在登录完成后,访问其他页面的时候带上token访问。这个暂时不考虑分析。
service.interceptors.response.use(
response => {
/**
* code为非20000是抛错 可结合自己业务进行修改
*/
const res = response.data
if (res.code !== 20000) {
Message({
message: res.message,
type: 'error',
duration: 5 * 1000
})
------省略------
return Promise.reject('error')
} else {
return response.data
}
},
error => {
console.log('err' + error) // for debug
Message({
message: error.message,
type: 'error',
duration: 5 * 1000
})
return Promise.reject(error)
}
)
该拦截器主要用于在请求完后,后台返回的消息进行处理。
(4)这个”登录“请求从开始发起request到response结束,基本流程就是这样。那么,在该项目登录模块中,form数据的提交到验证在到返回数据,获取token,获取用户信息,怎么都没有看到在上面分析的方法中呢。原因是在上面的框架结构图中,使用了mock,mock的简单使用请看vue中使用mock
(5)在mock目录中,index.js中,定义了mock的拦截,将对“登录”请求的提交/user/login进行拦截,如下:
import userAPI from './user'
Mock.mock(/\/user\/login/, 'post', userAPI.login)
该拦截将会调用mock目录下的user.js中的login方法。如下:
login: res => {
const { username } = JSON.parse(res.body)
const data = tokens[username]
if (data) {
return {
code: 20000,
data
}
}
return {
code: 60204,
message: 'Account and password are incorrect.'
}
},
于是就会将响应数据返回,这样在src\utils\request.js中,response响应拦截就会获取到数据,并进行相应判断,按发起登录请求路线返回,在src\store\modules里的user.js登录方法中设置setToken,直至返回src\views\login\index.vue,并进行相应页面跳转。
到这里,已经将在vue-admin-template中的“登录”请求进行了分析,其他请求的分析也是这样。作为初学者,在使用这个框架时,碰到了很多问题,分析了比较久的时间,特此记录下,为了以后碰到相应的问题不在耗费太多的时间,也为了给即将学习的朋友一点思路。写得不好,感谢指出。经过分析后,后面将会进行项目的二次开发。
首先,我们要改造项目,并且是“登录”功能,那么先根据上面分析的,修改项目的API接口为我们自己的,通过分析,如下:
(1)运行起来项目后,打开浏览器访问,F12打开调试控制台,选择Sources中,打开上述分析中的request.js,在如图位置打上断点,在request拦截器中,查看config中的数据
或者在console中,直接打上“config”查看
可以看到此处的baseURL的值为项目下config目录中,dev.env.js中配置的BASE_API
在上述方法中,再次在request.js的响应拦截处打个断点,查看响应的数据,如下:
可以看到相应的数据,而该数据的产生,就源于我们上面说的项目mock模拟数据,mock目录下index.js拦截了url,调用了user.js中的login方法
于是在request.js的response拦截中获取了相应的数据。
(1)将dev.env.js中的BASE_API值修改为项目(这里已我已有的后端项目接口举例,已启动后端项目)
这时来试试登录会怎么样,还是在request.js上的两个拦截器中打上断点
从图中可以看出来,接口的baseURL已经变成我们想要的,但是竟然响应返回的值还是mock中的模拟数据,并且跳过断点后,仍然是登录成功进入系统。
这里还是mock拦截在操作,并不会真正访问我们自己项目的api
一种解决方法:
如上图,将mock拦截注销掉就可以了,这样user/login就不会被mock拦截,就可以访问我们的后端api。
(2)后端登录接口:http://localhost:8082/login
postman测试:
在src\api\login.js中,将login方法的请求路径修改为/login(原来为/user/login)
这样,当点击登录时就可以调用我们的后端登录api接口了。
再次测试登录页面登录功能
先输入错误的密码
可以看到返回的结果中就是我们后端接口的返回数据。上图中报错消息的处理后面在进行。
输入正确的密码
可以看出返回了正确的数据,报错信息仍然和上面的报错信息图一样。因为我们还没对request.js中的response拦截器中的code进行修改,它判断出code不为20000的都是报错误消息,但是我们的后端接口200是正常,非200是异常。所以接下来,我们对拦截器进行简单修改,仅作为思路。
(3)下面贴上修改前和修改后的
import { Message, MessageBox } from 'element-ui' //这个位置也注意,后面不使用MessageBox要删除,否则报错
service.interceptors.response.use(
response => {
/**
* code为非20000是抛错 可结合自己业务进行修改
*/
const res = response.data
if (res.code !== 20000) {
Message({
message: res.message,
type: 'error',
duration: 5 * 1000
})
// 50008:非法的token; 50012:其他客户端登录了; 50014:Token 过期了;
if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
MessageBox.confirm(
'你已被登出,可以取消继续留在该页面,或者重新登录',
'确定登出',
{
confirmButtonText: '重新登录',
cancelButtonText: '取消',
type: 'warning'
}
).then(() => {
store.dispatch('FedLogOut').then(() => {
location.reload() // 为了重新实例化vue-router对象 避免bug
})
})
}
return Promise.reject('error')
} else {
return response.data
}
},
error => {
console.log('err' + error) // for debug
Message({
message: error.message,
type: 'error',
duration: 5 * 1000
})
return Promise.reject(error)
}
)
修改后:
import { Message } from 'element-ui'
// response 拦截器
service.interceptors.response.use(
response => {
/**
* code为非20000是抛错 可结合自己业务进行修改
*/
const res = response.data
console.log(res)
if (res.code !== 200) {
Message({
message: res.msg,
type: 'error',
duration: 5 * 1000
})
// // 50008:非法的token; 50012:其他客户端登录了; 50014:Token 过期了;
// if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
// MessageBox.confirm(
// '你已被登出,可以取消继续留在该页面,或者重新登录',
// '确定登出',
// {
// confirmButtonText: '重新登录',
// cancelButtonText: '取消',
// type: 'warning'
// }
// ).then(() => {
// store.dispatch('FedLogOut').then(() => {
// location.reload() // 为了重新实例化vue-router对象 避免bug
// })
// })
// }
return Promise.reject('error')
} else {
return response.data
}
},
error => {
console.log('err' + error) // for debug
Message({
message: error.msg,
type: 'error',
duration: 5 * 1000
})
return Promise.reject(error)
}
)
再次登录,发现打印的登录成功,但是会报错,那是因为登录成功后触发了获取用户信息的方法,获取出错。后端api接口在登录成功时返回了用户的信息。要设置用户信息等,可以在下面的方面内设置,包括token,关于获取用户信息就不说了。
关于对vue-admin-template的分析和改造就到此了,通过分析一个登录请求到响应,了解该项目的流程及功能点。至于其他的,可以参考该登录请求作为了解。
作为初学者,很多前端的知识都没有掌握,见谅,如有错误请指出,以期进步,感谢!