1. KeepAlive到底是什么?从“保鲜盒”说起
如果你用过Vue开发单页应用,肯定遇到过这样的烦恼:我在一个标签页里填了半天表单,切换到另一个页面再切回来,发现刚才辛辛苦苦填的内容全没了,页面又回到了初始状态。或者,你有一个数据复杂的列表页,每次从详情页返回,列表都要重新加载、滚动条又回到了顶部,用户体验非常割裂。这种时候,你就需要请出Vue的内置神器——KeepAlive组件了。
你可以把KeepAlive想象成一个智能的组件保鲜盒。在Vue应用里,组件的默认行为是“用完即弃”:当一个组件因为路由切换或v-if条件变化而离开视图时,它会被完全销毁,包括它内部的数据状态、DOM节点都会被清理掉。等下次需要再显示这个组件时,Vue会重新创建一个全新的实例,从头开始执行生命周期。而KeepAlive的作用,就是拦截这个“销毁”过程。它会把离开视图的组件实例“捡起来”,放进一个内部的缓存盒子里妥善保存起来,而不是扔掉。当组件需要再次显示时,KeepAlive会从盒子里把原来的实例“拿出来”,直接放回DOM中。因为组件实例本身(包括它的数据、DOM、事件监听器)都完好无损,所以用户会感觉页面状态被完美“冻结”并恢复了。
我刚开始用的时候,觉得这功能太省心了。比如做一个后台管理系统,左侧是导航菜单,右侧是内容区。管理员可能在“用户管理”页面筛选、翻页,然后去“订单管理”查个数据,再切回“用户管理”。如果没有KeepAlive,每次切换回来,筛选条件清零、页码回到第一页,管理员估计要抓狂。用上KeepAlive之后,这一切都变得顺滑无比,状态完全保留,就像应用从未离开过那个页面一样。
那么,这个“保鲜盒”具体是怎么工作的呢?从表面看,用法极其简单,就是用<KeepAlive>标签包裹你的动态组件或路由视图。但它的内部机制其实相当精巧。它利用了Vue渲染器的内部钩子,在组件即将被卸载时,将其从真实的DOM树中移动到内存里的一个隐藏容器中(这个过程对应deactivated生命周期);当组件需要再次渲染时,再将其从隐藏容器移回真实的DOM树(对应activated生命周期)。这个“移动”而非“销毁/重建”的过程,是性能提升和状态保留的关键。接下来,我们就深入这个“盒子”的内部,看看它有哪些可以调节的“保鲜”参数。
1.1 核心三要素:include、exclude 和 max
KeepAlive组件提供了三个非常实用的props,让你能精细地控制缓存策略,而不是一股脑儿全缓存。理解并用好它们,是避免内存泄漏和提升应用性能的关键。
第一个是 include。它的作用是指定“白名单”,只有匹配的组件才会被缓存。这个匹配依据的是组件的name选项。所以,第一个重要的实践点来了:任何你希望被KeepAlive缓存的组件,都必须显式地设置一个name。这个name通常和你定义组件时的变量名一致,但最好在组件内部用defineOptions或选项式API的name字段再声明一次,确保稳定。include的值很灵活,可以是逗号分隔的字符串、正则表达式或者数组。我个人的习惯是在中型以上项目里用数组,清晰明了。
<script setup>
// 组件必须定义name
defineOptions({
name: 'UserList'
})
</script>
<template>
<!-- 在父组件或路由视图中使用 -->
<KeepAlive :include="['UserList', 'OrderList']">
<router-view />
</KeepAlive>
</template>
第二个是 exclude。和include相反,它是“黑名单”,匹配到的组件坚决不缓存。这个在你有明确不需要缓存的组件时非常有用。比如,一个实时数据仪表盘页面,你希望它每次进入都拉取最新数据,那就把它加入exclude。include和exclude可以同时使用,但要注意逻辑,通常用一个就够了,避免规则冲突把自己绕晕。
第三个是 max。这是我认为最重要的一个属性,但也是最容易被新手忽略的。它决定了你的“保鲜盒”最多能放多少个组件实例。如果不设置,理论上缓存的实例会一直增加,这在大型单页应用中是非常危险的,可能导致内存持续增长,最终影响页面性能。max属性实现了LRU(最近最少使用)缓存淘汰算法。当缓存数量超过max时,那个最久没有被访问(激活)的组件实例会被自动销毁,腾出空间给新的实例。我一般会根据项目路由的复杂程度来设置,比如一个后台系统,同时打开的页面通常不会超过10个,那么设置:max="10"就是一个比较安全且充足的值。
<KeepAlive :include="cacheableComponents" :max="10">
<component :is="currentComponent" />
</KeepAlive>
这三个属性结合起来,你就能构建一个受控的、安全的组件缓存层。我踩过的坑是早期项目没设max,结果用户长时间使用后页面变卡,用Chrome DevTools的内存快照工具一分析,发现缓存了一堆早已不用的组件实例。加上max之后,问题迎刃而解。
1.2 专属的生命周期:activated 与 deactivated
当一个组件被KeepAlive缓存后,它就多了一对独特的生命周期钩子:onActivated 和 onDeactivated(在组合式API中)。这是你与缓存行为进行交互的主要桥梁。
onActivat


1146

被折叠的 条评论
为什么被折叠?



