keep-alive动态移除缓存(vue3实例)

大家好,我是一名测试开发工程师,正在计划开源一款面向项目的自动化测试框架,该框架思想源于华为企业网,并且已成功实践于多个项目,包括华为商城、低代码平台等等,欢迎关注我。

一、keep-alive 的实现原理和缓存策略

  1. 获取 keep-alive 包裹着的第一个子组件对象及其组件名
  2. 根据设定的 include/exclude(如果有)进行条件匹配,决定是否缓存。,则直接返回组件实例;,则继续往下执行。
  3. 根据组件 ID 和 tag 生成缓存 Key,并在缓存对象中查找是否已缓存过该组件实例。如果存在,直接取出缓存值;否则,重新加载组件实例,并在缓存对象中存储该组件实例。
  4. 更新该 key 在 this.keys 中的位置(更新 key 的位置是实现LRU置换策略的关键)。
  5. 检查缓存的实例数量是否超过 max 的设置值,超过,则根据 LRU 置换策略删除最近最久未使用的实例(即是下标为 0 的那个 key)。

二、动态移除缓存的实现策略

  1. 通过2个参数控制:
  • keepNumber:用于计数,将用来重命名组件实例的缓存 Key值。
  • keepInclude:用于记录组件实例的缓存 Key值。
  • 最终是通过改变组件关联的缓存 Key值,实现是否使用缓存,间接实现移除缓存的目标。
  1. 组件实例打开时,判断在keepInclude是否有记录,如果没有,则keepNumber+1,并进行赋值记录。
  2. 当需要移除缓存时(即下次打开不使用缓存),从keepInclude中移除该组件实例。
  3. 如果无限制的这样操作,会导致缓存越来越多。这时候就需要使用到 keep-alive自身的LRU置换策略。通过指定max值,确定keep-alive的缓存数量

三、实例代码(vue3+TS+elementUiPlus)

<template>
<!--目录选择,用于操作打开tab页签,即打开组件实例-->
  <el-menu :default-active="myMenuSec">
    <template v-for="(name, path, index) in menuInfo" :key="index">
      <el-menu-item :index="path" @click="my_tabs_add(path)">
        <template #title>
          <span>{{ name }}</span>
        </template>
      </el-menu-item>
    </template>
  </el-menu>

<!--tab页签-->
  <el-tabs
      v-model="myTabSec"
      type="card"
      closable
      @tab-change="my_tabs_change"
      @tab-remove="my_tabs_remove"
  >
    <el-tab-pane
        v-for="(name,path) in myTabs"
        :key="path"
        :label="name"
        :name="path"
    />
  </el-tabs>
  
<!--展示组件实例,通过 v-if keepNumber>0 可以避免报错-->
  <router-view v-if="keepNumber > 0" v-slot="{ Component }">
    <keep-alive max="8">
      <component
          :key="keepInclude[router.currentRoute.value.path]"
          :is="Component"
      />
    </keep-alive>
  </router-view>
</template>

<script lang="ts" setup>
import {ref} from "vue";
import router from "@/router";

const keepInclude = ref<any>({})
const keepNumber = ref(0)

const myMenuSec = ref("");
const menuInfo: any = {
  "/testPage1": "测试页_1",
  "/testPage2": "测试页_2",
  "/testPage3": "测试页_3",
  "/testPage4": "测试页_4",
}
const myTabLast = ref("");
const myTabSec = ref("");
const myTabs = ref<any>({});
const my_tabs_add = (path:string) => {
  if (myTabSec.value != path) {
    myTabs.value[path] = menuInfo[path];
    myTabSec.value = path;
  }
}
const my_tabs_change = async (path:string) => {
  if (myTabLast.value != path){
    if (!keepInclude.value[path]) {
      // 记录组件实例的缓存Key值
      keepNumber.value += 1;
      keepInclude.value[path] = keepNumber.value
    }
    await router.replace({path: path});
    myMenuSec.value = path;
    myTabLast.value = path;
  }
}
const my_tabs_remove = (path:string) => {
  delete myTabs.value[path];
  if (myTabSec.value == path) {
    if (Object.keys(myTabs.value).length > 1) {
      myTabSec.value = Object.keys(myTabs.value)[0];
    } else {
      myTabSec.value = ""
    }
  }
  // 移除组件实例的记录
  delete keepInclude.value[path];
}
</script>
  • 10
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

微知语

你的鼓励是我创作的源泉

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值