vue前进加载页面后退缓存数据记录运动位置 以及 vue destroy替代方案

831 阅读3分钟

移动端 h5页面经常会遇到 ,希望用户从当前页面往下滚动一段距离后点击进入其他页面,然后返回当前页面,用户看到的应该还是点击进去前的位置,并且不需要重新刷新数据。 vue中可以使用 keep-alive组件来使用,keep-alive组件的使用方式这里不做详细说明,具体可以看这里: vue keep-alive 组件使用方式详解

这里要解决,首先在keep-alive可用的前提下,实现 : 页面后退不刷新数据并且记住上次滚动位置

第一步:

配置页面为keep-alive页面 ,详细参考上边链接

这里有会几个问题: 1.确实再次进入页面不在刷新数据了,但如果多个入口,比如是个详情页,随着url参数的变化实际还需要刷新数据,但仅配置keep-alive会出现只有首次打开时会加载数据,当然我们可以将数据加载的方法写在active钩子函数中。

但我们这里不想让它每次进来都刷新数据,我们只需要他首次进刷新数据,返回到keep-alive的页面不刷新数据。

这样我们需要让它每次前进 进入该页面的时候都是首次进入,会调created钩子函数刷新数据,但从其他页面返回到keep-alive页面时保留上次进来时加载的数据。

实现方式如下: 1) 首先确保每次正向进入都是 新的页面/新的vue实例 ,这样每次都会调created钩子加载数据 这里提供一种方式 ,可以在 地址上追加一个routerkey参数 例如: 地址?id=XXX&routerkey='这里可 以是个时间戳但保证要唯一' 这样每次正向进入keep-alive的页面,实际都是进了不同的地址,也产生了新的vue实例,会重新走实例创建的那一套钩子函数 可以保证每次正向进入都刷新页面

2)当keep-alive页面中点击链接跳到其他页面后,再返回因为routerkey还是之前的所以还会展示之前实例的内容,但是还会有一个问题:数据没有刷新,但是页面照常重新渲染,看到的还是例如我们首次进入的内容。

但这里别忘了我们的初衷,我们是要返回时,之前滚动浏览到哪里这里依然要看到上次的位置。

这里我们需要做两个比较特别的操作

首先 当路由离开keep-alive页面时我们要记住离开前页面滚动到的 scrollTop 其次 进入 keep-alive 页面时 我们要让页面滚动到上次浏览的位置

这里我们会用到两个vue的钩子函数 beforeRouteLeave 以及 activated 首先在 beforeRouteLeave中记录离开前的滚动距离,这里直接上代码,不做额外讲解了

  beforeRouteLeave(to, from, next) {
    if (from.meta.keepAlive) {
      // 只针对 keep-alive 的页面记录滚动位置
      let $content = document.querySelector('#根容器 id'); // 列表的外层容器
      let scrollTop = $content ? $content.scrollTop : 0;
      from.meta.scrollTop = scrollTop;
    }
    next();
  },

这里将 记录的滚动距离 scrollTop 直接记录到了 路由配置中,这里实现方案在我的其他博客中有,不懂可以直接咨询。 然后 当页面进入keep-alive页面时会调用 activated 钩子函数,我们把页面滚动到上次浏览位置的操作可以放在这里实现,也是直接上代码:

activated() {
    let scrollTop = this.$route.meta.scrollTop;
    if (scrollTop && scrollTop !== 0) {
      // 初次进入页面不执行,返回页面执行
      let $content = document.querySelector('#根容器 id');
      if ($content) {
        this.$nextTick(() => {
          $content.scrollTop = scrollTop;
        })
      }
    }
  }

这个方法主要要注意的一点是 首先为了性能的优化 ,滚动距离为 0 的就不再走下面逻辑,其次滚动放在页面渲染完成 ,使用 vue的 $nextTick函数,这个函数的具体用法参考我的其他博客。

这两个方法也可以通过mixins混入的方式混入到所有页面,但这样主页性能上的问题,尽可能判断只在keep-alive页面上生效。 这样前进刷新页面,后退不刷新页面,记录上次滚动位置就实现了。

但这里还有个问题:出于性能的考虑,由于路由加上routerkey,每次访问keep-alive页面都会重新生成一个vue的实例,当浏览次数多时会造成累积了很多未销毁实例,影响页面性能 这里 vue提供了一个$destroy方法用于销毁vue实例,但这个方法存在一个严重问题,当用$destroy销毁了keep-alive页面后,销毁掉的页面永远不在会被缓存。所以这个方法并不可用,这里有替代这个方法的方案,但时间仓促,后续博客会针对讲解,请见谅。

本次内容如有不全或者疑惑的地方欢迎评论或者私信了解。