场景:
list页面(要缓存),跳转到details页面,
需求:
1 从details页面返回后 list页面不刷新,并保持离开时的位置.
2 从其他任意页面进入list页面,正常刷新
方案:
1 使用keep-alive
包裹router-view
<div id="app">
<keep-alive>
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<!-- 这里不会被keepalive -->
<router-view v-if="!$route.meta.keepAlive"></router-view>
</div>
2 路由注册,添加meta
{
path: '/list',
name: 'List',
component: () => import('@/pages/list.vue'),
meta: {
keepAlive: true
}
},
3 list.vue
中使用beforeRouteLeave
钩子
beforeRouteLeave(to, from, next) {
if (to.name == "details") {
from.meta.keepAlive = true
} else {
from.meta.keepAlive = false
}
next()
},
4 在组件中记录scroll滑动的距离
this.scrollTop = document.querySelector( ".scroll-box" ).scrollTop
keep-alive
缓存组件重新激活时会触发activated
周期函数,在此函数中做滚动,回到跳转details.vue
前的位置
activated() {
document.querySelector(".scroll-box").scrollTop = this.scrollTop
},
问题:
list页面会由于数据的不同,重复缓存,details返回后的页面不是它的真正的上级页面
场景还原:
点击/list?id=01
下的01-item
前往01-item-details
,返回后为/list?id=01
下的页面,正常
再点击/list?id=02
下的02-item
前往02-item-details
,返回后仍为/list?id=01
下的页面,异常
原因:第二次返回list?id=02时返回的是keep-alive
已缓存的组件(即第一次缓存的list组件)
解决问题:
手动销毁已缓存的list
组件,使其每次进入list都重新缓存新的页面;
1 使用keep-alive
的exclude
属性(任何名称匹配的组件都不会被缓存)
<keep-alive :exclude="exclude" >
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
data() {
return {
exclude: this.$exclude,
}
},
2 对list.vue
中的beforeRouteLeave
钩子函数做修改
beforeRouteLeave(to, from, next) {
// 离开list页面且进入的不是details页面
if (to.name != "details") {
// exclude添加匹配后,会自动销毁已缓存的组件
this.$exclude.push(this.$options.name)
// 缓存组件销毁后要把exclude中的匹配删除,不然下次进去页面不会缓存当前组件
setTimeout(() => {
for (let i = 0; i < this.$exclude.length; i++) {
if (this.$exclude[i] == this.$options.name) {
this.$exclude.splice(i, 1)
break
}
}
}, 0)
}
next()
},