你懂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 进行匹配
相关推荐
codeGoogle5 小时前
自研 IM 还是选择第三方 SDK?企业开发者应该如何权衡?
前端·后端·程序员
用户938515635076 小时前
React Context 与自定义 Hook 从底层到实践:「跨层级通信 + 副作用封装」全解析
前端·javascript·react.js
滴滴答答哒6 小时前
VUE3+element-plus MultiSelect 多选下拉组件
前端·javascript·vue.js
其美杰布-富贵-李7 小时前
04 watch 与 Vue 响应式数据流
前端·javascript·vue.js
赵大仁8 小时前
生成式 UI 实战:用 JSON Schema + React 动态渲染 AI 界面
前端·ai·react·next.js·前端架构·生成式ui
kyriewen9 小时前
我排查了一个React内存泄漏——罪魁祸首是这3个被忽略的清理函数
前端·javascript·面试
IT_陈寒9 小时前
我又被JavaScript的隐式类型转换坑了
前端·人工智能·后端
其美杰布-富贵-李10 小时前
03 ref、reactive 与 computed 响应式数据
前端·javascript·vue.js
OpenTiny社区10 小时前
GenUI SDK v1.3.0 发布|多框架兼容,一键换物料,渲染器 & 演练场全面增强!
前端·ai编程
用户9385156350710 小时前
useRef + Web Worker 实战:React 如何优雅地拥抱多线程
前端·javascript·react.js