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

相关推荐
婷婷婷婷几秒前
AntV X6 常用方法
前端
LucianaiB9 分钟前
拿到Offer,租房怎么办?看我用高德MCP+腾讯云MCP,帮你分分钟搞定!
前端·后端·cursor
用户175923421502815 分钟前
D3.js - 基本用法
前端·d3.js
Mr.Liu632 分钟前
小程序30-wxml语法-声明和绑定数据
前端·微信小程序·小程序
76756047933 分钟前
useDateFormat源码解析
前端·源码
Mintopia33 分钟前
Three.js粒子系统开发实战:从基础到性能优化
前端·javascript·three.js
Promise52033 分钟前
大屏"跑马灯" 长列表性能优化
前端·javascript
子玖34 分钟前
初始化项目前的准备
前端·javascript·vue.js
Mintopia34 分钟前
Three.js进阶实战:打造动态光影交互场景 ——结合环境光、聚光灯与相机控制的沉浸式体验
前端·javascript·three.js
贵州数擎科技有限公司35 分钟前
Threejs绘制小兩伞快拿去送给你的女神
前端