Vue router FAQ
It is used to record Vue router bugs and common solutions encountered in work
Router.push reports an error, avoided redundant navigation to current location: “/xxx”
The main idea is that frequent route clicks lead to repeated routes. This error has no impact on the route jump function
Solution: override the push method
If you capture the exception, you will not report an error
let routerPush = VueRouter.prototype.push;
VueRouter.prototype.push = function push(location) {
return routerPush.call(this, location).catch(err => err)
}
Click the route repeatedly to refresh the page effect
When rewriting the vuerouter.prototype.push method, compare the fullpath attribute in the currentroute object of vuerouter with the parameters of the push function to judge whether it is the same route. If yes, use the following method to complete the page refresh
Method 1: window. Location. Reload()
The problem is that it will refresh the whole page, which is not recommended
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)
}
Method 2: V-IF controls router view to realize local refresh
More complex, but can achieve local refresh
Since this in VueRouter.prototype.push points to the VueRouter instance
The reference property "app" (this.app) of the "global Vue instance" (generated by main.js new Vue()) exists in that instance
So, the push function can manipulate the Vue instance inside.
Realize thinking:
The vue instance uses provide to inject a getRouterAlive method, which returns the state variable isRouterAlive defined in the current vue instance.
Then define a reloadChild method to change the state variable isRouterAlive to false, and then change it to true after the dom update
Where a local refresh is needed, inject accepts the method getRouterAlive and binds it to the router-view
v-if="Object.prototype.toString.call(getRouterAlive) == '[object Function]' && getRouterAlive()"
Implementation code:
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)
}
Local refresh
...
<router-view v-if="Object.prototype.toString.call(getRouterAlive) == '[object Function]' && getRouterAlive()"></router-view>
...
inject: ["getRouterAlive"],
...