Vue-router 报NavigationDuplicated的可能解决方案
出现这个问题,控制台会报 [NavigationDuplicated {_name: "NavigationDuplicated", name: "NavigationDuplicated"}]
。其原因在于 Vue-router 在 3.1 之后把$router.push()
方法改为了 Promise。所以假如没有回调函数,错误信息就会交给全局的路由错误处理,因此就会报上述的错误。
如果你仔细观察并复现了多次错误你会发现,vue-router 是先报了一个Uncaught (in promise)
的错误 (因为 push 没加回调),然后再点击路由的时候才会触发NavigationDuplicated
的错误 (路由出现的错误,全局错误处理打印了出来)。
解决方案
方案 1
固定 vue-router 版本到 3.0.7 以下。这个方案没什么说的,就是简单粗暴,没有任何理由。但是你能确保以后不升级 vue-router 吗?
方案 2
禁止全局路由错误处理打印,这个也是 vue-router 开发者给出的解决方案:
import Router from 'vue-router'
const originalPush = Router.prototype.push
Router.prototype.push = function push(location, onResolve, onReject) {
if (onResolve || onReject) return originalPush.call(this, location, onResolve, onReject)
return originalPush.call(this, location).catch(err => err)
}
把这段代码放在引入 vue-router 之后就行,一般在 main.js 里,如果你的路由单独抽取出来了,那可能在其他的路由文件中。
方案 3(高成本高收益)
vue-router 的开发者也给出了解决方法,你需要为每个 router.push 增加回调函数。
router.push('/location').catch(err => {err})
对于我们来说这个解决方案的成本可能很高,但是是值得的。在 vue-router 3.1 版本之前的 push 调用时不会返回任何信息,假如 push 之后路由出现了问题也不会有任何的错误信息。如果你使用方案 1 固定了 vue-router 的版本,那么以后的项目需要路由的回调时你根本无从下手。
方案 4
如果你使用了 Element-UI,并且方案 2 无法解决你的问题。那么你只能用方案 1 来固定你的 vue-router 版本了。这是因为 Element-UI 的el-menu
在重复点击路由的时候报的错误,而且这个错误是 Element-UI 内部的路由问题,你无法通过方案 2 和 3 去解决。只能选择暂时不升级 Vue-router。
好消息是 Element-UI 已经有了解决方案,预计在 2.13.0 版本会解决这个问题。参考 Github 上 issue#17269。
参考文章
No stacktrace on NavigationDuplicated error #2881
[Bug Report] 升级 vue-router 至 3.1 以后版本,导航组件重复点击报错 NavigationDuplicated #17044
Menu: fix router NavigationDuplicated error when using vue-router@^3.1.0 #17269