keep-alive 缓存不生效,及解决办法

keep-alive的用法

首先,我们看下官方给出的用法 KeepAlive | Vue.js (vuejs.org)

html 复制代码
<!-- 非活跃的组件将会被缓存! -->
<KeepAlive>
  <component :is="activeComponent" />
</KeepAlive>

使用 include 属性指定缓存的组件,它会根据组件的 name 选项进行匹配,所以组件如果想要条件性地被 KeepAlive 缓存,就 必须显式声明 一个 name 选项。

html 复制代码
<!-- 数组 (需使用 `v-bind`) --> 
<KeepAlive :include="['a', 'b']"> 
  <component :is="view" /> 
</KeepAlive>

接下来结合路由一起使用 RouterView 插槽 | Vue Router (vuejs.org)

普通用法,这种用法会缓存所有的路由组件,如果需要缓存指定路由就只能使用include属性

html 复制代码
<router-view v-slot="{ Component }">
  <keep-alive>
    <component :is="Component" />
  </keep-alive>
</router-view>

指定include属性,这个时候就会发现,因为使用了vue3 setup 语法糖,指定路由组件名字变成了一件需要引入额外代码的事情,虽然办法不算麻烦,但终归是需要理解一下。

html 复制代码
<router-view v-slot="{ Component }">
  <keep-alive :include="['a', 'b']">
    <component :is="Component" />
  </keep-alive>
</router-view>

问题描述:

需求: 子页面tab切换时希望保存组件状态,不重新刷新

问题: keep-alive缓存不生效

根据前面的文章 【转】【keep-alive】如何一步一步解决keep-alive缓存不生效问题 - 掘金 (juejin.cn) 需要注意一下几点:

  • 因为keep-alive会判断第一层dom是不是组件,如果包裹了一层div,则会缓存失败
  • 是否name配置不对
  • 是否router-view嵌套超过两层

在我这里,发现最终影响的隐私还是name没有指定导致的,虽然可以比较方便的在组件内部指定,那么有没有更好的方法呢?

解决方法

我的方法是在路由层面的,一种是在每个路由component做处理,一种是给路由加一层过滤方法

给每个路由component做处理

处理方法

ts 复制代码
const renameRouteComponent: (name: string, component: () => Promise<any>) => any = (name, component) => {
  return {
    component: async () => {
      return {
        ...(await component())?.default,
        name,
      }
    },
    name,
  }
}

export default {
  renameRouteComponent,
}

使用方法

js 复制代码
{
  path: 'goods/list',
  ...common.renameRouteComponent(
    'taskGoodsList',
    () => import('@/views/Task/Goods/List/index.vue')
   ),
  // name: 'taskGoodsList',
  // component: () => import('@/views/Task/Goods/List/index.vue'),
  // redirect: { name: 'taskSalesmanList' },
},

这种方法虽然能解决问题,但是需要修改原来代码

加一层过滤方法

处理方法

js 复制代码
const filterRouters = (routers: RouteRecordRaw[]) => {
  if (!routers || routers.length < 1) return routers

  return routers.forEach((item) => {
    if (item.children) {
      filterRouters(item.children)
    }
    if (!item.component) return

    const temp = item.component

    item.component = async () => {

      return {
        // @ts-ignore
        ...(await temp?.())?.default,
        name: item.name,
      }
    }
  })
}

filterRouters(routers)

这种方法需要每个路由指定name才能做到给路由组件指定name

遗留问题

当tab页面关闭时,如何做到删掉缓存

相关推荐
橙子家7 小时前
浏览器缓存之【身份与会话管理】:Cookies 和 Private state tokens
前端
最新资讯动态8 小时前
HDC 2026 | 对话鲸鸿动能:存量时代,品牌如何夺回营销“主动权”?
前端
最新资讯动态8 小时前
游戏出海,从产品走向体系
前端
最新资讯动态8 小时前
20人团队跑出百万DAU、大厂也来抢量:谁在鸿蒙生态跑出加速度
前端
最新资讯动态8 小时前
千万开发者背后,鸿蒙商业化的B面
前端
爱勇宝10 小时前
AI 时代:智商决定起点,情商决定走多远
前端·ai编程
kyriewen10 小时前
用了半年 Claude Code 后,我尝试关掉它写了一周代码——结果比想象中严重
前端·javascript·ai编程
IT_陈寒11 小时前
Vite的静态资源打包让我熬夜到三点,这坑千万别跳
前端·人工智能·后端
徐小夕12 小时前
万字拆解 JitWord:企业级实时协同文档底层架构 + 大模型 AI 融合完整实践
前端·vue.js·github
一份执念12 小时前
uni-app 小程序分包限制处理与主包体积优化实战
前端·微信小程序