# Vue项目hash模式中记录滚动位置
由于vue-router中的scrollBehavior只在history模式中有效,需要自己实现记录滚动位置,当返回的时候,恢复原来的位置。
# 实现前提
路由组件需要被包裹,即缓存组件实例,不将其销毁。
# 基本实现
1、在每个路由页面的beforeRouteLeave记录滚动位置即scrollTop
2、当回退时,activate的生命周期中调用scrollTo方法,滚动到之前的位置。
# 优化
如果在每个路由页面写的话,代码有些冗余,因此尽量抽出公共部分,写最少的代码,方便后续维护。
# 优化实现
1、在滚动的父元素上添加指定的class(拥有不为0的scrollTop)
<div
class="keep-position-wrap"
>
<ul>
<li>...</li>
...
</ul>
</div>
2、在路由元信息添加标志位,表明该页面需要记录滚动位置
const routeMap = [{
path: '/index/merchant',
name: 'index_merchant',
meta: {
title: '商家福利',
keepPosition: true, // 表示该页面需要记录滚动位置
},
component: () => import('@/views/index/merchant'),
},
]
3、在全局的afterEach中读取滚动元素的scrollTop,并保存在from.meta中,由于组件内部可以通过this.$route获取路由信息,也就能拿到scrollTop。
router.afterEach((to, from) => {
const keepPositionWrap = document.querySelector('.keep-position-wrap');
if (from.meta && from.meta.keepPosition && keepPositionWrap) {
const { scrollTop } = keepPositionWrap;
from.meta.$scrollTop = scrollTop;
}
});
4、将activate生命周期放到mixin中,拿到scrollTop,并滚动到scrollTop。
activated() {
const keepPositionWrap = document.querySelector('.keep-position-wrap');
if (keepPositionWrap
&& this.$route
&& this.$route.meta
&& this.$route.meta.keepPosition
&& this.$route.meta.$scrollTop
) {
keepPositionWrap.scrollTo(0, this.$route.meta.$scrollTop);
}
}
对于我们项目组来说,要实现记录位置,只需要做两点:
1、在滚动的父元素上添加class:keep-position-wrap 2、在路由元信息中添加:keepPosition: true
参考:
- https://router.vuejs.org/zh/guide/advanced/scroll-behavior.html
- https://www.cnblogs.com/mmzuo-798/p/12901425.html