你懂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 进行匹配
相关推荐
喝拿铁写前端3 小时前
前端与 AI 结合的 10 个可能路径图谱
前端·人工智能
codingandsleeping3 小时前
浏览器的缓存机制
前端·后端
灵感__idea5 小时前
JavaScript高级程序设计(第5版):扎实的基本功是唯一捷径
前端·javascript·程序员
摇滚侠5 小时前
Vue3 其它API toRow和markRow
前端·javascript
難釋懷5 小时前
JavaScript基础-history 对象
开发语言·前端·javascript
beibeibeiooo5 小时前
【CSS3】04-标准流 + 浮动 + flex布局
前端·html·css3
拉不动的猪5 小时前
刷刷题47(react常规面试题2)
前端·javascript·面试
浪遏5 小时前
场景题:大文件上传 ?| 过总字节一面😱
前端·javascript·面试
Bigger6 小时前
Tauri(十八)——如何开发 Tauri 插件
前端·rust·app
355984268550556 小时前
医保服务平台 Webpack逆向
前端·webpack·node.js