R

React、“Diffing”和 DOM 回顾 DOM React 的“虚拟 DOM”回顾

2025-06-10

React、“Diffing”和 DOM

审查 DOM

React 的“虚拟 DOM”

回顾

审查 DOM

DOM(文档对象模型)是一种接口,它以带有节点的树状结构表示 HTML 文档。这种结构允许程序员遍历和修改文档,每个节点都表示为一个对象。DOM 由浏览器在
网页加载时创建。

来自MDN

浏览器将 HTML 解析为 DOM 树。HTML 解析涉及标记化和树的构建。HTML 标记包括开始和结束标记,以及属性名称和值。如果文档格式正确,则解析起来更简单快捷。解析器将标记化的输入解析到文档中,从而构建文档树。

每次 UI 发生变化时,DOM 都会更新,UI 必须重新绘制。这个重新绘制或重新渲染的过程非常缓慢,因为必须重新计算 CSS、布局的几何形状,并且浏览器必须将元素绘制到屏幕上。这时,React 版本的 DOM 就派上用场了。

猪画

React 的“虚拟 DOM”

“虚拟 DOM” 或 VDOM 与真实 DOM 非常相似,因为它是一种保存在内存中的树状结构,其中 React 元素以对象的形式表示。这棵树具有许多与真实 DOM 相同的属性,但无法更改屏幕上的内容。它是一个 JavaScript 对象,表示应用程序中的组件,可以通过 React 快速高效地更新。

当 JSX 元素渲染或元素状态发生变化时,会创建一个新的 VDOM 树。负责创建这棵树的函数是 React 的 render() 函数。这个过程非常快,因为虚拟 DOM 树只是一个 JavaScript 对象,UI 不会基于这棵新树重新绘制。

一旦创建了 VDOM,React 就会将这个新表示与虚拟 DOM 的先前版本的快照进行比较,以准确查看哪些元素发生了变化。

一旦知道了差异,React 只会更新实际 DOM 上不同的对象,浏览器会重新绘制屏幕。下次应用程序中某个组件的 state 或 props 发生变化时,React 元素将创建一个新的虚拟 DOM 树,并重复该过程。

“差异”

检查新旧 VDOM 树之间差异的过程称为“diffing”。diffing 由启发式 O(n) 算法完成。在此过程中,React 将推断出更新真实 DOM 所需的最少步骤数,从而消除不必要的昂贵更改。此过程也称为“reconciliation”。

来自React 文档

“相反,React 基于两个假设实现了启发式 O(n) 算法:

  1. 两种不同类型的元素将产生不同的树。
  2. 开发人员可以使用关键属性暗示哪些子元素可能在不同的渲染中保持稳定。”
快速绕行

补充说明一下,当一个元素包含多个子节点时,React 可以使用键来追踪哪些子节点发生了变化。差异算法会逐步检查子元素之间的差异,因此,如果在元素末尾添加了子元素,则该添加将被标记为唯一更新。但是,例如,如果在元素开头添加了一个元素,那么 React 可能会认为后面的子元素也需要更新,因为元素之间会逐行存在差异。以下是文档中的示例

  <li>Duke</li>
  <li>Villanova</li>
</ul>

<ul>
  <li>Connecticut</li>
  <li>Duke</li>
  <li>Villanova</li>
</ul>

如果不使用键,“React 将会改变每个子项,而不是意识到它可以保持<li>Duke</li><li>Villanova</li>子树的完整性。这种低效率可能会成为一个问题。”

通过使用 key 属性,React 将能够分辨哪些子项已经存在或需要更新,哪些子项不存在。

React 将批量更新

React 的“虚拟 DOM”速度更快的另一个原因是,它可以批量更新 DOM。React 会等待一批更新准备就绪,然后一次性执行所有 DOM 更新,这样重绘只需进行一次。

回顾

总而言之,操作 DOM 本身并不慢,但重新绘制 UI 的开销很大。React 的“虚拟 DOM”有助于最大限度地减少这些绘制事件,它确保只操作 DOM 中需要更改的元素,并且这些更新是批量发送的。这些批量更新可以避免不必要的“缓慢”绘制事件,从而提高 React 应用程序的效率。

封面照片由 Min An 从 Pexels 拍摄

鏂囩珷鏉ユ簮锛�https://dev.to/racheladaw/react-diffing-and-the-dom-2j2d
PREV
针对移动屏幕上 100vh 问题的 Javascript 修复
NEXT
2025 年的 Web 开发:您准备好迎接未来了吗?