1. 程式人生 > 其它 >Vue Router 常見問題(push報錯、push重複路由重新整理)

Vue Router 常見問題(push報錯、push重複路由重新整理)

Vue Router 常見問題

用於記錄工作遇到的Vue Router bug及常用方案

router.push報錯,Avoided redundant navigation to current location: “/xxx”


大意為 路由頻繁點選導致路由重複,該報錯對路由跳轉功能沒有任何影響

解決方案:重寫push方法

將異常捕獲就不會報錯了

let routerPush = VueRouter.prototype.push;
VueRouter.prototype.push = function push(location) {
  return routerPush.call(this, location).catch(err => err)
}

重複點選路由 重新整理頁面效果

在重寫VueRouter.prototype.push方法時,利用VueRouter的currentRoute物件中的fullpath屬性與push函式的引數對比,判斷是否為同一路由。如果是,使用一下方法完成頁面重新整理

方法一:window.location.reload()

問題在於會重新整理整個頁面,不是很推薦

let routerPush = VueRouter.prototype.push;
VueRouter.prototype.push = function push(location) {

  let history = this.currentRoute && this.currentRoute.fullPath;
  if (location === history) {
    window.location.reload(); //整個頁面都重新整理
  }
  return routerPush.call(this, location).catch(err => err)
}

方法二:v-if 控制router-view實現區域性重新整理

較為複雜,但是能夠實現區域性重新整理

由於VueRouter.prototype.push中的this指向VueRouter例項
該例項中存在 "全域性Vue例項"(main.js new Vue()生成的) 的引用屬性 "app"(this.app)

於是,push函式裡面就可以操作Vue例項了。

實現思維:

  vue例項使用provide注入一個 getRouterAlive 方法,返回當前vue例項中定義的狀態變數 isRouterAlive
    再定義一個 reloadChild 方法,修改狀態變數 isRouterAlive的值為false,dom更新後再改為true

  需要區域性重新整理的地方 inject 接受 getRouterAlive 這個方法,再在router-view 上繫結
    v-if="Object.prototype.toString.call(getRouterAlive) == '[object Function]' && getRouterAlive()"

實現程式碼:
main.js

// main.js

new Vue({
  router,
  store,
  render: h => h(App),
  provide() {
    return {
      getRouterAlive: this.getRouterAlive,
    }
  },
  data: {
    isRouterAlive: true
  },
  methods: {
    getRouterAlive() {
      return this.isRouterAlive;
    },
    reloadChild() {
      this.isRouterAlive = false;

      this.$nextTick(() => {
        this.isRouterAlive = true;
      })
    }
  }
}).$mount('#app')

router.js

// router/index.js
let routerPush = VueRouter.prototype.push;
VueRouter.prototype.push = function push(location) {

  let history = this.currentRoute && this.currentRoute.fullPath;
  if (location === history) {
    this.app.reloadChild && this.app.reloadChild();
  }
  return routerPush.call(this, location).catch(err => err)
}

區域性重新整理

// 區域性重新整理
...
<router-view v-if="Object.prototype.toString.call(getRouterAlive) == '[object Function]' && getRouterAlive()"></router-view>
...

inject: ["getRouterAlive"],
...