項目中,有些頁面須要登陸後才能進入,例如,在某頁面A,用戶在操做前須要先進入登陸頁(此時須要將上一頁的地址(/survey/start
)做爲query存入login頁面的地址中,如: http://localhost:8071/#/login?redirect=%2Fsurvey%2Freport
),登陸成功後再進入頁面A。css
首先,在router.js中建立路由時,給須要登陸的路由中的 meta 添加字段:requireLogin,以下:html
const router = new Router({ routes: [ { path: '/login', name: 'Login', component: Login, meta: { title: '登陸頁' } }, { path: '/register', name: 'Register', component: Register, meta: { title: '註冊頁' } }, { path: '/', redirect: '/survey/start', name: 'Full', component: Full, children: [ { path: '/survey/start', name: 'Home', component: Home, meta: { title: '首頁', requireLogin: true } }, { path: '/survey/report', name: 'Report', component: Report, meta: { title: '詳情頁', requireLogin: true } } ] } ] })
而後使用 router.beforeEach 註冊一個全局前置守衛:前端
// 全局導航鉤子 router.beforeEach((to, from, next) => { if (to.meta.title) { // 路由發生變化修改頁面title document.title = to.meta.title } if (to.meta.requireLogin) { if (store.state.token) { if (Object.keys(from.query).length === 0) { // 判斷路由來源是否有query,處理不是目的跳轉的狀況 next() } else { let redirect = from.query.redirect // 若是來源路由有query if (to.path === redirect) { // 避免 next 無限循環 next() } else { next({ path: redirect }) // 跳轉到目的路由 } } } else { next({ path: '/login', query: { redirect: to.fullPath } // 將跳轉的路由path做爲參數,登陸成功後跳轉到該路由 }) } } else { next() } })
關於Vue Router導航守衛,參考:https://router.vuejs.org/zh/guide/advanced/navigation-guards.html#%E5%85%A8%E5%B1%80%E5%89%8D%E7%BD%AE%E5%AE%88%E5%8D%ABvue
上面的方法只是進行了前端攔截,沒法肯定存儲在本地的token是否已經失效。須要 axios 攔截器:ios
在mian.js 中:axios
import Vue from 'vue' import App from './App.vue' import router from './router' import store from './store' import Axios from 'axios' import './assets/styles/reset.css' import './plugins/element.js' import htmlToPdf from './utils/htmlToPdf' Vue.config.productionTip = false Vue.use(htmlToPdf) // http request 攔截器 Axios.interceptors.request.use( config => { if (sessionStorage.getItem('token')) { // 若存在token,則每一個Http Header都加上token config.headers.Authorization = `token ${sessionStorage.getItem('token')}` } return config; }, err => { return Promise.reject(err); }) // http response 攔截器 Axios.interceptors.response.use( response => { return response; }, error => { if (error.response) { switch (error.response.status) { case 401: // 返回 401 (未受權) 清除 token 並跳轉到登陸頁面 sessionStorage.removeItem('token') router.replace({ path: 'login', query: { redirect: router.currentRoute.fullPath } }) } } return Promise.reject(error.response.data) // 返回接口返回的錯誤信息 } ) new Vue({ router, store, render: h => h(App) }).$mount('#app')