vue-router中scrollBehavior的妙用--使用keep-alive标签后返回页面指定位置

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);
    });
  },
});

这里为什么不能直接return而必须使用异步滚动操作呢?以下是个人的一些见解欢迎大家来探讨指正。

  1. 首先我们要先去了解scrollBehavior函数究竟在组件的哪个生命周期后才开始执行。这里我对组件的每个生命周期和scrollBehavior函数进行alert,经排查结果:scrollBehavior函数在组件的生命周期mounted后beforeUpdate前执行。

  2. 在scrollBehavior函数中直接return{ x:0,
    y:100},进入页面仍在顶部。为什么不会滚动到100px处?猜测:mounted中的异步请求回来的数据赋值给data中的变量a,变量a因为vue的双向绑定更新了view层而引起滚动失效?

  3. 验证下以上的猜测,设置一个静态页面数据都已经在html上写死。scrollBehavior函数中直接return { x:0, y:
    100},结果:进入页面都会滚动到100px处。证明:确实与异步请求回来后的操作有关系。

  4. 接着了解vue的mounted和beforeUpdate时期都做了些什么。mounted时期:data数据已经挂在到页面上。beforeUpdate和updated时期:当vue发现data中的数据发生了改变,会触发对应组件的重新渲染。

  5. 根据步骤4.mounted时期发起的异步请求并不会阻碍主线程的后续操作,所以请求回调事件未触发(对data中的变量a赋值操作未执行)便继续去执行scrollBehavior函数。如果此时直接return{
    x:0,
    y:100}。此时相当于在异步请求回调事件未执行前进行了滚动。等到滚动后异步请求回调事件开始执行,对data中的变量a被赋值,引起组件重新渲染又回到了顶部。这整个流程滚动是针对data的初始数据页进行滚动的,所以遮罩层仍会出现。

  6. 综合上述:必须使用异步滚动,利用setTimeout跳出主线程将回调事件放到队列中。由于mouted比scrollBehavior函数早执行,所以异步请求的回调事件优先进入队列,接下去才是setTimeout的回调事件。根据队列
    先进先出的原理。先执行了异步请求回调事件对data中的变量a做赋值操作。此时相当于这已经是个静态页面了,接着我只要执行return {
    x:0, y: 100
    }。这样就已经触发了页面滚动到100px的效果。但是由于data数据发生改变,页面重新渲染又回到顶部。这时整个轻触滚动效果已经暗中执行完成,不会再出现遮罩层了。

    https://juejin.cn/post/6844903634484854797
    https://www.cnblogs.com/jcxfighting/p/9437900.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值