为什么 React 的 Virtual DOM 概念被认为比脏模型检查更高性能?

2022-08-29 23:31:27

我在(Pete Hunt: React: Rethinking best practices -- JSConf EU 2013)上看到了一个 React 开发者演讲,演讲者提到对模型进行肮脏的检查可能会很慢。但是,计算虚拟DOM之间的差异实际上不是更低性能,因为在大多数情况下,虚拟DOM应该大于模型吗?

我真的很喜欢虚拟DOM的潜在功能(特别是服务器端渲染),但我想知道所有的优缺点。


答案 1

我是虚拟dom模块的主要作者,所以我也许能够回答你的问题。实际上,这里有2个问题需要解决

  1. 何时重新渲染?答:当我观察到数据是脏的。
  2. 如何高效地重新渲染?答:使用虚拟 DOM 生成真正的 DOM 补丁

在 React 中,你的每个组件都有一个状态。此状态类似于在挖空或其他 MVVM 样式库中找到的可观察量。从本质上讲,React 知道何时重新渲染场景,因为它能够观察这些数据何时发生变化。脏检查比可观察量慢,因为您必须定期轮询数据并以递归方式检查数据结构中的所有值。相比之下,在状态上设置一个值将向侦听器发出信号,表明某些状态已更改,因此 React 可以简单地侦听状态上的更改事件并排队重新渲染。

虚拟 DOM 用于对 DOM 进行高效的重新呈现。这与脏检查数据无关。您可以使用带或不带脏检查的虚拟 DOM 重新渲染。你是对的,因为计算两个虚拟树之间的差异有一些开销,但虚拟DOM差异是关于了解DOM中需要更新的内容,而不是你的数据是否已更改。实际上,diff 算法本身就是一个脏检查器,但它用于查看 DOM 是否是脏的。

我们的目标是仅在状态更改时才重新渲染虚拟树。因此,使用可观察量来检查状态是否已更改是防止不必要的重新呈现的有效方法,这将导致大量不必要的树差异。如果什么都没有改变,我们什么也做不了。

虚拟DOM很好,因为它允许我们编写代码,就好像我们正在重新渲染整个场景一样。在幕后,我们希望计算一个补丁操作,该操作更新 DOM 以使其符合我们的期望。因此,虽然虚拟DOM差异/补丁算法可能不是最佳解决方案,但它为我们提供了一种非常好的方式来表达我们的应用程序。我们只是声明我们想要的,React/virtual-dom将研究如何让你的场景看起来像这样。我们不必进行手动DOM操作,也不必对以前的DOM状态感到困惑。我们也不必重新渲染整个场景,这可能比修补它的效率低得多。


答案 2

我最近在这里读了一篇关于 React diff 算法的详细文章:http://calendar.perfplanet.com/2013/diff/。据我所知,使 React 快速的是:

  • 批处理的 DOM 读/写操作。
  • 仅高效更新子树。

与脏检查相比,IMO的主要区别是:

  1. 模型脏检查:每当调用 React 组件时,都会显式设置为脏,因此这里不需要比较(数据)。对于脏检查,比较(模型)总是在每个摘要循环中发生。setState

  2. DOM更新:DOM操作非常昂贵,因为修改DOM也将应用和计算CSS样式,布局。从不必要的 DOM 修改中节省的时间可能比比较虚拟 DOM 所花费的时间更长。

第二点对于非平凡的模型更为重要,例如具有大量字段或大型列表的模型。复杂模型的一个字段更改将导致仅涉及该字段的 DOM 元素所需的操作,而不是整个视图/模板。