前言
下班前,20 分钟,发一篇。。。简单介绍,使用 keep-alive 的时候,返回前一页,没有保持滚动条位置。事实上,就算不使用 keep-alive,位置也没有被记录。但是,在不适用 keep-alive 的时候,页面内容会刷新,所以就随他去了……就是这么任性……
思路
官方有推荐一个 scrollBehavior,链接,但是上面标注,只在 history.pushState 的浏览器生效,不知道是不是只能开启 history.pushState 才可以使用,看了下实现,挺不友好的,还是自己搞一个吧。。。
实现思路是这样的,首先给路由增加一个对象 meta:
meta: {
keepAlive: true,
scrollTop: 0,
}
keepAlive 是否需要保持页面,scrollTop 记录页面的滚动位置。然后在 app.vue 增加如下入口:
<keep-alive>
<router-view v-if=”$route.meta.keepAlive”></router-view>
</keep-alive>
<router-view v-if=”!$route.meta.keepAlive”></router-view>
这样就启用 keep-alive 了。然后在全局 main.ts 增加一个全局路由控制:
router.beforeEach((to: Route, from: Route, next: () => void) => {
if (from.meta.keepAlive) {
const $content = document.querySelector(‘#content’);
const scrollTop = $content ? $content.scrollTop : 0;
from.meta.scrollTop = scrollTop;
}
next();
});
很简单,离开的时候判断当前页是否需要保持页面,如果需要,记录页面主容器 content 的滚动位置,写入路由。然后,每次进入保持好的页面,读取滚动条位置 scrollTop,修改主容器的 scrollTop,就搞定了:
public activated() {
const scrollTop = this.$route.meta.scrollTop;
const $content = document.querySelector(‘#content’);
if (scrollTop && $content) {
$content.scrollTop = scrollTop;
}
}
看起来很简单哦。
遗留问题
1、是不是每个页面都可以记录滚动条位置呢?
其实不是的,有的页面,内部有 js 交互,比如 tab 交互,不同的 tab,页面可滚动的高度不一致,如果不保持页面状态而统一记录滚动位置,有可能导致滚动条的位置错位。
2、能不能把 activated 这一步写到全局的 main.ts 或者 state 去呢?
有想过这点,但是目前来说,没找到实现的方法。
首先,如果通过 router 来控制,做不到,全局路由控制只能在页面加载前监听,取不到载入页的元素。
如果写在一个通用的全局函数去控制,比如定义一个 state,当页面加载完的时候设置,那需要定义一个 mixins 来处理,但是对这个 mixins 不太熟悉,暂时还不知道该怎么做,可能有时间找个方法搞定它。
没有啦……