• 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 ()
        at VueRouter.push (http://localhost:8080/main.js:32147:12)
        at VueComponent.created
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    查看源码先看看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
        )
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    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))
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    而这个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
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    经过这几处代码分析和阅读,可以发现,为啥会报错 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);
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
  • 相关阅读:
    如何封装js来调用各开放平台打印组件,实现同步效果
    c#一个udp代码
    VS2019下生成dll动态库及其引入实验
    乘坐公交-(贪心算法)
    c++day7
    Photoshop 2023:重塑创意,引领数字艺术新纪元
    linux中正则匹配
    代码中统一异常如何处理,才能让代码更清晰
    GIS数据获取:气象数据免费下载网站
    JVM(3)
  • 原文地址:https://blog.csdn.net/qq_44472790/article/details/125908583