问题: 使用keep-alive标签后部分安卓机返回缓存页位置不精确问题html
解决方案:vue
<div id="app">
<keep-alive>
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>
</div>
复制代码
const router = new Router({
scrollBehavior(to, from, savedPosition) {
if (savedPosition && to.meta.keepAlive) {
return savedPosition;
}
return { x: 0, y:0 };
},
});
复制代码
【前提】:iOS设备
【步骤】: 页面A是个列表很长-->滑到页脚的时候点击跳转以后到页面B--->再返回A页面
--->屏幕会出现空白遮罩层--->手指轻触屏幕滑动--->遮罩层消失
复制代码
在接口请求成功后的回调操做完成后进行该操做,例如缓存
// fetchCourseList是一个封装好的Promise请求
fetchCourseList().then(({ data: courses }) => {
this.courses = courses;
}).then(() => {
setTimeout(() => {
window.scrollTo(0, 1);
window.scrollTo(0, 0);
});
});
复制代码
该方案的弊端: 每一个页面都须要作这样的处理,不推荐使用。bash
使用scrollBehavior中的异步滚动操做app
const router = new Router({
scrollBehavior(to, from, savedPosition) {
// keep-alive 返回缓存页面后记录浏览位置
if (savedPosition && to.meta.keepAlive) {
return savedPosition;
}
// 异步滚动操做
return new Promise((resolve) => {
setTimeout(() => {
resolve({ x: 0, y: 1 });
}, 0);
});
},
});
复制代码
该方案直接在路由进行处理,兼容每一个页面而且页面加载完后并也不会产生1px的滚动位置。异步
首先咱们要先去了解scrollBehavior函数究竟在组件的哪一个生命周期后才开始执行。这里我对组件的每一个生命周期和scrollBehavior函数进行alert,经排查结果:scrollBehavior函数在组件的生命周期mounted后beforeUpdate前执行。函数
在scrollBehavior函数中直接return{ x:0, y:100},进入页面仍在顶部。为何不会滚动到100px处?猜想:mounted中的异步请求回来的数据赋值给data中的变量a,变量a由于vue的双向绑定更新了view层而引发滚动失效?fetch
验证下以上的猜想,设置一个静态页面数据都已经在html上写死。scrollBehavior函数中直接return { x:0, y: 100},结果:进入页面都会滚动到100px处。证实:确实与异步请求回来后的操做有关系。ui
接着了解vue的mounted和beforeUpdate时期都作了些什么。mounted时期:data数据已经挂在到页面上。beforeUpdate和updated时期:当vue发现data中的数据发生了改变,会触发对应组件的从新渲染。this
根据步骤4.mounted时期发起的异步请求并不会阻碍主线程的后续操做,因此请求回调事件未触发(对data中的变量a赋值操做未执行)便继续去执行scrollBehavior函数。若是此时直接return{ x:0, y:100}。此时至关于在异步请求回调事件未执行前进行了滚动。等到滚动后异步请求回调事件开始执行,对data中的变量a被赋值,引发组件从新渲染又回到了顶部。这整个流程滚动是针对data的初始数据页进行滚动的,因此遮罩层仍会出现。
综合上述:必须使用异步滚动,利用setTimeout跳出主线程将回调事件放到队列中。因为mouted比scrollBehavior函数早执行,因此异步请求的回调事件优先进入队列,接下去才是setTimeout的回调事件。根据队列 先进先出的原理。先执行了异步请求回调事件对data中的变量a作赋值操做。此时至关于这已是个静态页面了,接着我只要执行return { x:0, y: 100 }。这样就已经触发了页面滚动到100px的效果。可是因为data数据发生改变,页面从新渲染又回到顶部。这时整个轻触滚动效果已经暗中执行完成,不会再出现遮罩层了。