是Vue本身提供的一个抽象组件,它自身并不会渲染一个 DOM 元素,主要用于保留组件状态或避免重新渲染。
在Vue2.X中可直接使用组件包裹,使用v-if 配合$route.meta实现组件状态有条件的保留。
<template>
<div id="app">
<keep-alive v-if="includedComponents">
<router-view ></router-view>
</keep-alive>
<router-view v-else></router-view>
</div>
</template>
<script>
export default {
computed:{
includedComponents(){
return this.$route.meta.keepAlive
}
}
}
</script>
组件状态保留是通过将组件实例以对象的形式存储在componentInstance中的cache对象内。因此可以利用组件提供的deactivated生命周期钩子手动删除保留的组件状态数据。
1、为每一个组件声明name属性,且name属性值应该具有唯一性,方便准确删除组件保留的数据;
2、为不需要保留状态的组件添加一个removeKeepAliveCache:true标识该组件不需要保留组件状态;
3、使用mixin全局注入如下组件生命周期钩子函数。
deactivated() {
const removeTabItem = sessionStorage.getItem("removeTabItem");
if (removeTabItem && this.$vnode && this.$vnode.parent) {
if (this.$options.removeKeepAliveCache && this.$vnode.parent.componentInstance.cache) {
let componentInstance = this.$vnode.parent.componentInstance;
for (const key in componentInstance.cache) {
if (Object.hasOwnProperty.call(componentInstance.cache, key)) {
const item = componentInstance.cache[key];
if (item.name === this.$options.name) {
delete componentInstance.cache[key];
}
}
}
sessionStorage.removeItem("removeTabItem");
}
}
},
在Vue3.X中不能像Vue2.X那样直接使用组件包裹,否则会有如下警告:图片
接下来看看在Vue3.X中如何使用
至于为什么要变为这样,请查看vue-router官网对于router-view 的介绍:
https://next.router.vuejs.org/zh/api/#router-view-%E7%9A%84-v-slot
至此,我们在vue3.X中也实现了对组件状态的保留。同样的,我们在Vue3.X中也可以使用v-if 配合$route.meta实现组件状态有条件的保留,请参照Vue2.X版本的示例,以下内容主要介绍通过组件提供的onDeactivated生命周期钩子函数在激活时如何删除保留的组件状态数据。
1、通过Vue提供的getCurrentInstance获取组件实例;
2、为不需要保留状态的组件添加一个removeKeepAliveCache:true标识该组件不需要保留组件状态;
3、通过onDeactivated生命周期钩子函数删除保留的数据。
// about/index.jsx
import { defineComponent, onDeactivated, getCurrentInstance } from "vue";
export default defineComponent({
name: "About",
removeKeepAliveCache: true,
setup() {
const instance = getCurrentInstance();
onDeactivated(() => {
const cache = instance.parent.__v_cache;
cache.forEach((value, key) => {
if (key.removeKeepAliveCache) {
cache.delete(key);
}
});
});
return () => (
<>
<h1>欢迎关注公众号~WEB前端李志杰~</h1>
</>
);
},
});
我们可以利用vue3.0的hooks开发思想进一步优化基于onDeactivated命周期钩子函数实现删除组件保留数据的这一部分逻辑。
1、新建一个hooks文件夹,并在hooks文件夹中新建一个useDeleteCache.js的文件,用来实现useDeleteCache函数。
图片
2、实现useDeleteCache.js,并且将获取到的组件实例return返回。
// useDeleteCache.js
import { onDeactivated, getCurrentInstance } from "vue"
export const useDeleteCache = () => {
const instance = getCurrentInstance();
onDeactivated(() => {
const cache = instance.parent.__v_cache;
cache.forEach((value, key) => {
if (key.removeKeepAliveCache) {
cache.delete(key);
}
});
});
return instance
}
3、改造about/index.jsx文件
// about/index.jsx
import { defineComponent, getCurrentInstance } from "vue";
import { useDeleteCache } from "../../hooks/useDeleteCache";
export default defineComponent({
name: "About",
removeKeepAliveCache: true,
setup() {
const instance = useDeleteCache();
return () => (
<>
<h1>欢迎关注公众号~WEB前端李志杰~</h1>
</>
);
},
});
至此,就实现了由About页面切换至其他页面时自动删除保留的About组件状态的全部功能。
最后附上一张Vue3.X关于组件实现的源码:
往期精彩内容:
【Vue】在Vite+Vue3.0中使用jsx语法开发。