一、发现问题
当我在完成模仿网易云项目中的MV模块时, 不同的MV都是用到MV详情组件,只是根据不同MV的id,路由不同,组件中渲染的内容不同而已。
当我在一个MV的详情页面,通过里面的相关推荐去到另一个MV中时。
正常来讲应该是当前我的路由是/mv/details?id=123456,点击另一个MV则路由变为/mv/details?id=654321,此时页面应该要刷新,页面内容从id为123456的MV变成关于id为654321MV的内容。
但是呢,只有路由改变没有组件数据没有更新,还是旧的MV信息。
二、原因
vue官网详细解释说明使用同一路由携带不同参数,本质上是重用相同的组件实例,默认在跳转路由时会采用缓存策略,并不会刷新当前路由组件,因此不会调用组件的生命周期挂钩。
三、解决问题
由于我这个渲染MV详情的组件是一个子组件,所以一开始我查解决方法的时候使用的是。
provide和inject结合使用,利用v-if原理重载路由
通过v-if 对进行摧毁和重建,强行使页面进行重新渲染
1、父组件
<template>
<div>
<router-view v-if="isRouterAlive" ></router-view>
</div>
</template>
<script>
export default{
//父组件暴露出来的一些方法属性之类
provide () {
return {
//把父组件的reload方法暴露出来
reload: this.reload
}
},
data(){
return{
isRouterAlive: true
}
},
methods:{
//这是要暴露给子组件的方法,用来刷新子组件
reload () {
this.isRouterAlive = false
this.$nextTick(() => (this.isRouterAlive = true))
}
}
}
</script>
2、子组件
//接收父组件暴露出来的reload方法
inject: ['reload'],
methods:{
...
//这是从当前mv去其他mv调用的函数,传递了要去mv的id,这样才能定义路由嘛
toOtherMV(id){
this.$router.push(`/mv/detail?id=${id}`)
//在刷新一下组件
this.reload()
}
}
是不是很完美?你以为这就完事了嘛?
这样确实可以解决上面的问题,但是呢,当你点击左上角返回箭头从id为654321的MV详情回来id为123456的MV时候,组件还是不会刷新。只能说上面只是完成了前进的部分。
那么后退该怎么办呢?
简单,在子组件中监听路由的变化当路由变化则刷新组件,在toOtherMV函数中只要修改路由就好了。
子组件
watch: {
// 监听路由变化
$route (to, from) {
// 组件刷新
this.reload()
}
},
//接收父组件暴露出来的reload方法
inject: ['reload'],
methods:{
...
//这是从当前mv去其他mv调用的函数,传递了要去mv的id,这样才能定义路由嘛
toOtherMV(id){
this.$router.push(`/mv/detail?id=${id}`)
}
}
当当当!这样就解决了,跳转同一路由但是参数不同,组件不刷新的问题!