vue-router重复路由跳转报错:Uncaught (in promise) NavigationDuplicated: Avoided redundant navigation to cu...

今天偶然发现在使用vue-router实现路由跳转时,同一个地方点了两次,发现控制台报错了

NavigationDuplicated: Avoided redundant navigation to current location
避免了对当前位置的冗余导航,就是重复跳转了

在百度上查了一下,大部分都只是对push方法进行重写,但是感觉都略显不足,后来在github上找到了一个大神写的,在路由的index文件引入router之后写入以下程序,并附上我的注释,如果注释有误,欢迎大家指正!!

// 缓存原本的push方法
const originalPush = VueRouter.prototype.push
const originalReplace = VueRouter.prototype.replace

// 指定新的push方法
VueRouter.prototype.push = function push(location, onResolve, onReject) {
  // 如果指定了成功或者失败的回调
  if (onResolve || onReject) {
    // 直接调用原本的push方法
    /**
     * 不能直接调用,因为打包成为严格模式下this不是router而是undefined
     */
    // originalPush(location, onResolve, onReject)
    return originalPush.call(this, location, onResolve, onReject)
  }
  // 没有指定成功或者失败的回调,要用catch处理
  return originalPush.call(this, location).catch((err) => {
    // 如果是重复导航产生的错误,不再向外传递错误
    if (VueRouter.isNavigationFailure(err)) {
      // 产生的是成功的promise,成功的promise的value是err
      // 产生失败的promise:抛出错误或者return一个失败的promise
      return err
    }
    
    // 如果不是重复导航的错误,将错误向下传递
    return Promise.reject(err)
  })
}

VueRouter.prototype.replace = function (location, onResolve, onReject) {
  if (onResolve || onReject) {
    return originalReplace.call(this, location, onResolve, onReject)
  }
  return originalReplace.call(this, location).catch((err) => {
    if (VueRouter.isNavigationFailure(err)) {
      return err
    }
    return Promise.reject(err)
  })
}

这个方法的好处是同时重写了push和replace方法,因为单单重写push是不够的,当然如果你的项目只用到了一个,那就可以重写一个方法。

以push方法为例

  • 回调函数的写法
router.push(location, onComplete?, onAbort?)
// onComplete 成功回调
// onAbort 失败的回调
该方法不会返回promise
  • 返回promise
router.push(location)
    .then(onComplete)
    .catch(OnAbout)

之所以报错,就是因为我们没有对异常进行捕获也没有传入的成功的回调,所以这里有两种方法也可以解决:

  • 传入成功回调
router.push(location, () => {})
  • 利用promise捕获错误
this.$router.push(locatiion).catch(() => {});

所以第一种方法就会判断你是否传入了回调,如果你传入了回调,那么就是用本来的push方法

...
 if (onResolve || onReject) {
    return originalPush.call(this, location, onResolve, onReject)
  }
...

通过添加回调的方法虽然也可以解决问题,但是如果回调没有函数体,就显得程序不优雅,综上还是重写push和replace方法比较周全

你可能感兴趣的:(vue-router重复路由跳转报错:Uncaught (in promise) NavigationDuplicated: Avoided redundant navigation to cu...)