今天偶然发现在使用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方法比较周全