需求: 当用户的查询的列表数据过多,然后翻到很多页以后,点击查看详情,再点击返回后页面重新加载,再想看还得翻到刚才的位置,对于用户的体验不友好。
分析:
- 跳转到详情页面后页列表页需要记录滚动条滚动的位置。
- 列表页保活,不需要重新加载数据。
- 跳转回来后拿到记录的滚动条位置,为滚动条位置赋值。
具体实现
- 页面离开可以通过Vue3的生命周期中的钩子函数 onBeforeRouteLeave
// <div class="list_wrapper" ref="***panyListRef">
// 这个就是你要记录滚动位置的div的引用
const ***panyListRef = ref<any>(null);
// 记录滚动位置
const scrollTopY = ref<number>();
onBeforeRouteLeave(() => {
scrollTopY.value = ***panyListRef.value.scrollTop;
});
- 页面重新进入也同样可以通过Vue3的生命周期函数onActivated
// 页面进入给滚动条赋值上一次的滚动位置
onActivated(() => {
if (scrollTopY.value) {
fixName.value.scrollTop = scrollTopY.value;
}
});
- 页面保活可以通过 vue-router 配置 keepAlive
摘抄自Vue官网:
- 默认情况下,一个组件实例在被替换掉后会被销毁。
- 要解决这个问题,我们可以用 KeepAlive内置组件将这些动态组件包装起来
- 可以通过 include 和 exclude prop 来定制该行为
- 它会根据组件的 name 选项进行匹配,所以组件如果想要条件性地被 KeepAlive 缓存,就必须显式声明一个 name 选项
// 组件指定名字 这个名字要和路由配置的name 属性一直才会缓存该组件
defineOptions({
name: '***panyList'
});
至此,上面已经完成了需求的功能,但是代码还是如果每个页面都拷贝这么多代码进去略微有些麻烦,我们在把代码升级一下,可以使用自定义hooks 函数
import { onActivated, ref } from 'vue';
import { onBeforeRouteLeave } from 'vue-router';
export const useFixScroll = (fixName: any) => {
const scrollTopY = ref<number>();
onActivated(() => {
if (scrollTopY.value) {
fixName.value.scrollTop = scrollTopY.value;
}
});
onBeforeRouteLeave(() => {
scrollTopY.value = fixName.value.scrollTop;
});
};
在需要的地方引入hooks
// 把需要记录的滚动条的位置ref 传入到hooks 里面即可
useFixScroll(***panyListRef);