起始
前端的权限控制一直是一个可繁可简的问题,要想简单,直接写入所有路由,然后将每个路由的权限写入路由原信息中,然后在router.beforeEach
中判断这个路由是否该用户的权限,进行reject()
或者next()
。这样做很简单,但是Vue提供了一个addRouter
的api,用于动态注册路由,由此可以用这个api来根据用户角色进行动态路由注入。
问题
动态注入路由后404问题
一般我们将公共路由放置到路的初始化中,这其中就包括404页面,他的path一般是*****,也就是匹配所有路由,因此Vue官方文档中提到:
当使用通配符路由时,请确保路由的顺序是正确的,也就是说含有通配符的路由应该放在最后。路由
{ path: '*' }
通常用于客户端 404 错误。
所以我们一般将404放到静态路由的最后一个,但是当我们动态注入路由后,理论上来说,404
的优先级应该比我动态注入的路由高,所以我第一使用动态注入时,所有页面跳转至404
页面。开始以为是注入失败,后来将404页面删除就能够正常跳转了。
解决办法
所以我参照了
element-ui-admin
中的思路,没有使用*
来匹配404页面,而是在router.beforeEach
中,判断路由是否存在,手动跳转路由。我在今天(2020-1-6)再次测试,发现
Vue-router
似乎对*
进行了优化,即使将*
的路由放到任意位置,包括首位,也会正确匹配路由,即当前所有路由中不存在时,才回去主动匹配*
里有。当前使用的版本是:Vue(2.6.10)
,Vue-router(3.1.3)
,但是仅仅对*
做了优化,其他通配符,比如/*
并没有优化。
综合就是如果Vue-router版本够高,则可以使用*
的方式来进行通配页面。
刷新路由消失的问题
还有一个问题就是如果用户主动刷新浏览器,那么动态注入的路由就会生效,但是浏览器url并不会变,这个时候又会跳转至404。我这里采用的比较简答的方法就是在Vue实例初始化的时候进行重新注入。
- 在用户登录时将其用户标识信息存储至SessionStorage。
- 在Vue实例初始化时(第一次或刷新),首先应该是判断token,如果token失效,直接跳转至登录页。
- 如果token有效,再通过sessionStorage获取用户标识符,请求后端用户权限等级。再进行路由注入,并跳转至权限对应的页面。
因为刷新过程中整个页面的数据都会重新载入,所以我们必须使用一个持久化的容器,sessionStorage
,localStorage
,cookie
都可以,但是我们不能将权限信息直接明文放到这些容器中,要么加密,要么只存储标识符,通过标识符再请求用户信息。
用户退出的问题
使用router.addRouter
的问题在于官方只提供了增加路由的api,并没有提供一个清除路由的api,这就导致如果同一个页面两个用户先后登录,那么就会出现路由重复注入,或者越级路由暴露的问题。经过查找资料,目前有两个主流的办法:
直接
location.reload()
刷新页面,重置整个Vue实例,路由当然也被重置。- 优点
- 方便,一行代码解决问题。
- 缺点
- 如果页面应用过大,那么重新载入可能会花费一定的时间,会给用户不好的体验。
- 优点
使用hack的方法,直接创建一个新的
VueRouter
,并将静态路由添加到新的路由中去,然后用新Router
的matcher
去替换就Router
的matcher
,这样相当于变相的清除了动态注入的路由。优点
- 解决了上面刷新页面的问题。
- 缺点
- 官方没有提过使用该方法,所以可能会存在一定的问题,但是我发现
element-ui-admin
中也是使用的这个方法来实现路由清除,所以目前应该是不会有太大的问题。版本更新后就不一定了,也许后续官方就会推出清除路由的api。
附代码:
1 | //router.js |