前后端分离的数据交互需要注意高效的交互方式,常用轮子有 axios。
主要模式是用使用顶层的 store 中的 state 存储 token,在每次请求中使用 token 发起请求,然后判断响应的状态返回状态信息。
request.js :
import axios from 'axios'import { Message, MessageBox } from 'element-ui'import store from '@/store'import { getToken } from '@/utils/auth'// create an axios instanceconst service = axios.create({baseURL: process.env.BASE_API, // api 的 base_urltimeout: 40000 // request timeout})// request interceptorservice.interceptors.request.use(config => {// Do something before request is sentif (store.getters.token) {// 让每个请求携带token-- ['X-Token']为自定义key 请根据实际情况自行修改config.headers['admin-token'] = getToken()}return config},error => {// Do something with request errorconsole.log(error) // for debugPromise.reject(error)})// response interceptorservice.interceptors.response.use(/** response => response,* 下面的注释为通过在response里,自定义code来标示请求状态* 当code返回如下情况则说明权限有问题,登出并返回到登录页* 如想通过 xmlhttprequest 来状态码标识 逻辑可写在下面error中* 以下代码均为样例,请结合自生需求加以修改,若不需要,则可删除*/response => {const res = response.dataconst typew = res.typeif (typew === 'application/vnd.ms-excel') {return res}// 50008:非法的token; 50012:其他客户端登录了; 50014:Token 过期了;if (res.code === 'login' || res.code === 'role_not_exit') {// 请自行在引入 MessageBox//MessageBox.confirm('你已被登出,请重新登录', '确定登出', {confirmButtonText: '重新登录',cancelButtonText: '取消',type: 'warning'}).then(() => {store.dispatch('FedLogOut').then(() => {location.reload() // 为了重新实例化vue-router对象 避免bug})})// }return Promise.reject(res)} else if (res.code === 'no_permit') {Message({message: res.msg,type: 'error',duration: 3 * 1000})return Promise.reject(res)} else {return res}},error => {let response = {msg: '系统发生异常,请重试或联系管理员',status: 'system error',code: 50000,detail: error,ok: false}if (error.response) {if (error.response.status === 504) {response = {...response,msg: `${error.response.status}:网关炸了!`}} else if (error.response.status === 404) {response = {...response,msg: `${error.response.status}:请求未知路径!`}} else if (error.response.status === 403) {response = {...response,msg: `${error.response.status}:权限不足,请联系管理员!`}} else if (error.response.status === 500) {response = {...response,msg: `${error.response.status}:服务器发生异常,请重试或联系管理员!`}} else {response = {...response,msg: `${error.response.status}:发生未知错误,请重试或联系管理员!`}}} else {response = {...response,msg: '请求无响应,请检查本地或联系管理员检查服务端网络连接状态'}Message({type: 'error',message: response.msg})}return response})export default service
store/index.js :
import Vue from 'vue'import Vuex from 'vuex'import app from './modules/app'import errorLog from './modules/errorLog'import permission from './modules/permission'import tagsView from './modules/tagsView'import user from './modules/user'import getters from './getters'Vue.use(Vuex)const store = new Vuex.Store({modules: {app,errorLog,permission,tagsView,user},getters})export default store
getters.js :
const getters = {sidebar: state => state.app.sidebar,language: state => state.app.language,size: state => state.app.size,device: state => state.app.device,visitedViews: state => state.tagsView.visitedViews,cachedViews: state => state.tagsView.cachedViews,token: state => state.user.token,avatar: state => state.user.avatar,name: state => state.user.name,introduction: state => state.user.introduction,status: state => state.user.status,roles: state => state.user.roles,roleName: state => state.user.roleName,setting: state => state.user.setting,permission_routes: state => state.permission.routes,addRoutes: state => state.permission.addRoutes,errorLogs: state => state.errorLog.logs}export default getters
utils/auth.js :
import Cookies from 'js-cookie'const TokenKey = 'Admin-Token'export function getToken() {return Cookies.get(TokenKey)}export function setToken(token) {return Cookies.set(TokenKey, token)}export function removeToken() {return Cookies.remove(TokenKey)}