【前端每天一题】🔥 第 24 题:Virtual DOM 中 diff 算法的核心流程(详细版

第 24 题:Virtual DOM 中 diff 算法的核心流程(详细版)

下面是详细讲解(不画图、不引用图片):


24. Virtual DOM 的 Diff 算法核心流程(详细版)

Diff(差异对比)算法是 Virtual DOM 的核心,用来比较新旧两棵虚拟 DOM 树的不同,最终只把差异更新到真实 DOM,从而提升性能。

以下分 6 个步骤讲清楚整个流程:


① 第一层优化:同层比较,不跨层

虚拟 DOM 永不跨层比较:

  • 旧树第 1 层只对比新树第 1 层
  • 旧树第 2 层只对比新树第 2 层
  • ......

原因: 浏览器真实 DOM 结构很少跨层变动,所以避免跨层,大幅减少计算量。


② 第二层优化:节点类型不同 → 整个节点直接替换

判断两个节点是否"同类型",主要看:

判断内容 示例
标签是否相同 div → div
组件是否相同 MyComponent → MyComponent
key 是否一致 key="1" → key="1"

如果节点类型不同直接整棵替换

css 复制代码
<div> → <span>

不用再继续往下比较 children。


③ 节点类型相同 → 继续比较属性(props)

例如两个 div

ini 复制代码
<div id="a" class="x">
<div id="b">

Diff 会:

  1. 找出删除的属性
  2. 找出新增的属性
  3. 找出修改的属性

最终生成类似补丁:

kotlin 复制代码
PATCH {
  remove class
  update id: a → b
}

④ 比较 Children(最复杂的部分)

子节点可能会:

  • 增加
  • 删除
  • 移动
  • 更新内容

其中列表渲染 v-for 的 diff 最复杂,需要 key。

Vue Diff 对 children 会做三类操作:


(1)同位置比较(前置指针)

从左往右一个一个比:

旧:A B C D

新:A B E D

前两个一致,跳过

到第三个不一致,执行更新


(2)尾部比较(后置指针)

从右往左比:

旧:A B C D

新:E B C D

尾部 D、C、B 都一样

只需处理最前面的 A 、E。

这种前后双指针优化减少很多循环。


(3)核心:key 的最长递增子序列(LIS)优化移动

这是最精华部分。

举例:

旧节点:A B C D

新节点:B A D C

为了尽量减少"移动 DOM 次数",Vue 会:

  1. 先计算每个旧节点在新列表中的下标映射。
  2. 找出最长递增子序列(LIS),这些节点不动。
  3. 剩下的节点才需要移动。

这样 DOM 操作最少,性能最好。


⑤ 生成补丁(patch)列表

patch 列表包含:

  • 哪些节点要删除
  • 哪些要新增
  • 哪些要移动
  • 哪些属性要更新
  • 哪些文本要替换

最终所有操作都是对真实 DOM 的最小修改集。


⑥ 执行 patch,更新真实 DOM

最后一步由渲染器完成:

  • 删除 DOM
  • 插入 DOM
  • 更新属性
  • 设置文本内容
  • 移动节点位置

这一步才真正发生浏览器的重绘/回流。


总结(背诵用)

Diff 算法核心 6 步:

  1. 同层对比,不跨层
  2. 节点类型不同 → 整个替换
  3. 节点类型相同 → 更新属性
  4. 比较 children:前置/后置/Key+LIS
  5. 生成最小修改补丁(patch)
  6. 执行 patch 更新真实 DOM

如果你要,我可以继续:

✅ 用图示方式讲

✅ 用代码模拟一次完整的 diff 流程

✅ 用实际 Vue 代码展示 diff 如何触发

你要哪个?

相关推荐
子兮曰1 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰1 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万1 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝1 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋1 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
晨米酱1 天前
AGENTS.md:Agent 的上下文策略层
面试·架构·agent
卡布鲁1 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
彧azz1 天前
Linux 环境下 Redis 学习总结:数据类型、持久化、锁、事务、主从与缓存问题
linux·redis·笔记·学习·面试
汉堡大王95271 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大1 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端