🔧 场景问题:
在一个典型的移动端(H5)应用中,用户从 列表页(如商品列表)点击进入 详情页,然后点击返回时,发现:
列表 恢复到第一页
滚动位置丢失
加载状态被重置
用户体验较差
✅ 目标:
返回列表页后 保留原有的数据和状态
恢复滚动位置
支持继续滚动加载下一页
✅ 解决方案
1. 使用 <keep-alive>
缓存组件状态
Vue 提供 <keep-alive>
用于缓存被包裹的组件实例,防止其在切换时被销毁。
<template>
<router-view v-slot="{ Component }">
<keep-alive>
<component :is="Component" v-if="$route.name === 'List'" />
</keep-alive>
<component :is="Component" v-if="$route.name !== 'List'" />
</router-view>
</template>
📌 说明:
只有
List
页面会被缓存,其他页面如Detail
不缓存。返回
List
页面时,不会重新加载数据,也不会重新挂载组件。
2. 监听激活与取消激活的生命周期
使用 onActivated
和 onDeactivated
来处理滚动监听器等副作用:
import { onActivated, onDeactivated } from 'vue'
onActivated(() => {
// 重新绑定滚动监听
})
onDeactivated(() => {
// 解绑监听器,防止重复
})
3. 列表容器使用局部滚动(而不是全页面滚动)
设置一个固定高度的列表容器,使用 overflow-y: auto
,更容易控制滚动行为:
<div ref="scrollContainer" style="height: 400px; overflow-y: auto" @scroll="handleScroll">
<!-- 列表内容 -->
</div>
4. 保存并恢复滚动位置(可选扩展)
如果你使用的是全页面滚动而不是容器滚动,也可以保存滚动位置:
// 离开页面前保存
onBeforeRouteLeave(() => {
sessionStorage.setItem('scrollTop', window.scrollY)
})
// 返回页面后恢复
onMounted(() => {
window.scrollTo(0, Number(sessionStorage.getItem('scrollTop') || 0))
})
✅ 总结关键词
技术点 | 作用 |
---|---|
<keep-alive> |
缓存组件实例及其数据状态 |
onActivated |
恢复副作用,如滚动监听 |
onDeactivated |
清理副作用,防止重复绑定 |
容器滚动优化 | 可控区域滚动,便于触底检测 |
滚动位置缓存 | 保留用户阅读进度(增强体验) |