Vue 移动端(H5)项目怎么实现页面缓存(即列表页面进入详情返回后列表页面缓存且还原页面滚动条位置)keep-alive缓存及清除keep-alive缓存

一、需求

产品要求:Vue移动端项目进入列表页,列表页需要刷新,而从详情页返回列表页,列表页则需要缓存并且还原页面滚动条位置

二、实现思路

1、使用Vue中的keep-alive组件,keep-alive提供了路由缓存功能

2、因为我项目只是针对某几个列表页面做缓存,我就直接把指定的几个页面单独的做处理(即:把需要做缓存的页面路由的meta新增了keepAlive属性,当keepAlive为true时缓存,为false则不缓存),从而实现进入列表页,列表页需要刷新,而从详情页返回列表页,列表页则需要保持页面缓存

建议使用keep-alive includes属性来做缓存页面

三、最终效果

四、具体实现

1、app.vue文件修改

html 复制代码
<template>
  <div id="app">
    <keep-alive>
      <router-view class="Router" v-if="$route.meta.keepAlive"></router-view>
    </keep-alive>
    <router-view class="Router" v-if="!$route.meta.keepAlive"></router-view>
  </div>
</template>

2、在动态路由生成后初始化指定缓存页面路由设置metakeepAlive属性为true

3、单个列表页面的缓存处理(详情返回到列表滚动条的位置)

js 复制代码
beforeRouteLeave(to, from, next) {
    // console.log('777---', from)
    this.scroll = document.querySelector('.endInfo').scrollTop
    // 离开页面时,需要清除缓存(为了下次进入后刷新页面)
    from.meta.keepAlive = false
    next()
  },
  activated() {
   // 注意`endInfo`类是:列表box的顶级类,用来计算滚动条的距离
    document.querySelector('.endInfo').scrollTop = this.scroll
    console.log('缓存页面距离', this.scroll)
  },

4、从详情页面返回到列表,需要如下设置(关键步骤)

js 复制代码
beforeRouteLeave(to, from, next) {
    console.log('支付单详情页', to)
    // 设置下一个路由的meta,让列表页面缓存,即不刷新(即:此详情页面返回到sell和customerMangement页面后此页面缓存)
    if (to?.path?.includes('sell') || to?.name?.includes('customerMangement')) {
      to.meta.keepAlive = true
    }
    next()
  },

五、缺陷:按此方法缓存页面,会出现列表新增数据后进入详情在返回到列表时,之前新增的数据没有(即还是上一次的缓存列表数据)

六、解决方法:在离开列表页面就手动清除keep-alive缓存

1、在app.vue页面加上clearKeepAlive方法(并使用EventBus全局监听)

解释:this.$bus就是在main.js 加上:Vue.prototype.$bus = new Vue()

html 复制代码
<template>
  <div id="app">
    <keep-alive>
      <router-view class="Router" v-if="$route.meta.keepAlive" :key="fullPath"></router-view>
    </keep-alive>
    <router-view class="Router" v-if="!$route.meta.keepAlive"></router-view>
  </div>
</template>

<script>
export default {
  name: 'app',
  computed: {
    fullPath() {
      // console.log(this.$route.fullPath);
      return this.$route.fullPath;
    },
  },
  mounted() {
    console.log('app---mounted')
      // 注册监听全局的clearKeepAlive方法,可在其他组件中触发此方法
      this.$bus.$on("clearKeepAlive", this.clearKeepAlive);
  },
  methods: {
    // 根据fullUrl清除keepAlive
    clearKeepAlive(fullUrl) {
      // console.log('bus触发要清除的keepAlive', fullUrl);
      this.$children.forEach((item) => {
        if (item.$vnode.data.key == fullUrl) {
          // console.log('destorykeepAlive', item.$vnode.data.key, fullUrl, item);
          this.destorykeepAlive(item);
        }
      });
    },
    // 封装清除某个组件的keepAlive状态,并销毁
    destorykeepAlive(keepAliveDom) {
      if (keepAliveDom?.$vnode?.data?.keepAlive) {
        if (keepAliveDom?.$vnode?.parent?.componentInstance?.cache) {
          if (keepAliveDom.$vnode.componentOptions) {
            var key =
              keepAliveDom.$vnode.key == null
                ? keepAliveDom.$vnode.componentOptions.Ctor.cid +
                (keepAliveDom.$vnode.componentOptions.tag
                  ? `::${keepAliveDom.$vnode.componentOptions.tag}`
                  : "")
                : keepAliveDom.$vnode.key;
            var cache =
              keepAliveDom.$vnode.parent.componentInstance.cache;
            var keys = keepAliveDom.$vnode.parent.componentInstance.keys;
            if (cache[key]) {
              if (keys.length) {
                var index = keys.indexOf(key);
                if (index > -1) {
                  keys.splice(index, 1);
                }
              }
              delete cache[key];
            }
          }
        }
      }
      keepAliveDom.$destroy();
    }
}
</script>

2、单个列表页面使用

js 复制代码
  beforeRouteLeave(to, from, next) {
    if (to.name !== '列表进入的详情页面name') {
     // 离开列表页面的时候:当不是进入列表详情页面时清除列表页面的缓存
      this.$bus.$emit("clearKeepAlive", from.path)
    }
    next()
  },

相关文章

基于ElementUi再次封装基础组件文档


基于ant-design-vue再次封装基础组件文档


vue3+ts基于Element-plus再次封装基础组件文档

相关推荐
前端小端长2 小时前
Vue 中 keep-alive 组件的原理与实践详解
前端·vue.js·spring
小胖霞4 小时前
企业级全栈项目(14) winston记录所有日志
vue.js·前端框架·node.js
OpenTiny社区4 小时前
TinyEngine2.9版本发布:更智能,更灵活,更开放!
前端·vue.js·低代码
老华带你飞4 小时前
列车售票|基于springboot 列车售票系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·学习·spring
幸运小圣4 小时前
深入理解ref、reactive【Vue3工程级指南】
前端·javascript·vue.js
狗哥哥5 小时前
🚀 拒绝重复造轮子!在 Vue3 项目中打造一套企业级“统一上传服务”(支持分片、秒传、断点续传)
vue.js·架构
汝生淮南吾在北5 小时前
SpringBoot+Vue在线考试系统
vue.js·spring boot·后端·毕业设计·毕设
幸运小圣5 小时前
【Vue3】 中 ref 与 reactive:状态与模型的深入理解
前端·javascript·vue.js
叁两5 小时前
教你快速从Vue 开发者 → React开发者转变!
前端·vue.js·react.js
编程小Y6 小时前
Vue 3 + Vite
前端·javascript·vue.js