路由拦截
项目中,有些页面需要登录后才能进入,例如,在某页面A,用户在操作前需要先进入登录页(此时需要将上一页的地址(/survey/start
)作为query存入login页面的地址中,如: http://localhost:8071/#/login?redirect=%2Fsurvey%2Freport
),登录成功后再进入页面A。
首先,在router.js中创建路由时,给需要登录的路由中的 meta 添加字段:requireLogin,如下:
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导航守卫,参考
axios 请求拦截
上面的方法只是进行了前端拦截,无法确定存储在本地的token是否已经失效。需要 axios 拦截器:
在mian.js 中:
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 = falseVue.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')