vue-router 重复跳转路径报错源码分析和解决方案

1.第一部分 通过源码分析报错原因
vue-router v3.1.0版本以后就会存在对性能优化,抛错处理。
例如使用this.$router.push(‘/list’) 重复跳转 就会报错:

overlay.js:2065 Uncaught (in promise) NavigationDuplicated: Avoided redundant navigation to current location: "/list".
    at createRouterError (http://localhost:8080/main.js:31179:15)
    at createNavigationDuplicatedError (http://localhost:8080/main.js:31149:15)
    at HTML5History.confirmTransition (http://localhost:8080/main.js:31447:18)
    at HTML5History.transitionTo (http://localhost:8080/main.js:31374:8)
    at HTML5History.push (http://localhost:8080/main.js:31720:10)
    at http://localhost:8080/main.js:32148:22
    at new Promise (<anonymous>)
    at VueRouter.push (http://localhost:8080/main.js:32147:12)
    at VueComponent.created

查看源码先看看push做了啥

push (location: RawLocation, onComplete?: Function, onAbort?: Function) {
    const { current: fromRoute } = this
    this.transitionTo(
      location,
      route => {
        pushHash(route.fullPath)
        handleScroll(this.router, route, fromRoute, false)
        onComplete && onComplete(route)
      },
      onAbort
    )
  }

push方法内部调用了transitionTo方法,而transitionTo内部又调用confirmTransition方法来优化处理重复访问同一个路由。transitionTo方法省略。直接看confirmTransition方法中源码怎么优化的。
源码src/history/base.js文件中的confirmTransition 方法中

 const abort = err => {
      // changed after adding errors with
      // https://github.com/vuejs/vue-router/pull/3047 before that change,
      // redirect and aborted navigation would produce an err == null
      if (!isNavigationFailure(err) && isError(err)) {
        if (this.errorCbs.length) {
          this.errorCbs.forEach(cb => {
            cb(err)
          })
        } else {
          if (process.env.NODE_ENV !== 'production') {
            warn(false, 'uncaught error during route navigation:')
          }
          console.error(err)
        }
      }
      onAbort && onAbort(err)
    }
	
	// 	对重复,相同路由跳转时进行判断
   const lastRouteIndex = route.matched.length - 1
    const lastCurrentIndex = current.matched.length - 1
    if (
      isSameRoute(route, current) &&
      // in the case the route map has been dynamically appended to
      lastRouteIndex === lastCurrentIndex &&
      route.matched[lastRouteIndex] === current.matched[lastCurrentIndex]
    ) {
      this.ensureURL()
      if (route.hash) {
        handleScroll(this.router, current, route, false)
      }
      // 报错处理 createNavigationDuplicatedError方法中
      return abort(createNavigationDuplicatedError(current, route))
    }

而这个createNavigationDuplicatedError方法的处理错误,源码如下:

export function createNavigationDuplicatedError (from, to) {
  const error = createRouterError(
    from,
    to,
    NavigationFailureType.duplicated,
    `Avoided redundant navigation to current location: "${from.fullPath}".`
  )
  // backwards compatible with the first introduction of Errors
  error.name = 'NavigationDuplicated'
  return error
}

经过这几处代码分析和阅读,可以发现,为啥会报错 overlay.js:2065 Uncaught (in promise) NavigationDuplicated: Avoided redundant navigation to current location: “/list”.错误了。

2.第二部分 使用prototype重写push方法 在开发如果存在报错,常规解决方案如下:
在router添加原型重新push

import Vue from 'vue'
import Router from 'vue-router'
 
 // 重写push和报错处理
const originalPush = Router.prototype.push;
Router.prototype.push = function push(location, onResolve, onReject) {
  if (onResolve || onReject) return originalPush.call(this, location, onResolve, onReject);
  return originalPush.call(this, location).catch((err) => err);
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

追逐梦想之路_随笔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值