前言
小编觉得这个keep-alive还挺好玩,就浅浅总结了一下哈哈,确实是挺不错的。
基本概念
<keep-alive>
是 Vue 内置的抽象组件,用于缓存不活动的组件实例,避免重复渲染。特点:
- 包裹动态组件时,缓存组件状态
- 自身不会渲染 DOM 元素
- 通过
include
/exclude
控制缓存组件 - 使用 LRU 算法管理缓存
使用方法
基本语法
html
<keep-alive>
//里面写缓存的组件
<component v-if="$route.meta.keepAlive"></component>
</keep-alive>
//外面可以写不缓存的组件
<component v-if="!$route.meta.keepAlive"></component>
配置参数
参数 | 说明 |
---|---|
include | 字符串/正则/数组,匹配组件名 |
exclude | 字符串/正则/数组,排除组件名 |
max | 最大缓存组件数 |
生命周期
被缓存的组件会触发特殊生命周期:
activated
- 组件被激活时调用deactivated
- 组件被停用时调用
首次讲入组件: beforeRouteEnter ->beforeCreated ->created ->mounted -> activated ->beforeRouteLeave ->deactivated
再次讲入组件: beforeRouteEnter ->activated ->beforeRouteLeave -> deactivated
代码示例
基础用法
vue
<template>
<keep-alive>
<component :is="currentTabComponent"></component>
</keep-alive>
</template>
包含/排除组件
vue
<keep-alive :include="['Home', 'About']" :exclude="/(User|Setting)/">
<router-view/>
</keep-alive>
最大缓存数'
当缓存的组件数量超过这个限制时,Vue 会使用 LRU (Least Recently Used) 算法自动移除最久未被访问的缓存实例。
vue
<keep-alive :max="5">
<child-component v-if="show"></child-component>
</keep-alive>
使用场景
- 表单内容缓存
典型场景:多步骤表单、填写后需要返回修改的表单、填了一半需要切换其他页面再回来的情况
实现细节:
- 当用户在表单中输入大量内容后,如果意外切换页面或刷新,传统方式会导致数据丢失
- 使用keep-alive包裹表单组件,可以保持所有表单字段状态
- 特别注意表单验证状态的保持,包括错误提示、脏检查等
vue
<template>
<keep-alive>
<multi-step-form v-if="showForm" />
</keep-alive>
</template>
<script>
export default {
data() {
return {
showForm: true
}
}
}
</script>
- Tab 切换保持状态
典型场景:后台管理系统中的多标签页、内容型网站的频道切换、数据分析平台的多视图切换
实现细节:
- 每个Tab内容通常是独立的组件
- 切换Tab时,非活动Tab的内容和状态(如滚动位置、已加载数据等)会被保留
- 避免每次切换都重新请求数据和重新渲染
vue
<template>
<div>
<div class="tabs">
<button
v-for="tab in tabs"
:key="tab.id"
@click="currentTab = tab.component"
>
{{ tab.name }}
</button>
</div>
<keep-alive :max="5">
<component :is="currentTab" />
</keep-alive>
</div>
</template>
- 路由视图缓存
典型场景:移动端应用的页面导航、需要保持状态的详情页、需要记住筛选条件的列表页
实现细节:
- 基于vue-router的路由系统
- 通过路由元信息(meta)控制哪些路由需要缓存
- 可以细粒度控制不同路由的缓存策略
vue
<template>
<keep-alive>
<router-view v-if="$route.meta.keepAlive" />
</keep-alive>
<router-view v-if="!$route.meta.keepAlive" />
</template>
- 需要保留滚动位置的列表
典型场景:社交媒体feed流、商品列表、新闻列表、聊天记录
实现细节:
- 列表组件被缓存后,滚动位置会自动保持
- 配合vue-router的scrollBehavior实现更流畅的体验
- 大数据量列表的性能优化关键
vue
<template>
<keep-alive>
<news-list v-if="showList" />
</keep-alive>
<news-detail
v-else
@back="showList = true"
/>
</template>
- 复杂组件初始化成本高的情况
典型场景:数据可视化大屏、复杂图表组件、3D模型渲染、富文本编辑器
实现细节:
- 这些组件通常初始化需要大量计算或资源加载
- 每次重新创建都会导致明显的性能开销
- 缓存可以显著提升用户体验
vue
<template>
<div>
<button @click="showChart = !showChart">
切换图表显示
</button>
<keep-alive>
<complex-chart v-if="showChart" />
</keep-alive>
</div>
</template>
注意事项
- 需要配合组件名使用(
name
选项) - 缓存过多会导致内存占用过高
- 被缓存的组件需要唯一 key
- 嵌套使用可能产生意外行为
- 不适合频繁更新的组件
面试常见问题
1. keep-alive 的实现原理?
- 使用 LRU 缓存策略
- 通过 abstract 属性标记为抽象组件
- 缓存 vnode 和组件实例
2. activated 和 created 的区别?
- created 只会在组件首次创建时调用
- activated 在每次从缓存中激活时调用
3. 如何实现路由级别的缓存?
vue
<keep-alive>
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>
4. 与 v-show 的区别?
- v-show 通过 CSS 切换显示
- keep-alive 是完整的组件缓存
原理剖析(面试重点)
- 缓存机制:使用
cache
对象存储组件实例 - 渲染机制:通过
$slots.default
获取子组件 - LRU 策略:当缓存数量超过 max 时,删除最近最久未使用的实例
- 组件匹配:通过
name
和include/exclude
进行匹配