写在前面
前端现代化工程实践中,路由设计与权限拦截是不可或缺的一环,不管是react或者vue,不论是SPA还是MPA,路由都是整个项目核心的部分,下面我将结合目前已有的一些实践,来聊一聊路由设计以及对应的守卫拦截,此处以vue为例
路由设计的组成部分
一般来讲,我们至少需要业务路由,404路由, 通配符*路由三部分,路由的mode可以根据浏览器表现不同,分为history与hash路由。
路由的history与hash模式
简单来说,不管是history还是hash路由,对于内部调用不产生影响,也就是说,不管你的页面最终形式是/home
还是/#/home
,在代码里写的时候,都是$router.push('/home)
, 区别是什么呢?
- 外观不同:history模式的path路径不带#号,hash模式有#号
- 原理不同:hash模式使用onhashchange,history使用pushState
- 兼容性不同:hash模式兼容性好(对浏览器的兼容性好),history的兼容性比hash模式差一些
- 项目上线后有区别,一般来说,hash无需特殊配置,而history常常需要后端配置资源路径,在404时返回index.html等
- 在微信内的h5初始化jssdk时,history每一次都需要重新初始化,而hash则不用,支付回调或静默授权时,history与hash表现不一致。
路由的两种构建方式
- 基于后台返回的数据,通过addRoute的方式去动态添加路由
- 基于对业务的梳理总结,通过参数路由与meta元标签相结合的方式处理路由
动态路由的优点
- 路由来源于后台,无需硬编码维护
- 一次解析,多次配置
动态路由的缺点
- 如果采用了异步加载,会导致白屏,需要刷新重载
静态参数路由与元数据设计
静态参数路由就是形如/list/:code
这样的形式,这个路由相当于可以匹配到
/list/book
/list/cate
... 这样做的好处是,我们可以通过一个页面去接入同类型的列表页,而不用担心重复编码的问题
路由对象的元数据支持我们做任意的扩展,比如,
我们可以定义当前路由是否需要登录
meta: { isAuth: true/false }
我们还可以定义路由是否需要新增页签(多页签模式下)
meta: { isTab: true/false }
我们可以定义路由是否在菜单隐藏
meta: { isHide: true/false }
为了区分是普通路由还是参数路由,我们可以定义是否是参数路由
meta: { isParams: true/false }
有些子页面从属于父页面,我们还能定义他的权限来源
meta: { staticName: 'sa' }
...
可以这样讲 路由的meta属性,就是为了我们实现自定义的权限拦截而存在的!
权限拦截的设计
权限拦截依赖于路由的导航守卫,我们可以定义这几种守卫,依次去处理, 首先,loginAuth, 这个守卫是为了校验是否登录而存在的,这里我们需要考虑到白名单的情况,当然也可以完全依赖路由meta里的isAuth
js
function loginAuth (to, from, next) {
const ignore = ['login', '404', '403']
if (ignore.includes(to.name) || !to.meta.isAuth) {
next()
} else {
next('/login')
}
}
然后就是业务内是否有权限的判断。
js
function permAuth (to, from, next) {
if (loginIgnore.includes(to)) {
next()
return false
}
const perm = // 权限标识数组
if(to.meta.isParams) {
if (perm.includes(to.params.code)) {
next()
} else {
next('/403')
}
} else {
if (perm.includes(perm)) {
next()
} else {
next('/403')
}
}
}
结语
ok , 我们通过这样的方式,就实现了静态加载动态业务,而且避免了重复开发,避免了首次加载的白屏。over~