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

相关推荐
前端李易安1 小时前
Web常见的攻击方式及防御方法
前端
PythonFun2 小时前
Python技巧:如何避免数据输入类型错误
前端·python
hakesashou2 小时前
python交互式命令时如何清除
java·前端·python
天涯学馆2 小时前
Next.js与NextAuth:身份验证实践
前端·javascript·next.js
HEX9CF2 小时前
【CTF Web】Pikachu xss之href输出 Writeup(GET请求+反射型XSS+javascript:伪协议绕过)
开发语言·前端·javascript·安全·网络安全·ecmascript·xss
ConardLi2 小时前
Chrome:新的滚动捕捉事件助你实现更丝滑的动画效果!
前端·javascript·浏览器
ConardLi2 小时前
安全赋值运算符,新的 JavaScript 提案让你告别 trycatch !
前端·javascript
凌云行者2 小时前
使用rust写一个Web服务器——单线程版本
服务器·前端·rust
华农第一蒟蒻3 小时前
Java中JWT(JSON Web Token)的运用
java·前端·spring boot·json·token
积水成江3 小时前
关于Generator,async 和 await的介绍
前端·javascript·vue.js