vue项目中如果使用到登录注册会用到token,这里需要我们在二次封装的request中设置拦截器,
首先在plugins文件下新建一个reques.js
import axios from 'axios' import { Message } from 'element-ui' import store from '@/store' import router from '@/router/index.js' var CancelToken = axios.CancelToken const service = axios.create({ // baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url // withCredentials: true, // send cookies when cross-domain requests timeout: 15000 // request timeout }) // request interceptor 请求之前拦截判断,权限等处理 service.interceptors.request.use( (config) => { // do something before request is sent if (!localStorage.getItem('token')) { router.replace({ name: '/loginPage' }) } else { config.headers['token'] = localStorage.getItem('token') } config.cancelToken = new CancelToken(e => { store.state.axiosCancel.push(e) }) // if (store.getters.token) { // let each request carry token // ['X-Token'] is a custom headers key // please modify it according to the actual situation // config.headers['X-Token'] = getToken() // } return config }, (error) => { // do something with request error console.log(error) // for debug return Promise.reject(error) } ) // response interceptor service.interceptors.response.use( /** * If you want to get http information such as headers or status * Please return response => response */ /** * Determine the request status by custom code * Here is just an example * You can also judge the status by HTTP Status Code */ (response) => { const res = response.data if (!res.data) { if (res.code === '200') { return Promise.reject(new Error('数据异常!')) // localStorage.removeItem('token'); } else { return res } } else if (res.data instanceof Array) { if (res.data.length === 0) { return Promise.reject(new Error('数据异常!')) } else { return res } } else { return res } // var str = JSON.stringify(res) // var json = JSON.parse(str) // console.log(json) // if the custom code is not 20000, it is judged as an error. // if (res.code !== 20000 && res.code !== 0) { // // Message({ // // message: res.message || 'Error', // // type: 'error', // // duration: 5 * 1000 // // }) // // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired; // if (res.code === 50008 || res.code === 50012 || res.code === 50014) { // // to re-login // MessageBox.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', { // confirmButtonText: 'Re-Login', // cancelButtonText: 'Cancel', // type: 'warning' // }).then(() => { // store.dispatch('user/resetToken').then(() => { // location.reload() // }) // }) // } // return Promise.reject(new Error(res.message || 'Error')) // } else { // } }, (error) => { console.log('err' + error) // for debug // Message({ // message: error.message, // type: 'error', // duration: 5 * 1000 // }) return Promise.reject(error).catch(err => { console.log(err) }) // return Promise.reject(error) } ) export default service
具体我们看一下拦截器的内容,这里我们每次请求时都给请求设置一个拦截器,拦截器主要判断我们 localStorage.token是否存在,如果存在就给请求设置一个请求头,如果没有token就回到登陆界面,注意请求还是出去了,还是能.then得到结果。
在真实项目中,当路由已经跳转,而上一页的请求还在pending状态,如果数据量小还好,数据量大时,跳到新页面,旧的请求依旧没有停止,这将会十分损耗性能,这时我们应该先取消掉之前还没有获得相应的请求,再跳转页面。所以这里我们用到了CancelToken,通过传递一个 executor 函数到 CancelToken 的构造函数来创建 cancel token,在vuex里写一个全局axiosCancel的空数组,用来装我们的cancel函数,每次请求时都将cancel函数推入的axiosCancel数组。
然后我们在路由守卫里添加一个清空cancel的方法,这样就实现了每次切换页面时都会清空padding状态的请求,减少性能消耗
router.beforeEach((to, from, next) => { //中断请求 store.state.axiosCancel.forEach(item=> { item() }) //清空数组 store.state.axiosCancel = [] })
封装好请求后,我们新建一个api文件夹,这里存放各种接口,我这里就举两个post和get方法的例子供参考
import request from '@/plugins/axios' // 根据指定条件数据 export function getUsersByConditions(params) { return request({ url: '/019/user/getUsersByConditions', method: 'get', params: params }) } // 修改用户数据 export function saveOrUpdateUser(data) { return request({ url: '/019/user/saveOrUpdateUser', method: 'post', data }) }