1.config index.js下面的跨域代理设置:
proxyTable: { '/api': { target: 'http://xxxx', //要访问的后端接口 changeOrigin: true, pathRewrite: { '^/api': 'http://xxx' } }, },
2.http.js(封装axios)
import Vue from 'vue' import axios from 'axios' import QS from 'qs' //视情况用于不用; import { Loading, Message } from 'element-ui'; import store from '../store/index' let loading //定义loading变量 function startLoading() { //使用Element loading-start 方法 loading = Loading.service({ lock: true, text: '努力加载中……', background: 'rgba(0, 0, 0, 0.5)' }) } function endLoading() { //使用Element loading-close 方法 loading.close() } //那么 showFullScreenLoading() tryHideFullScreenLoading() 要干的事儿就是将同一时刻的请求合并。 //声明一个变量 needLoadingRequestCount,每次调用showFullScreenLoading方法 needLoadingRequestCount + 1。 //调用tryHideFullScreenLoading()方法,needLoadingRequestCount - 1。needLoadingRequestCount为 0 时,结束 loading。 let needLoadingRequestCount = 0 export function showFullScreenLoading() { if (needLoadingRequestCount === 0) { startLoading() } needLoadingRequestCount++ } export function tryHideFullScreenLoading() { if (needLoadingRequestCount <= 0) return needLoadingRequestCount-- if (needLoadingRequestCount === 0) { endLoading() } } let baseWebURL = ''; // 环境的切换 if (process.env.NODE_ENV == 'development') { //开发环境 baseWebURL = '/api' + '/api';(多加一个api是后台那边统一拦截处理视项目情况而定加不加) } else if (process.env.NODE_ENV == 'test') { //测试环境 baseWebURL = 'https://www.test.com'; } else if (process.env.NODE_ENV == 'production') { //生产环境 baseWebURL = 'http://www.producetion.com'; } //生成一个axios实例 var instance = axios.create({ baseURL: baseWebURL, }); console.log(instance, 'instance') //1.请求超时时间 instance.defaults.timeout = 10000; //2.post请求头 instance.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8'; //3.公共部分(请求带token设置) //instance.defaults.headers.common['Authorization'] = store.state.token; //4.返回数据类型的定义 //instance.defaults.responseType = 'json'; //5.带cookie请求 instance.defaults.withCredentials = true // 请求拦截器 instance.interceptors.request.use( config => { console.log(config, 'config请求拦截器') //1.全局loadin配置 /*2.token校验:一般是在登录完成之后,将用户的token通过localStorage或者cookie存在本地; 然后用户每次在进入页面的时候(即在main.js中),会首先从本地存储中读取token; 如果token存在说明用户已经登陆过则更新vuex中的token状态; 然后,在每次请求接口的时候,都会在请求的header中携带token; 后台人员就可以根据你携带的token来判断你的登录是否过期,如果没有携带,则说明没有登录过。 v1.每次发送请求之前判断vuex中是否存在token v2.如果存在,则统一在http请求的header都加上token,这样后台根据token判断你的登录情况 v3.即使本地存在token,也有可能token是过期的,所以在响应拦截器中要对返回状态进行判断*/ const token = store.state.token; alert(token,'token') token && (config.headers.Authorization = token); if (config.method == 'post') { console.log('post请求统一需要做什么判断') } //config.headers.Accept = 'application/json'; //规定接受形式json格式 showFullScreenLoading() //开启loading return config; }, error => { return Promise.reject(error); }); // 响应拦截器 instance.interceptors.response.use( response => { console.log(response, 'response响应拦截器') // 如果返回的状态码为200,说明接口请求成功,可以正常拿到数据 //否则的话抛出错误 if (response.status === 200) { tryHideFullScreenLoading() //关闭loading Message({ showClose: true, message: '响应成功', type: 'success' }) return Promise.resolve(response); } else { return Promise.reject(response); } }, error => { console.log(error, 'error') if (error.response.data.status) { console.log('后台错误码统一处理') switch (error.response.data.status) { // 401:未登录;未登录则跳转登录页面,并携带当前页面的路径;在登录成功后返回当前页面,这一步需要在登录页操作。 case 401: router.replace({ path: '/login', query: { redirect: router.currentRoute.fullPath } }); break; // 403:token过期;登录过期对用户进行提示;清除本地token和清空vuex中token对象;跳转登录页面 case 403: Message({ showClose: true, message: '登录过期,请重新登录', duration: 1000, type: 'warning' }) //清除token localStorage.removeItem('userToken'); store.commit('LOGIN_OUT', null); //跳转登录页面,并将要浏览的页面fullPath传过去,登录成功后跳转需要访问的页面 setTimeout(() => { router.replace({ path: '/login', query: { redirect: router.currentRoute.fullPath } }); }, 1000); break; //404请求不存在 case 404: Message({ showClose: true, message: '网络请求不存在', duration: 1000, type: 'error' }) break; //其他错误,直接抛出错误提示 default: Message({ showClose: true, message: error.response.data.message, duration: 1000, type: 'error' }) } } return Promise.reject(error); }); // 封装axios的get请求 export function getData(url, params) { return new Promise((resolve, reject) => { instance.get(url, params).then(response => { resolve(response.data); }) .catch(error => { reject(error); }); }); } // 封装axios的post请求 export function postData(url, params) { return new Promise((resolve, reject) => { instance.post(url, QS.stringify(params)).then(response => { resolve(response.data); }) .catch(error => { reject(error); }); }); }
3.api.js(封装接口)
import { postData, getData } from './http.js' export function cityList(data = {}) { return postData('/xxxx/xx', data); }
4.vuex构成
(1)index.js
import Vue from 'vue'; import Vuex from 'vuex'; import state from './state' import mutations from './mutations' import getters from './getters' import actions from './actions' Vue.use(Vuex); const store = new Vuex.Store({ state, mutations, getters, actions }); export default store;
(2)state.js
export default { state: { // 存储token token: localStorage.getItem('userToken') ? localStorage.getItem('userToken') : '' } }
(3)mutation-types.js (常量)
export const LOGIN_IN = 'LOGIN_IN';//登入 export const LOGIN_OUT = 'LOGIN_OUT';//登出
(4)mutation.js
import * as type from './mutation-types' export default { //登入 [type.LOGIN_IN](state, token) { state.token = token; localStorage.setItem('userToken', token); }, //登出 or 退出登入 [type.LOGIN_OUT](state, token) { localStorage.removeItem("userToken", token); state.token = token; }, }
(5)actions (这里是异步操作)
export default{ //actions这里提交的是mutation getLoginInInfo({commit},token){ commit('LOGIN_IN',token) }, getLoginOutInfo({commit},token){ commit('LOGIN_OUT',token) } }
(6)getters.js 视情况放什么获取state更改后的值
(7)路由 router下面的index.js
import Vue from 'vue' import Router from 'vue-router' import store from '../store/index' //方式一:最简单直接的使用组件 //import HelloWorld from '@/components/HelloWorld' //import Test from '@/components/test' //方式二:webpack自带的模块按需加载 r就是resolve //const HelloWorld = r => require.ensure([], () => r(require('@/components/HelloWorld')), 'HelloWorld'); Vue.use(Router) const router = new Router({ mode: 'history', //去掉地址栏#号 routes: [{ path: '/', name: 'testMain', meta: { title: '系统首页', requireAuth: true, // 添加该字段,表示进入这个路由是需要登录的 }, component: resolve => require(['@/components/testMain'], resolve) //测试首页 }, { path: '/login', name: 'login', meta: { title: '登入', }, component: resolve => require(['@/components/login'], resolve) //模拟登入------(方式三:懒加载方式) }, { path: '/HelloWorld', name: 'HelloWorld', meta: { requireAuth: true, title: '测试二级联动路由传参', }, component: resolve => require(['@/components/HelloWorld'], resolve) //测试二级联动路由传参 }, { path: '/test', name: 'test', meta: { requireAuth: true, title: '测试参数解码', }, component: resolve => require(['@/components/test'], resolve) //测试参数解码 }, { path: '/testEgdit', name: 'testEgdit', meta: { requireAuth: true, title: '富文本编辑器试用', }, component: resolve => require(['@/components/testEgdit'], resolve) //富文本编辑器试用 }, { path: '/testElementComponent', name: 'testElementComponent', meta: { requireAuth: true, title: 'element ui组件测试', }, component: resolve => require(['@/components/testElementComponent'], resolve) //element ui 组件测试 }, { path: '/tableTest', name: 'tableTest', meta: { requireAuth: true, title: 'element ui表格组件测试', }, component: resolve => require(['@/components/tableTest'], resolve) //element ui table组件测试 }, { path: '/echartTest', name: 'echartTest', meta: { requireAuth: true, title: 'echart插件测试', }, component: resolve => require(['@/components/echartTest'], resolve) //echart插件测试 }, { path: '*', name: 'notFound', meta: { title: '404页面', }, component: resolve => require(['@/components/notFound'], resolve) //全不匹配的情况下,返回404,路由按顺序从上到下,依次匹配。最后一个*能匹配全部 }] }) router.beforeEach((to, from, next) => { //可以做 loadong 开始加载 效果 store.state.token = localStorage.getItem('userToken'); //获取本地存储的token if (to.meta.title) { //判断是否有标题 该操作可以再监听路由时候处理 watch:{'$route'(to,from){xxx操作}} document.title = to.meta.title } if (to.meta.requireAuth) { // 判断该路由是否需要登录权限 if (store.state.token) { // 通过vuex state获取当前的token是否存 console.log('有token时候', to, from, next) next(); } else { console.log('没有token时候', to) next({ path: '/login', query: { redirect: to.fullPath } // 将跳转的路由path作为参数,登录成功后跳转到该路由 }) } } else { next(); } }) router.afterEach(route => { //loading加载完成 }); export default router;