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