问题描述:重复点击导航时,控制台出现报错 ,虽然不影响功能使用,但也不能坐视不管。

解决 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的上下文。

问题解决。

Logo

基于 Vue 的企业级 UI 组件库和中后台系统解决方案,为数万开发者服务。

更多推荐