Vue 更改keep-alive源码,满足条件性缓存(多个页签之间切换缓存,关闭页签重新打开不缓存)

本文介绍了如何在Vue应用中实现特定场景的缓存策略:在多页签切换时保持缓存,而关闭页签后再打开时不缓存。通过修改Vue的keep-alive源码,为路由参数添加时间戳以生成唯一key,自定义keep-alive组件并设置其key,最终实现了条件性的组件缓存。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

应用场景
当系统打开多个页签时,多个页签之间切换去做缓存,关闭页签重新打开该页签不缓存。

解决方案
更改 vue keep-alive源码

1、制造一个唯一的key值,在路由参数里面加一个时间戳

1.1 因keep-alive 使用组件名称name值作为唯一的key值去做条件缓存,但是该项目因书写不规范导致组件的name值不是唯一的。在路由的参数

    里面增加一个时间戳

        // 当点击系统左侧菜单的时候加时间戳

         select(url) {

             //先把打开的页签全部放到store里面

            //在打开页签里面找index原因是:找到已经打开过的页签的index,避免打开重复的多个页签
            const isHas = this.$store.state.multiTabPages.findIndex((val)=>{
                return val.name === url
            })
            if(isHas === -1) {
                this.$router.push({name:url, query: {
                    timeStr: new Date().getTime()
                }});
            }else {

               //如果找到已经打开过的这个页签,那就跳转到它原来的最初打开的页签页面
                this.$router.push({name:url, query: {
                    timeStr: this.$store.state.multiTabPages[isHas].query.timeStr
                }});
            }
        },

2、给自定义的keep-alive组件唯一的key值

 2.1 从依赖vue包里面找到keep-alive组件,拿到源码。在全局的组件里面创建一个自定义的keep-alive组件,注意组件名不要和vue自带的keep-alive组件名称相同会有冲突。

 2.2 源码是用ts写的,如果你的项目不支持ts,要先改成js,主要改的是render里面的逻辑。

 // keep-alive使用的是name值做匹配缓存,如下:

 const name = getComponentName(componentOptions)
    const { include, exclude } = this
    if (
      // not included
      (include && (!name || !matches(include, name))) ||
      // excluded
      (exclude && name && matches(exclude, name))
    ) {
      return vnode
    }


    const { cache, keys } = this
    const key = vnode.key == null
      // same constructor may get registered as different local components
      // so cid alone is not enough (#3269)
      ? componentOptions.Ctor.cid + (componentOptions.tag ? `::${componentOptions.tag}` : '')
      : vnode.key

2.3   把关闭页签的路由信息存入store中,在自定义的keep-alive组件中拿到关闭页签的路由信息

const slot = this.$slots.default // 获取默认插槽
const vnode = getFirstComponentChild(slot) // 获取第一个子节点
const componentOptions = vnode && vnode.componentOptions
if (componentOptions) {
  const { cache, keys } = this
  const route = this.$route  
  const key = route.fullPath  //拿到打开的页签的唯一key值(在路由里面加的时间戳和path组成的一个唯一的key值)


  // 拿到关闭页签的路由信息
  const removeRoute = this.$store.state.removeRoute || []
  if(removeRoute && removeRoute.length > 0){
    let tempKeys = JSON.parse(JSON.stringify(this.keys))
    let diff = tempKeys.filter((val) => { return !removeRoute.includes(val)})
    this.keys = JSON.parse(JSON.stringify(diff))
    for (const key in this.cache) {
      // 在缓存的cache对象里面移除掉已关闭的页签的信息
      if(removeRoute.includes(key)) {
        delete this.cache[key];
      }
    }
  }
  // 如果key对应的vnode存在,则更新key值
  if (cache[key]) {
    vnode.componentInstance = cache[key].componentInstance
    remove(keys, key)
    keys.push(key) // 调整key排序
  } else {
    // 否则将v
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值