vue项目路由配置(导航守卫+白名单)
- vue Router
- 导航守卫
- router目录结构
- 具体实现代码
- router.js
- constRouter.js
- index.js
- 总结
vue Router
Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。包含的功能有:
- 嵌套的路由/视图表
- 模块化的、基于组件的路由配置
- 路由参数、查询、通配符
- 基于 Vue.js 过渡系统的视图过渡效果
- 细粒度的导航控制
- 带有自动激活的 CSS class 的链接
- HTML5 历史模式或 hash 模式,在 IE9 中自动降级
- 自定义的滚动条行为
导航守卫
首先说明该项目的前提条件,一般在未登陆情况下默认跳转至login页面,因此需要导航守卫来确保这一需求。但,例如忘记密码,注册,各类提醒等页面的跳转并不需要用户进行登陆操作,因此我们设置了路由白名单让这一类的页面可以跳出导航守卫的条条框框直接跳转并渲染出来。
router目录结构
首先来看一下该项目的router目录结构
- routers.js文件中定义的是默认路由,也就是上面说到的登陆页面
- constRouters.js文件中定义的是路由白名单,也就是那些不需要用户登陆之后再进行跳转的页面
- index.js文件中写的便是具体路由跳转的逻辑代码,也是最重要的一部分
ps:其余几个文件里写的是根据角色来划分的路由,与导航守卫的思想关系不大
具体实现代码
router.js
// 默认路由 /login
var routers = [
{ path: "/",
name: "主页",
component: QuestionView,
icon: "none",
redirect: "/login",//重定向至/login
children:[
{ path: "/home",
name: "系统主页",
component: HomePageView,
icon: "home"
}
]
},
]
export default routers
constRouter.js
在该文件下定义的是不需登陆便可跳转的页面,例如忘记密码,浏览器版本提醒等
// 路由白名单
var constRouters = [
{
path: '/login',
name: '登录页',
component: LoginView,
},
{
path: '/index',
name: '首页',
redirect: '/login'
},
{
path:'/forgetStepOne',
name:'forgetStepOne',
component: ()=>import('../views/forgetPassword/ForgetStepOne.vue')
},
{
path:'/forgetStepTwo',
name:'forgetStepTwo',
component: ()=>import('../views/forgetPassword/ForgetStepTwo.vue')
},
{
path:'/forgetStepThree',
name:'forgetStepThree',
component: ()=>import('../views/forgetPassword/ForgetStepThree.vue')
}, {
path:'/majorSelect',
name:'majorSelect',
component: ()=>import('../views/login/MajorSelect.vue')
},
{
path:"/browserVersionReminder",
name:"浏览器版本提醒",
component: ()=>import('../views/error/BrowserVersionReminder')
}
]
export default constRouters
index.js
该文件下实现了具体的路由跳转逻辑
- 首先全局使用Router,再获取默认路由和路由白名单
import Vue from 'vue'
import Router from 'vue-router'
import constRouters from './constRouters'
import routers from './routers'
import teacherRouters from './teacherRouters'
import studentRouters from './studentRouters'
import adminRouters from './adminRouters'
import db from '../utils/localstorage'
import websocketRequest from '../utils/websocketRequest'
import store from '../store';
Vue.use(Router)//vue全局使用Router
function exportWhiteListFromRouter(router){
let res = []
for(let item of router)
res.push(item.path)
return res
}
let router = new Router({
routes: constRouters
})
function save (name, data) {
localStorage.setItem(name, JSON.stringify(data))
}
router.addRoutes(routers)
// 路由白名单
const whiteList = exportWhiteListFromRouter(constRouters)
- 导航守卫,渲染动态路由
在该项目中我们使用的是全局前置守卫
使用 router.beforeEach 注册一个全局前置守卫:
const router = new VueRouter({ ... }) router.beforeEach((to, from, next) => { // ... })
当一个导航触发时,全局前置守卫按照创建顺序调用。守卫是异步解析执行,此时导航在所有守卫 resolve 完之前一直处于 等待中。 每个守卫方法接收三个参数: to: Route: 即将要进入的目标 路由对象 from: Route: 当前导航正要离开的路由 next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。
话不多说,直接贴核心代码
// 导航守卫,渲染动态路由
router.beforeEach((to, from, next) => {
let token = db.get('USER_TOKEN')
let user = db.get('USER')
let identity = user.identity
let name = user.name
let userRouter = db.get('USER_ROUTER')
if(whiteList.indexOf(to.path) != -1){
console.log("白名单")
next()
return
}
if(!token.length || !user){
websocketRequest.closeWebSocket();
next('/login');
return
}
console.log(userRouter)
//配置动态路由信息
let newRouter = null;
if(identity === "教师" || identity === "大学生"){
newRouter = teacherRouters;
}else if(identity === "学生"){
newRouter = studentRouters;
}else if(name === "管理员"){
newRouter = adminRouters;
}
if(store.getters.newRouter === newRouter)
next()
else{
router.addRoutes(newRouter) //添加动态路由
store.dispatch('routerAction',newRouter).then(res => {
next({ ...to })
}).catch(() => {
})
}
})
先说明一点,在给部分的代码中使用到了if-else优化思想——提早返回,减少嵌套 比如说,前两个if都是提前返回的情况。
- 判断当前路由是否为路由白名单的最后一个,如果不是则next(),也就是说跳出了导航守卫的条条框框;
- 判断当前用户是否登陆,如果没有则跳转至登陆页面。
接下去的代码便是正常的用户登陆之后的路由跳转代码了
总结
在这个项目 背景下,我的理解中导航守卫的作用便是防止未登陆用户进入系统内,需先默认跳转至登陆页面进行登陆之后,才允许跳转至其它页面。 但在很多情况下,有些功能并不需要用户进行登陆,因此为了解决这一问题我们采取了路由白名单,将这种特殊功能的页面路由单独拎出来,使其跳出导航守卫以达到我们的目的。 以上便是在具体项目中的前置全局守卫的具体操作过程,第一次记录,写的不好请多多指教