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再次封装基础组件文档

相关推荐
娃哈哈哈哈呀39 分钟前
vue中的css深度选择器v-deep 配合!important
前端·css·vue.js
真滴book理喻3 小时前
Vue(四)
前端·javascript·vue.js
不是鱼5 小时前
构建React基础及理解与Vue的区别
前端·vue.js·react.js
开心工作室_kaic5 小时前
springboot476基于vue篮球联盟管理系统(论文+源码)_kaic
前端·javascript·vue.js
川石教育5 小时前
Vue前端开发-缓存优化
前端·javascript·vue.js·缓存·前端框架·vue·数据缓存
搏博5 小时前
使用Vue创建前后端分离项目的过程(前端部分)
前端·javascript·vue.js
isSamle5 小时前
使用Vue+Django开发的旅游路书应用
前端·vue.js·django
ss2736 小时前
基于Springboot + vue实现的汽车资讯网站
vue.js·spring boot·后端
武昌库里写JAVA7 小时前
浅谈怎样系统的准备前端面试
数据结构·vue.js·spring boot·算法·课程设计
TttHhhYy7 小时前
uniapp+vue开发app,蓝牙连接,蓝牙接收文件保存到手机特定文件夹,从手机特定目录(可自定义),读取文件内容,这篇首先说如何读取,手机目录如何寻找
开发语言·前端·javascript·vue.js·uni-app