你懂keep-alive吗?

前言

小编觉得这个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 最大缓存组件数

生命周期

被缓存的组件会触发特殊生命周期:

  1. activated - 组件被激活时调用
  2. 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>

使用场景

  1. 表单内容缓存

典型场景:多步骤表单、填写后需要返回修改的表单、填了一半需要切换其他页面再回来的情况

实现细节

  • 当用户在表单中输入大量内容后,如果意外切换页面或刷新,传统方式会导致数据丢失
  • 使用keep-alive包裹表单组件,可以保持所有表单字段状态
  • 特别注意表单验证状态的保持,包括错误提示、脏检查等
vue 复制代码
<template>
  <keep-alive>
    <multi-step-form v-if="showForm" />
  </keep-alive>
</template>

<script>
export default {
  data() {
    return {
      showForm: true
    }
  }
}
</script>
  1. 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>
  1. 路由视图缓存

典型场景:移动端应用的页面导航、需要保持状态的详情页、需要记住筛选条件的列表页

实现细节

  • 基于vue-router的路由系统
  • 通过路由元信息(meta)控制哪些路由需要缓存
  • 可以细粒度控制不同路由的缓存策略
vue 复制代码
<template>
  <keep-alive>
    <router-view v-if="$route.meta.keepAlive" />
  </keep-alive>
  <router-view v-if="!$route.meta.keepAlive" />
</template>
  1. 需要保留滚动位置的列表

典型场景:社交媒体feed流、商品列表、新闻列表、聊天记录

实现细节

  • 列表组件被缓存后,滚动位置会自动保持
  • 配合vue-router的scrollBehavior实现更流畅的体验
  • 大数据量列表的性能优化关键
vue 复制代码
<template>
  <keep-alive>
    <news-list v-if="showList" />
  </keep-alive>
  <news-detail 
    v-else 
    @back="showList = true" 
  />
</template>
  1. 复杂组件初始化成本高的情况

典型场景:数据可视化大屏、复杂图表组件、3D模型渲染、富文本编辑器

实现细节

  • 这些组件通常初始化需要大量计算或资源加载
  • 每次重新创建都会导致明显的性能开销
  • 缓存可以显著提升用户体验
vue 复制代码
<template>
  <div>
    <button @click="showChart = !showChart">
      切换图表显示
    </button>
    
    <keep-alive>
      <complex-chart v-if="showChart" />
    </keep-alive>
  </div>
</template>

注意事项

  1. 需要配合组件名使用(name 选项)
  2. 缓存过多会导致内存占用过高
  3. 被缓存的组件需要唯一 key
  4. 嵌套使用可能产生意外行为
  5. 不适合频繁更新的组件

面试常见问题

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 是完整的组件缓存

原理剖析(面试重点)

  1. 缓存机制:使用 cache 对象存储组件实例
  2. 渲染机制:通过 $slots.default 获取子组件
  3. LRU 策略:当缓存数量超过 max 时,删除最近最久未使用的实例
  4. 组件匹配:通过 nameinclude/exclude 进行匹配
相关推荐
小小小小宇41 分钟前
前端转后端基础- 变量和类型
前端
Cobyte1 小时前
1.基于依赖追踪和触发的响应式系统的本质
前端·javascript·vue.js
主宰者2 小时前
C# CommunityToolkit.Mvvm全局事件
java·前端·c#
前端小咸鱼一条2 小时前
16.迭代器 和 生成器
开发语言·前端·javascript
小江的记录本3 小时前
【注解】常见 Java 注解系统性知识体系总结(附《全方位对比表》+ 思维导图)
java·前端·spring boot·后端·spring·mybatis·web
web守墓人3 小时前
【前端】记一次将ruoyi vue3 element-plus迁移到arco design vue的经历
前端·vue.js·arco design
伊步沁心3 小时前
Webpack & Vite 深度解析
前端
libokaifa3 小时前
OpenSpec + TDD:让 AI 写代码,用测试兜底
前端·ai编程
用户15815963743703 小时前
搭 AI Agent 团队踩了 18 个坑,总结出这 5 个关键步骤
前端
Kellen3 小时前
Fumadocs 基础概念:从内容源到页面渲染
前端