Vue Router 常見問題(push報錯、push重複路由重新整理)
阿新 • • 發佈:2021-10-20
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"],
...