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;