Vue重写push方法(NavigationDuplicated报错)

一、场景

在点击侧边栏进行路由跳转的时候,如果再次点击本身所处的侧边栏选项,控制台就会报错,用的是编程式导航,如下图所示:

Vue重写push方法(NavigationDuplicated报错)_第1张图片

二、报错原因

vue-router 在 3.1 版本之后把 this.$router.replace() 方法改为了 Promise,没有回调函数时错误信息就会由全局显示

vue-router中重写了push方法,源码如下:

push (location: RawLocation, onComplete?: Function, onAbort?: Function) {
  // $flow-disable-line
  if (!onComplete && !onAbort && typeof Promise !== 'undefined') {
    return new Promise((resolve, reject) => {
      this.history.push(location, resolve, reject)
    })
  } else {
    this.history.push(location, onComplete, onAbort)
  }
}
let res = that.$router.push(info.path);
console.log(res);

Vue重写push方法(NavigationDuplicated报错)_第2张图片

三、解决方法

1、给push方法传递相应的成功与失败的函数
let res = that.$router.push(info.path,() => {},() => {});
console.log(res);

缺陷:只要使用到了push方法就要加回调函数,比较麻烦

2、重写VueRouter原型对象上的push方法

通过VueComponent上的原型可以找到$router,它是在入口文件注册路由的时候通过Vue.use(VueRouter)出来的实例,如下图所示:

Vue重写push方法(NavigationDuplicated报错)_第3张图片

在VueRouter原型对象上可以找到找到push方法,如下图所示:

Vue重写push方法(NavigationDuplicated报错)_第4张图片

对原型方法push进行修改,修改结果就会作用于组件实例的$router实例

1、先把VueRouter原型对象的push方法备份

const originalPush = VueRouter.prototype.push

注意:此时originalPush的this是指向window

2、重写push方法

VueRouter.prototype.push = function(location,resolve,reject){
	// 如果成功和失败的回调都传了,则调用原来的push方法,即originalPush
	// 但是此时的originalPush的上下文this是window,而要求push方法的this指向VueRouter的实例,所以用call来改变this指向
    if(resolve && reject){
        originalPush.call(this,location,resolve,reject)
    }else{
   		// 如果没有传回调,默认加上两个空的,返回undefined
        originalPush.call(this,location,()=>{},()=>{})
    }
}

解析:

function(location,resolve,reject) { }
参数:location:原来的push方法往哪里跳;resolve:成功的回调;reject:失败的回调

也可以通过catch()捕获异常来省去判断(常用)

//通过catch不用判断
 VueRouter.prototype.push = function push(location) {
   return originalPush.call(this, location).catch(err => err)
 }

你可能感兴趣的:(vue,vue.js,javascript,前端)