主要遇到的问题:
1、根据权限生成的路由调用 router.addRoutes() 无法正常显示问题
2、无法动态生成路由组件(component)问题
3、路由刷新失效问题
第一个问题解决方案,增加如下代码:(参考博客:https://blog.youkuaiyun.com/u013465194/article/details/86175227)
// 主要增加这行代码
router.options.routes = routes
// 动态添加可访问路由表
router.addRoutes(routes)
next({ ...to, replace: true })
第二个问题:
这个方案会出现异常,原因大致是import不允许传入变量:
// userAuth.component 是获取权限菜单,返回的路由组件配置,主要就是一个地址如:@/views/home/index
// __router 是本人自定义的一个路由对象(根据权限动态生成)
__router.component = () => import(userAuth.component)
后来折腾了一下,试试拼接的方法,成功解决异常问题:
// userAuth.component 是获取权限菜单,返回的路由组件配置,主要就是一个地址如:home/index
// __router 是本人自定义的一个路由对象(根据权限动态生成)
__router.component = () => import(`@/views/${userAuth.component}`)
第三个问题:
这个问题折腾的比较久
最初的方案是将生成好的路由,转换成JSON保存到 sessionStorage,然后放到store里面。最后从store里面取出,调用router.addRoutes() 方法,但这个时候却报错了:
组件(component)没有成功保存到sessionStorage,后来尝试过修改写法,可以成功保存到sessionStorage:
// 原写法:
__router.component = () => import(`@/views/${userAuth.component}`)
// 修改为:
import Home from '@/views/home/index'
__router.component = Home
// 以上改法只为说明问题,勿用
// 改为这种写法可以转换成JSON,保存到sessionStorage;但在转回路由表的过程中,依然会报错
这里猜测可能是JSON.parse 转换的时候,出了点问题;也就是不能将整个路由表转换成JSON 保存在sessionStorage中。如果看过本文的大佬,能针对路由表保存到sessionStorage中,取出后可以正常使用路由的方案,欢迎留言讨论,非常感谢🤝
针对该问题,本人没有合适的处理方案;最后只好缓存后端返回的权限列表,然后每次都根据权限列表去生成路由表,如下:
// 'user/getAuth' 后端获取权限列表的接口
await store.dispatch('user/getAuth').then(response => {
const { data } = response
if (data) {
// initRouter 这个方法就是根据权限列表生产路由的方法;因项目而异,不同的人的实现方案也可能不一样
const routes = initRouter(data)
router.options.routes = routes
// 动态添加可访问路由表
router.addRoutes(routes)
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record
}
})
这样就解决了路由表生成的问题。
最后在使用的过程中,如果不刷新界面,一切正常。刷新界面后,发现 router.options.routes 里面没有根据权限生成的动态路由,也就是没有调用router.addRoutes() 添加的路由。
针对这个问题,只需要加一个判断就好,如下:
// constantRoutes.length 是项目初始化的时候,初始化路由使用的默认路由表(自定义)。
// router.options.routes.length 是每次动路由中获取的路由表数量
// 如果每次获取的路由表数量和默认的自定义路由表数量一致,说明router.addRoutes方法添加的路由不在获取的路由表里面
if (router.options.routes.length === constantRoutes.length) {
await store.dispatch('user/getAuth').then(response => {
const { data } = response
if (data) {
const routes = initRouter(data)
router.options.routes = routes
// 动态添加可访问路由表
router.addRoutes(routes)
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record
}
})
} else {
next()
}
这样,完美的解决了刷新的问题
不过,如果在不刷新界面的情况下,退出登录,然后重新登录。router.options.routes 是存在动态添加的路由。 这个时候会直接执行 else 里面的next()。会发现登录成功后进入首页一片空白。 一定要刷新一下才会重新显示。 作为一个有强迫症的猿,肯定不允许这种情况出现。解决的方法也简单,就是重新登录后让程序执行if 里面的处理,这个就因人而异了。
本文涉及到的问题是目前遇到的主要问题,还有很多小问题,相信有经验的前端都能解决。给出的参考方案可能需要开发人员有一定的前端基础。 本文主要提供的是解决问题的思路,如果各位大神有更好的方案,或对本文有异议,欢迎留言一起交流。🤝
本文参考链接:https://blog.youkuaiyun.com/u013465194/article/details/86175227