你懂keep-alive吗?

Published 2025-03-25 20:57 1228 words 7 min read

做产品前,先别急着写代码:我是怎么判断一个点子值不值得做的想偷卷?但微信不支持md文档?这个软件助你!新手小白如何开发练手项目?前端常见安全问题 + 防御方法 + 面试回答吉比特(雷霆游戏)前端二面问题总结吉比特27前端实习面试纷享销客前端实习一面08-刚体约束 Constraint07-监听碰撞事件和获取碰撞信息06 - 物体休眠与休眠事件详解(Cannon.js)05-碰撞与碰撞组04 - 弹性与接触材质详解03 - Cannon 材质与摩擦系数设置02 - Cannon 引擎基础碰撞讲解01 - Cannon.js 引擎的用途和基本使用一款减轻前端图片命名工作量的图片转换器总结:一个双非大学生的两年,是怎么过来的?数学公式Input-输入框组件实现详解用HTML5实现实时ASCII艺术摄像头object-fit: contain - CSS 属性详解GSAP (GreenSock Animation Platform) 动画库学习指南Webview通信系统学习指南实现手势操控3D粒子动画?太好玩了!东田数码科技前端面试前端性能优化面试回答技巧(一)React与Vue表单的对比差异融山科技前端面经·React的入门学习(一)九方前端面试JavaScript 核心:数组/字符串 API 精要指南JavaScript的常用数组API原理解析前端练习小网站-新手突破之路前端の骚操作代码合集 (二)| 让你的网页变得有趣前端Threejs入门(五)Vue 3 响应式原理:computed的模板解包机制Vue 监听器 watch 深度解析Axios 深入解析从0到1配置vue项目跟git仓库连接!前端Three.js入门(四)你懂keep-alive吗?见过Vue的小区保安吗?前端Three.js入门(三)前端Three.js入门(二)前端Three.js入门(一)-Three的第一个简单的页面 Git 大冒险:解锁代码管理的秘密武器如何将网站加载速度提升50%?前端性能优化全攻略前端の骚操作代码合集 | 让你的网页充满恶趣味进击蓝桥杯!2025web前端HTML5uniapp-页面生命周期
This post is not yet available in English. Showing the original.
你懂keepalive吗? 作者: 前端AC | 原文: https://juejin.cn/post/7485562229087338535 前言 小编觉得这个keepalive还挺好玩,就浅浅总结了一下哈哈,确实是挺不错的。 基本概念 <keepalive 是 Vue 内置的抽象组件,用于...

你懂keep-alive吗?

作者: 前端AC | 原文: https://juejin.cn/post/7485562229087338535

前言

小编觉得这个keep-alive还挺好玩,就浅浅总结了一下哈哈,确实是挺不错的。

基本概念

<keep-alive> 是 Vue 内置的抽象组件,用于缓存不活动的组件实例,避免重复渲染。特点:

  • 包裹动态组件时,缓存组件状态
  • 自身不会渲染 DOM 元素
  • 通过 include/exclude 控制缓存组件
  • 使用 LRU 算法管理缓存

使用方法

基本语法

<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


代码示例

基础用法

<template>
  <keep-alive>
    <component :is="currentTabComponent"></component>
  </keep-alive>
</template>

包含/排除组件

<keep-alive :include="['Home', 'About']" :exclude="/(User|Setting)/">
  <router-view/>
</keep-alive>

最大缓存数‘

当缓存的组件数量超过这个限制时,Vue 会使用 LRU (Least Recently Used) 算法自动移除最久未被访问的缓存实例。

<keep-alive :max="5">
  <child-component v-if="show"></child-component>
</keep-alive>

使用场景

  1. 表单内容缓存

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

实现细节

  • 当用户在表单中输入大量内容后,如果意外切换页面或刷新,传统方式会导致数据丢失
  • 使用keep-alive包裹表单组件,可以保持所有表单字段状态
  • 特别注意表单验证状态的保持,包括错误提示、脏检查等
<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的内容和状态(如滚动位置、已加载数据等)会被保留
  • 避免每次切换都重新请求数据和重新渲染
<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)控制哪些路由需要缓存
  • 可以细粒度控制不同路由的缓存策略
<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实现更流畅的体验
  • 大数据量列表的性能优化关键
<template>
  <keep-alive>
    <news-list v-if="showList" />
  </keep-alive>
  <news-detail 
    v-else 
    @back="showList = true" 
  />
</template>
  1. 复杂组件初始化成本高的情况

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

实现细节

  • 这些组件通常初始化需要大量计算或资源加载
  • 每次重新创建都会导致明显的性能开销
  • 缓存可以显著提升用户体验
<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. 如何实现路由级别的缓存?

<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 进行匹配