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页面关闭时,如何做到删掉缓存

相关推荐
大橙子额6 分钟前
【解决报错】Cannot assign to read only property ‘exports‘ of object ‘#<Object>‘
前端·javascript·vue.js
LYFlied1 小时前
从 Vue 到 React,再到 React Native:资深前端开发者的平滑过渡指南
vue.js·react native·react.js
爱喝白开水a2 小时前
前端AI自动化测试:brower-use调研让大模型帮你做网页交互与测试
前端·人工智能·大模型·prompt·交互·agent·rag
董世昌412 小时前
深度解析ES6 Set与Map:相同点、核心差异及实战选型
前端·javascript·es6
B站_计算机毕业设计之家2 小时前
豆瓣电影数据采集分析推荐系统 | Python Vue Flask框架 LSTM Echarts多技术融合开发 毕业设计源码 计算机
vue.js·python·机器学习·flask·echarts·lstm·推荐算法
吃杠碰小鸡3 小时前
高中数学-数列-导数证明
前端·数学·算法
kingwebo'sZone3 小时前
C#使用Aspose.Words把 word转成图片
前端·c#·word
xjt_09013 小时前
基于 Vue 3 构建企业级 Web Components 组件库
前端·javascript·vue.js
我是伪码农3 小时前
Vue 2.3
前端·javascript·vue.js
夜郎king4 小时前
HTML5 SVG 实现日出日落动画与实时天气可视化
前端·html5·svg 日出日落