【前端每天一题】🔥 第 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 如何触发

你要哪个?

相关推荐
掘金011 小时前
根据提供的表格动态渲染多个表单,每个配置项包含 label、prop、type 和 placeholder 等属性。
前端
用户4445543654261 小时前
自定义viewgroup
前端
ohyeah2 小时前
用 Coze 打造你的教育智能客服:从想法到前端集成的完整实践
前端·coze·trae
雨雨雨雨雨别下啦2 小时前
【从0开始学前端】 Git版本控制系统
前端·git
前端一课2 小时前
【前端每天一题】 第 15 题:CSS 水平垂直居中高频方案(Flex / Grid / transform 等)
前端·面试
前端一课2 小时前
【前端每天一题】🔥 第 19 题:什么是重排(Reflow)和重绘(Repaint)?有什么区别?如何减少?
前端·面试
前端一课2 小时前
【前端每天一题】🔥 第 14 题:Promise.then 链式调用执行顺序
前端·面试
前端一课2 小时前
【前端每天一题】🔥 第 18 题:防抖和节流是什么?区别是什么?如何实现?
前端·面试
前端一课2 小时前
【前端每天一题】第 16 题:数组去重高频方法(Set / filter / reduce / 对象键值法)
前端·面试