当前位置: 首页 > news >正文

Vue3底层原理——keep-alive

一、keep-alive 概述

keep-alive​ 不是缓存 DOM,而是缓存「组件 VNode + 组件实例(但 VNode 里持有组件实例)」,它通过“劫持组件卸载流程”,把 destroy 变成 deactivate

源码位置:

packages/runtime-core/src/components/KeepAlive.ts

keep-alive 是一个抽象组件,它不产生真实 DOM,只影响子组件的渲染/生命周期(只“包裹 & 接管”子组件)。

为什么 keep-alive 不缓存 DOM 快照?

因为:

  • DOM 是副产品,真正的“状态”在组件实例中
  • DOM 可以随时重建

所以:Vue 缓存的是“状态”,不是“视图” 。

二、keep-alive 渲染流程

2.1 核心数据结构

KeepAlive.ts 中,有一个 setup() 函数,里面有两个核心数据结构:

const cache = new Map<CacheKey, VNode>() // key -> VNode
const keys = new Set<CacheKey>() // 维护 LRU 顺序

2.2 render 阶段拦截子节点

const vnode = slots.default()[0]

keep-alive 只关心第一个组件子节点

2.3 设置缓存

const key = vnode.key ?? vnode.type // 决定缓存是否命中

2.3.1 命中缓存

const cachedVNode = cache.get(key)vnode.component = cachedVNode.component
vnode.el = cachedVNode.el// 并打上标记
vnode.shapeFlag |= ShapeFlags.COMPONENT_KEPT_ALIVE

2.3.2 首次渲染

cache.set(key, vnode)
keys.add(key)// 打上标记
vnode.shapeFlag |= ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE

三、keep-alive “阻止组件被卸载”

3.1 Vue 正常卸载组件会做什么?

unmount(vnode)↓
unmountComponent(instance)↓
stop effects↓
卸载 DOM

3.2 keep-alive 如何拦截?

在卸载阶段,Vue 会检查 flag:

if (shapeFlag & COMPONENT_SHOULD_KEEP_ALIVE) {deactivate(vnode) // destroy 被替换成 deactivatereturn
}

3.3 deactivate 实际做了什么?

function deactivate(vnode) {move(vnode, storageContainer) // 移动 DOM 到隐藏容器(effect / state / refs 全保留)queuePostRenderEffect(() => {invokeArrayFns(instance.da) // deactivated hooks})
}

四、activated / deactivated 生命周期

在组件实例上:

instance.a  // activated hooks
instance.da // deactivated hooks

注册来源:

onActivated(fn)
onDeactivated(fn)

触发时机:

activated / deactivated 正是与 Vue 调度系统有关:

queuePostRenderEffect(hook) // DOM 更新后,批量调度

所以缓存的视图尽管不在界面上,却仍然会触发响应式调度。

五、include / exclude / max

5.1 include / exclude(基于组件名)

function matches(pattern, name) {return pattern.split(',').includes(name)
}

在 render 阶段:

if (!matches(include, name)) {return vnode // 不缓存
}

5.2 max(LRU 缓存)

没错,这个 LRU 缓存正是咱们刷力扣经典题“LRU 缓存”算法!

if (keys.size > max) {pruneCacheEntry(keys.values().next().value) // 看到这个写法,用 js/ts 刷算法的同学是不是突然恍然大悟!
}

prune 可以从 cache 中真正 unmount 组件。

这是 keep-alive 唯一会“真的销毁组件”的地方。

http://www.jsqmd.com/news/285854/

相关文章:

  • :vtkBooleanOperationPolyDataFilter 布尔运算全解析
  • 2026年拼多多代运营服务商专业深度测评:排名前五权威榜单
  • APS1604M-SQR-SN核心性能特点及应用
  • GD5F2GM7UEYIGR核心性能及应用
  • 维基百科志愿者创建AI写作特征库,现推出插件帮助规避检测
  • Java毕设选题推荐:基于springboot+vue的食品安全管理系统基于springboot的食品安全管理系统【附源码、mysql、文档、调试+代码讲解+全bao等】
  • 计算机Java毕设实战-基于SpringBoot+Vue线上素菜超市平台蔬菜商城springboot的蔬菜超市系统【完整源码+LW+部署说明+演示视频,全bao一条龙等】
  • AI助力托管安全服务商降本增效实战分享
  • 2026 年办公效率新标杆:AI PPT 工具的全流程生成能力评测,重新定义演示文稿制作
  • ThinkPHP框架学习全攻略
  • 前端性能优化系列(一):问题分析与诊断
  • Java毕设选题推荐:基于SpringBoot生鲜商城系统基于springboot的蔬菜超市系统【附源码、mysql、文档、调试+代码讲解+全bao等】
  • 高管无视AI泡沫担忧,坚定推进技术采用计划
  • 2026年天猫代运营公司排名前五权威发布:专业深度测评
  • MX Linux 25.1恢复可切换初始化系统功能
  • offline_install_processor.cpp中的IPC通信
  • 微软CEO重新定义AI主权:关键在控制权而非数据中心位置
  • (新卷,200分)- 数字加减游戏(Java JS Python)
  • Nginx多服务静态资源路径冲突解决方案
  • CIO如何解锁人工智能战略价值并实施落地
  • Java毕设项目:基于springboot的蔬菜超市系统(源码+文档,讲解、调试运行,定制等)
  • Mobileye关键之年,Robotaxi去安全员、SuperVisionChauffeur迈入量产
  • scheme3.1.1 局部状态变量
  • 机器学习模型部署需超越聚合指标评估
  • 如何直接编辑Github的Readme.md文件
  • (新卷,200分)- 区间交叠问题(Java JS Python)
  • (新卷,200分)- 区块链文件转储系统(Java JS Python)
  • JVM(Java虚拟机) - 教程
  • 全网最全9个AI论文软件,本科生毕业论文必备!
  • 【课程设计/毕业设计】基于springboot的小区蔬菜水果商城系统蔬菜超市系统【附源码、数据库、万字文档】