[Vue]VueRouter点击同一导航报错

1.说明

编程式路由导航当中,如果重复点击一个链接[路由导航],那么就会抛出一个NavigationDuplicated异常,该异常并不会影响我们的程序执行。

  • 在声明式路由导航中,不会出现这种情况。
  • 这种情况只会在vue-router@3.1.0+版本出现,因为它引入了primise。
  • 目前@3.1.1版本,官方已经修复了此问题。

2.为什么会出现这样的错误

router.push(location, onComplete?, onAbort?)
router.replace(location, onComplete?, onAbort?)

以上是路由跳转的两个函数,注意看它的第二个和第三个参数,在官方文档中是这么写的:

  • 当导航跳转成功完成之后,会执行onComplete回调,它相当于resolve。

  • 导航到相同的路由,或者此次路由未导航成功之前,又导航到其他路由时就会执行onAbort回调,它相当于reject。

  • @3.1.0+后,可以省略这两个参数,如果忽略了,那么就会返回一个Promise。

    • 如果填写了这两个参数,返回的就是undefined。
  • 那么,当没有传递第二个和第三个参数时,并且点击的是同一个导航,就会返回reject。

    • 当返回reject后,我们并未捕获这个错误,然后控制台就会报红。

解决办法【3.3为最优方法】

3.0:

降级处理,使用#3.1.1版本。

3.1:

在调用方法时,传递上第二个和第三个参数。

this.$router.push("/search", ()=>{}, ()=>{});

3.2:

在push后链式调用catch()方法,捕获错误。

  • 注意:
    • 不能使用try…catch的形式去捕获,这种捕获方式只能捕获同步方法的错误。
this.$router.push("/search")
    .catch((err)=>{});

3.3:

对push和replace方法进行二次封装,在router->index.js中封装即可。

// 保存一份原有的方法
let originPush = VueRouter.prototype.push;
let originReplace = VueRouter.prototype.replace;

// 修改原型上的函数内容,如果传递了resolve和reject则使用传递的,否则默认处理内容为空
// 在调用原有的push时[相当于调用上面保存的那一份],应该让VueRouter实例调用,应该修改上下文。
VueRouter.prototype.push = function(location, resolve, reject){
    if(resolve && reject){
        originPush.call(this, resolve, reject)
    }else{
        originPush.call(this, location, (res)=>{}, (err)=>{});
    }
}

VueRouter.prototype.replace = function(location, resolve, reject){
    if(resolve && reject){
        originReplace.call(this, resolve, reject)
    }else{
        originReplace.call(this, location, (res)=>{}, (err)=>{});
    }
}
发表评论 / Comment

用心评论~