虚拟 DOM——React 的支柱

2025-06-10

虚拟 DOM——React 的支柱

在处理页面更新、数据绑定等方面,我们对 React 的性能赞不绝口。但实现这种性能背后还有很多因素。其中一个影响因素就是虚拟 DOM。

等等,你之前说了 DOM 这个概念,现在又说有个叫虚拟 DOM 的全新玩意儿。这到底是怎么回事?在深入探讨之前,我们先来了解一下 DOM 到底是什么。

什么是 DOM?

在前端 Web 开发中,文档对象模型(DOM)通常被称作“文档对象模型”(Document Object Model),它是一种树状结构,用于表示 HTML 文档,其中树中的每个节点都是 HTML 元素,并且 HTML 元素之间的父子关系也保存在树中。这种 DOM 结构为我们提供了遍历 DOM 节点并进行修改的方法。原生 JavaScript 提供了操作 DOM 的 API,jQuery 对此进行了进一步的抽象和简化。

好的,您说的是,Vanilla JavaScript 提供了 API,jQuery 也提供了简化的 API,如果这些都有的话,React 和其他前端框架还有什么存在的必要呢?要回答这个问题,以及虚拟 DOM 诞生的因素,我们必须了解 DOM 缺少什么。

DOM 的缺点

是的,DOM 对于简单、静态的网站以及 UI 更新很少的网站来说非常棒。但是,当人们开始转向更注重 UI、移动端和响应式的网站设计时,他们开始意识到 DOM 的弊端。

1. DOM 突变的成本

与其他 JavaScript 操作相比,更新 DOM 的速度要慢得多。每当你想要更新或添加 DOM 时,它都必须找到要更新的 DOM 节点,或者找到新节点应该插入的位置。对于 DOM 节点数量较少的小型网站来说,这并非问题。但对于拥有大量 DOM 节点且更新成本高昂的大型网站来说,更新 DOM 节点的速度就会成为性能问题。此外,当 DOM 更新时,浏览器会重新绘制 DOM 节点,这无疑会更加耗时。

2. 更新效率低下

在确定需要更新的内容时,DOM 效率极低。有时它可能会更新超出实际需要的内容。例如,让我们考虑一个场景。你有一个<ul>包含由值数组生成的项目列表<li>。现在,当数组中的一个值发生更改时,整个列表都会重新渲染,这是不必要的,因为只有一个项目被更新了。

通常,每当发生单个 DOM 突变调用时,就会发生以下步骤:

  1. 遍历 DOM 直到必须插入或更新节点的位置。
  2. 更新 DOM 节点或者添加它。
  3. 重新计算位置和 CSS。
  4. 再次遍历并重新绘制页面上的节点。

这两点加上单页应用程序(SPA)的兴起(SPA通常具有大量的DOM节点、DOM变异以及监听站点变化的监听器)促使人们提出框架来绕过这些性能问题。

虚拟 DOM

首先,我要说的是,React 并没有发明虚拟 DOM,他们只是在性能方面对其进行了改进。虚拟 DOM 的核心概念是一个 JavaScript 对象,其中包含需要在真实 DOM 中渲染的节点列表。更新此 JavaScript 对象中的值比更新实际的 DOM 树要快得多。

简单来说,如果 DOM 是实际的建筑,那么虚拟 DOM 就是建筑的蓝图。其核心思想是,修改蓝图总是比修改实际的建筑更容易、更快捷。

实现虚拟 DOM 的两种方法是:

  1. 脏检查:涉及定期检查组件是否有变化。
  2. 可观察的:涉及通过监听器监听变化以找出需要更新的组件。

正如猜测的那样,React 使用了后一种实现方式,这也是 React 具有单向数据绑定及其惊人性能的主要原因之一。

哇,这一切都很棒。但它是如何在 React 中实现的呢?

同步虚拟 DOM 和真实 DOM

根据组件更新来更新 DOM 节点的过程通常由 ReactDOM 库完成。在此过程中通常会发生以下情况:

  1. 差异/对帐
  2. 批量更新真实 DOM

差异/对帐

当发生类似更新setState()时,会从头创建一个新的虚拟 DOM 树(不用担心,因为它只是一个 JavaScript 对象,所以速度很快)。差异算法会比较新旧虚拟 DOM 树,以查找脏组件。一旦找到所有脏组件,它就会确定更新真实 DOM 所需的最少步骤数。为了加快速度,此差异算法基于某些假设,因为 React 使用了一种启发式方法,我不会在这里讨论,但如果你想了解,可以访问React 的Reconciliation文档。

批量更新真实 DOM

一旦确定了更新步骤,ReactDOM 就会将所有步骤放在事件循环中的一次调用中。ReactDOM 会对这些步骤进行排序,只在最后一步调用 DOM 的重绘。因此,一旦所有步骤都执行完毕,事件循环就会调用 DOM 重绘,从而在整个过程中只调用一次 DOM 重绘,从而提高性能。如果在 ReactDOM 更新真实 DOM 时组件发生更新,它会等待真实 DOM 更新完成。

这就是 React 虚拟 DOM 带来惊人性能的原因,它已成为 React 的标志性特征。因此,在创建 React 应用程序时,请牢记虚拟 DOM 的概念,以便充分利用 React 带来的性能提升。

鏂囩珷鏉ユ簮锛�https://dev.to/sadarshannaiynar/virtual-dom---the-backbone-of-react-3cpp
PREV
讨厌你不使用的语言
NEXT
5 个很棒的库,可用于你的下一个 ReactJs 项目