问题描述:重复点击导航时,控制台出现报错 ,虽然不影响功能使用,但也不能坐视不管。
解决 Vue 重复点击相同路由,出现 Uncaught (in promise) NavigationDuplicated: Avoided redundant navigation 问题 .
报错内容:
Uncaught (in promise) NavigationDuplicated: Avoided redundant navigation to current location: "/home".
浏览器控制台 · 报错截图:
解决方案:
方案一:只需在 router 文件夹下,添加如下代码:
// src/router/index.js
Vue.use(Router)
const router = new Router({
routes
})
const VueRouterPush = Router.prototype.push
Router.prototype.push = function push (to) {
return VueRouterPush.call(this, to).catch(err => err)
}
方案二:在跳转时,判断是否跳转路由和当前路由是否一致,避免重复跳转产生问题。
toMenu (item) {
if (this.$route.path !== item.url) {
this.$router.push({ path: item.url })
}
}
方案三:使用 catch 方法捕获 router.push 异常。
this.$router.push(route).catch(err => {
console.log('输出报错',err)
})
这个异常其实对程序没有什么影响。出现这个问题是因为重复点击了相同的路由引起的:编程式导航路由跳转到当前路由,参数不变,在多次执行时会抛出Uncaught (in promise) NavigationDuplicated 异常。(声明式导航不会出现这个问题)
异常出现原因
在执行$router.push() 操作时,函数返回的是promise,这里可以在打印看一下:
var a = this.$router.push({name:"search",params:{keyword:this.keyword},query:{k:this.keyword.toUpperCase()}})
console.log(a);
这是因为promise需要传递一个成功/失败的回调,才能处理这个异常。
解决方案
第一个解决方案:给push方法传递相应的成功、失败回调函数,可以捕获当前的错误。
但是使用这种写法,在别的组件中使用push() 或replace() 中,还是会有类似的错误出现。
var a = this.$router.push({name:"search",params:{keyword:this.keyword},query:{k:this.keyword.toUpperCase()}},()=>{},()=>{});
console.log(a);
第二个解决方案(推荐):
this:当前组件的实例
this.$router:是VueRouter类的一个实例。
push:是VueRouter类的一个实例。
要重写VueRouter原型对象的push方法:在router文件夹下的index.js文件中补充以下代码:
//先把VueRouter原型对象的push保存一份
const originPush = VueRouter.prototype.push
//重写push方法
VueRouter.prototype.push = function (location,resolve,reject) {
//调用保存的push方法
//但是保存的push方法是挂载在window的方法 所以要通过call修改this的指向
if(resolve&&reject){
originPush.call(this,location,resolve,reject);
}else{
originPush.call(this,location,()=>{},()=>{});
}
}
location传的是往哪里跳转。resolve与reject是用户传的成功/失败的回调。这里注意需要用call修改originpush的上下文。
问题解决。