情景再现:
第二次跳转到同一页面中 页面不刷新
数据刷新 但是页面不渲染
代码:
info-catalog页面
<template>
<div class="info-catalogue-index">
<div class="left-catalogue">
<el-tree :data="catalogData" :props="catalogProps" accordion @node-click="handleNodeClick"></el-tree>
</div>
<div class="right-news">
<keep-alive>
<router-view></router-view>
</keep-alive>
</div>
</div>
</template>
// 节点被点击时的回调
handleNodeClick (val, node, el){
console.log('handleNodeClick-id', node.data.treeId)
this.$router.push({
path:'/news',
query:{
treeId: node.data.treeId
}
})
}
news页面
<template>
<div class="news">{{treeId}}</div>
</template>
created (){
console.log('query-id-c', this.$route.query.treeId)
this.treeId = this.$route.query.treeId
}
原因:
vue官网详细解释说明使用同一路由携带不同参数,本质上是重用相同的组件实例,默认在跳转路由时会采用缓
存策略,并不会刷新当前路由组件,因此不会调用组件的生命周期钩子函数.
解决方法:
参考来源
方法一:监听路由变化,当有变化时刷新页面(验证过的)
watch:{
// 监听route变化 query改变时 更新id
$route (to, from){
if(this.$route.query.treeId!==this.treeId){
this.init()
}
}
}
methods:{
init (){
console.log('query-id-c', this.$route.query.treeId)
this.treeId= this.$route.query.treeId
}
}
注意:
1.该方案可以在监听方法中完成希望在vue生命周期初始化过程中的业务逻辑,加载相关的数据;可以实现页面重新
加载数据效果,但是滚动条并未重置,因此需要对滚动条进行重置处理;
2.当页面刷新后,此时会认为路由并未发生改变,虽然此时watch中的$route或者beforeRouteUpdate 路由监听均
视作无变化,但是会正常执行生命周期,因此不存在刷新出错的问题;
方法二:给路由添加唯一key
如果想强制刷新,可以在根路由上为其分配一个唯一key。采用$route.fullpath作为其唯一key。这样vue
就回认为内部路由每个都是不同的路由,在跳转时便会强制刷新组件
// layout.vue
<template>
<div class="mk-container">
<!-- <mk-header class="mk_nav_header"></mk-header> -->
<keep-alive>
<router-view class="mk_nav_content" v-if="$route.meta.keepAlive" :key="$route.fullPath"></router-view>
</keep-alive>
<router-view class="mk_nav_content" v-if="!$route.meta.keepAlive" :key="$route.fullPath"></router-view>
<!-- <mk-footer class="mk_nav_footer"></mk-footer> -->
</div>
</template>
//test.vue
methods: {
/**
* @description: 同路由携带不同参数跳转
* @param {type}
* @return:
*/
sameRouteSkip() {
this.$router.push({
path: "/mk_gsui",
query: {
id: Math.ceil(Math.random()*100)
}
});
},
}
方法三: provide和inject结合使用-利用v-if原理重载路由
思路 : 通过v-if 对进行摧毁和重建,强行使页面进行重新渲染,感谢大佬的分享的方法,哈哈!
// app.vue
<template>
<div id="app" v-if="routerAlive">
<router-view></router-view>
</div>
</template>
<script>
export default {
name: "App",
data() {
return {
routerAlive: true
};
},
provide() {
return {
routerRefresh: this.routerRefresh
};
},
created() {},
methods: {
/**
* @description: 路由销毁重建(解决跳转同一路由不刷新问题)
* @param {type}
* @return:
*/
routerRefresh() {
this.routerAlive = false;
this.$nextTick(() => {
this.routerAlive = true;
});
}
}
};
</script>
//payOrderList.vue
export default {
// import引入的组件需要注入到对象中才能使用
components: {},
inject: ["routerRefresh"], //在子组件中注入在父组件中创建的属性
data() {
// 这里存放数据
return {
activeTab: 0,
payStatus: 0,
list: []
};
},
//使用beforeRouteUpdate 导航位置监听路由变化;对路由销毁重建
beforeRouteUpdate(to, from, next) {
this.routerRefresh(); //路由销毁重建方法
next();
},
// 生命周期 - 创建完成(可以访问当前this实例)
created() {
this.$nextTick(() => {
this.onRefresh("init");
});
},
// 方法集合
methods: {
/**
* @description: 跳到交费查询界面
* @param {type}
* @return:
*/
goPaiedRecord() {
this.$router.push({
path: "/payOrderList",
query: {
payStatus: 1
}
});
},
}
};
使用beforeRouteUpdate 导航位置监听路由变化,使用从父组件注入的方法进行路由的销毁重建,完美解决这个问题!