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"],
...