vue-router之解决addRoutes使用遇到的坑
作者:weixin_34179968 发布时间:2024-04-30 10:19:26
最近项目中使用了vue-router的addRoutes这个api,遇到了一个小坑,记录总结一下。
场景复现:
做前端开发的同学,大多都遇到过这种需求:页面菜单根据用户权限动态生成,一个常见的解决方案是:
前端初始化的时候,只挂载不需要权限路由,如登陆,注册等页面路由,然后等用户登录之后,后端返回当前用户的权限表,前端根据这个权限表遍历前端路由表,动态生成用户权限路由,然后使用vue-router提供的addRoutes,将权限路由表动态添加到路由实例中,整个过程大致如下:
// router.js 文件
// 需要用户权限的路由表
const appRoutes = [
{
path: '/dashboard',
name: 'dashboard',
component: () => import('...'),
children: [
RouteConfig1,
RouteConfig2,
...
]
},
RouteConfig,
...
];
// 不需要用户权限的路由表
const constantRoutes = [
{
path: '/login',
name: 'login',
component: Login
},
{
path: '/register',
name: 'register',
component: Register
},
...
]
// 初始化路由的时候,只挂载不需要用户权限的路由表
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
constantRoutes
});
/**
*
* 假如后端返回的数据格式如下:
*
* {
* status: 200,
* message: 'successful',
* data: {
* user: {...},
* token: '...',
* permisssion: [...]
* }
* }
*
* login.vue
*/
axios.post('/user/login',{username,password})
.then(res => {
if (res.status === 200) {
// 如果登录成功,则需要遍历生成用户权限路由
// filterRoutes根据permission和router.js中定义的appRoutes生成动态路由表
const routes = filterRoutes(permission);
// 然后使用addRoutes将routes挂载到router中
router.addRoutes(routes);
} else {
...
}
})
.catch(error => { ... })
写到这里,貌似动态生成路由的功能就好了,一切都perfect了,但问题紧接着就来了,当用户登录之后,我们点击页面上的退出按钮退出当前登录,然后重新登录,会发现浏览器console面板紧接着就报如下错误:
纳尼(⊙o⊙)?这是怎么回事呢,第二次登录也正常登录了,功能上似乎没有什么问题,但这个警告从哪里来的呢?对于一个重度强迫症患者来说,任何警告和报错都是不允许出现的,哪怕功能上没什么问题。
捋一捋
这段警告的意思是说,以上的这几个路由命名重复,存在多个name相同的路由。那么为什么会有多个路由名称相同的路由呢?
让我们从头捋一下这个错误是怎么来的。首先第一次打开网站登录的时候是没有问题的,只有当我们退出登录,重新登录的时候,这段警告就来了。并且如果我们在重复登录之前刷新一下浏览器然后再登录,这种警告就不会出现了,很神奇是不是?
分析一下上面的情景:首先这个警告只会在用户重新登录的时候出现,登录的时候我们做的唯一跟路由相关的事情就是动态添加路由,所以问题肯定出在 router.addRoutes(routes)这里,其次这里又分了两种情况:有刷新和无刷新。在无刷新的情况下会报这个警告,有刷新就不会报这个警告。那么有刷新和无刷新有什么区别呢?
我们很容易就想到,当页面刷新的时候,Vue实例会重新初始化,Vue实例初始化的过程中,挂载在它上面的Vue-Router,Store等内容也会重新初始化。而在不刷新的情况下,就不会重新初始化。
再想想,我们第一次登录之后,通过addRoutes添加了权限路由routes到router上,假设我们这个权限routes中包括了dashboard,user,role三个路由,那么当我们退出登录,然后重新登录的时候,由于同一个用户登录,后端返回的权限列表是一样的,生成的动态路由routes也是一样的(即里面同样包含了dashboard,user,role三个路由),那么此时再次添加这三个路由就导致router中挂载的routes重复。而在刷新的情况下,由于router重新初始化,只包含了初始化我们添加的不需要权限的路由,此时再次登录,重新添加就不存在路由重复的问题了。
通过以上的分析,我们搞清了问题的来源,那么如何解决呢,很遗憾,vue-router并没有删除路由的api。根据以上的分析,我们很容易想到,通过强制刷新页面的方式来重置router:即当用户退出登录的时候,通过js强制刷新一下页面。就可以解决问题。这种方式虽然可以解决问题,但显得不是很优雅,而且刷新页面导致资源重新加载和页面闪烁,体验也不是特别好。因此有没有在不刷新的情况下解决问题的办法呢?
经过一番搜索,终于找到了一种方法,即重置当前router的match属性:
router.js
// 定义一个函数来创建router
export const createRouter = routes => new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
});
// 在使用addRoutes的地方
// 重置当前router的match = 初始router.match
router.match = createRouter(constantRoutes).match;
router.addRoutes(routes);
这样就可以完美解决问题了。
总结:
整个解决的过程还是比较痛苦的,因为实际中我的代码是比较复杂的,并不像上面简化后那么简单。
整个addRoutes是在store.dispatch中完成,并且中间还夹杂着生成动态路由,根据动态路由再生成用户菜单等一系列功能,干扰比较大,并且这个是源码报警,不好定位,只能通过console和浏览器调试,一步步缩小报错范围,最终找到问题原因。
然后再通过google,以及搜索vue-router仓库的issue一步步找到解决方法。
所以想说,如果大家开发中遇到一些第三方依赖的问题,可以去搜索官方仓库的issue,很好用的,很多问题其实issue中都有答案。我是屡试不爽。
最后,一定要用google,百度,浪费我好长时间,啥都没找到~
来源:https://blog.csdn.net/weixin_34179968/article/details/91366145
猜你喜欢
- 将转储设备加入到SQL Server备份数据库的地方。在SEM中转储设备是可见性的,并且在设备上的信息被存储在主要数据库的sysdevice
- 在进行单个爬虫抓取的时候,我们不可能按照一次抓取一个url的方式进行网页抓取,这样效率低,也浪费了cpu的资源。目前python上面进行并发
- 本文实例为大家分享了python sort、sort_index的具体代码,供大家参考,具体内容如下对Series进行排序#生成序列objo
- 本文实例讲述了Python自定义装饰器原理与用法。分享给大家供大家参考,具体如下:什么是装饰器?装饰器本质是一个函数,它可以在不改变原来的函
- 前言对于pprof,相信熟悉go语言的程序员基本都不陌生,一般线上的问题都是靠它可以快速定位。但是实际项目中,很多时候我们为了性能都不会开启
- TensorFlow里面的padding只有两个选项也就是valid和samepytorch里面的padding么有这两个选项,它是数字0,
- 前言本文主要个大家介绍了关于Python上下文管理器与else块的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。
- 介绍今天有个不正经的需求,就是要快速做一个restful api的性能测试,要求测试在海量作业数据的情况下客户端分页获取所有作业的性能。因为
- 1.什么是property简单地说就是一个类里面的方法一旦被@property装饰,就可以像调用属性一样地去调用这个方法,它能够简化调用者获
- 二、XML的定义 XML是一个精简的SGML,它将SGML的丰富功能与HTML的易用性结合到Web的应用中。XML保留了SGML的可扩展功能
- python将字符串转换成数组的方法。分享给大家供大家参考。具体实现方法如下:#------------------------------
- 背景:大约有3K家商家需要重新确认信息并签订合同。合同是统一的Word版本。每个供应商需要修改合同内的金额部分。人工处理方式需要每个复制粘贴
- sync.WaitGroup对于Golang开发者来说并不陌生,其经常作为多协程之间同步的一种机制。用好它势必会让你事半功倍,但是一旦错用将
- 本文实例讲述了django框架基于queryset和双下划线的跨表查询操作。分享给大家供大家参考,具体如下:前面篇随笔写的是基于对象的跨表查
- 1、搭载QT环境按win+R输入 pip install pyqt5 下载QT5 当然也可以去Qt的官网的下载 ,使用命令行更快捷方便 所以
- 数据库连接:<% set conn=server.createobject("adodb.connection&q
- Python跑循环时内存泄露今天在用Tensorflow跑回归做测试时,仅仅需要循环四千多次 (补充说一句,我在个人PC上跑的)。运行以后,
- 1、问题描述在使用v-model指令实现输入框数据双向绑定,输入值时对应的这个变量的值也随着变化;但是这里不允许使用v-model,需要写一
- git 报错信息:OpenSSL SSL_read: Connection was reset, errno 10054Git 中 push
- 安装保证你的用户有权限 安装 没有 切换 rootsu root (su的意思:swich user)# rpm -ivh http://d