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

你要哪个?

相关推荐
dlhto10 分钟前
前端登录验证码组件
前端
@万里挑一12 分钟前
vue中使用虚拟列表,封装虚拟列表
前端·javascript·vue.js
黑臂麒麟15 分钟前
Electron for OpenHarmony 跨平台实战开发:Electron 文件系统操作实战
前端·javascript·electron·openharmony
wordbaby15 分钟前
Tanstack Router 文件命名速查表
前端
a程序小傲21 分钟前
京东Java面试被问:Fork/Join框架的使用场景
java·开发语言·后端·postgresql·面试·职场和发展
1024肥宅23 分钟前
工程化工具类:模块化系统全解析与实践
前端·javascript·面试
软件技术NINI23 分钟前
如何学习前端
前端·学习
想用offer打牌24 分钟前
面试官问Redis主从延迟导致脏数据读怎么解决?
redis·后端·面试
weixin_4225554225 分钟前
ezuikit-js官网使用示例
前端·javascript·vue·ezuikit-js
鱼鱼块28 分钟前
从零搭一个 Vue 小家:用 Vite + 路由轻松入门现代前端开发
vue.js·面试·前端框架