虚拟 DOM 如何提高 ReactJS 的速度?

Posted

技术标签:

【中文标题】虚拟 DOM 如何提高 ReactJS 的速度?【英文标题】:How virtual DOM increases speed for ReactJS? 【发布时间】:2016-01-09 11:33:22 【问题描述】:

我读到 ReactJS 与其他框架相比非常快,因为 if 使用虚拟 dom。

我无法理解的是最终所有框架都必须在浏览器中推送 dom 对象。 virtualDom 如何帮助提高速度?

假设我要添加10K节点列表,ReactJS和其他框架所需的DOM操作时间不应该相似吗?

【问题讨论】:

它只执行需要执行的更改。速度的提高是您将新树与虚拟树进行更改,而不是针对速度较慢的真实 DOM。如果您需要从头开始渲染 10k 节点,那么在任何地方都会很慢:整个事情都针对现有结构的频繁更改进行了优化。 使用虚拟 DOM 也可以进行优化;例如,如果您通常必须在 React 中“添加 10K 节点”,您可能会构建一个包含 10K 项的数组,然后在引擎盖下 React 可能会在一个 innerhtml 操作中将其刷新到 DOM(显然 DOM 仍然很慢但操作次数可以优化)。 令人惊讶的是,实际上并不是虚拟 DOM 本身在大型模型上比其他框架反应更快,它避免了对大型模型上更改的脏检查/观察。公平地说,一旦发现,DOM 的角度变化与反应中的变化一样快。虚拟 dom 的优点是可以观察视图输出而不是模型。在 bigO 中,这是 O(model)O(view) 之间的区别,并且由于分页、制表符等,当需要实际更新视图时,通常需要排序的视图片段少于模型片段。 【参考方案1】:

浏览器引擎在 DOM 上的每次增量更新或更改都会占用更多内存和布局更改。因为它涉及到更多的几何和数学计算,这是在浏览器上的每次布局更改时计算的。

但是,浏览器上的计算占用的内存更少,并且不会反映 DOM 上的任何内容。 VirtualDOM 使用了这种方法。

让我们来一个 DOM,每个 DOM 都有自己的属性DOM properties,这些属性是模拟的(使用 JS)。

虚拟 DOM 保留状态可以说它具有 DOM 的初始状态和所有属性

因此,每当发生变化时,Virtual DOM 不会直接反映在 DOM 中,而是会进行比较操作或差异操作,只会返回从先前状态更改的属性或属性

所以它只会更新 DOM 中更改的属性。而不是重新绘制整个 DOM 以进行微小的更改。

这在频繁更新的网络应用程序中非常有效,更改 DOM 的一小部分可以节省更多的内存或浏览器引擎的几何计算,而不是整个 DOM。

ex: <DIV style="color:red; background-color:white;">Hello world <span>from Foo</span></DIV>

当我将文本更改为 Hello Mars 时。而不是删除并创建一个新的 DOM。

Virtual DOM 只会改变 DIV 的文本,不会影响子 &lt;span&gt; 以及 DOM 的其他属性

另见

How browser works浏览器如何绘制DOM Reactive programming 负责响应式编程。

【讨论】:

【参考方案2】:

首先您必须记住,DOM 操作(重绘、重排)比 javascript 操作要昂贵得多。

例如(人为的),更新一个

实时 DOM 元素可能需要 3 秒 虚拟 DOM 元素可能需要 1 秒

现在假设我有一个 DOM

<ul>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
</ul>

假设您想将其更新为

<ul>
    <li>First Item</li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
</ul>

如果没有虚拟 dom,它将在屏幕上重新绘制所有 6 个元素,这需要 3x6=18 秒

使用虚拟 dom,我们可以在内存中绘制它,这将花费我们 6 秒。绘制完成后,我们可以比较发生了什么变化,在我们的例子中是 1 个元素——我们可以在 3 秒内绘制这个元素,因此我们在 9 秒内完成了这个操作(这比没有虚拟 dom 的情况要快)。

当然,您可以想象并非所有情况都会从虚拟 dom 中受益,但在大多数情况下,使用虚拟 dom 是一个显着的改进。

关键假设是实时 DOM 重绘/重排比虚拟 DOM 昂贵得多。

【讨论】:

这几乎是一回事,这是一个原生浏览器实现。 React 也有自己的实现,但它们做的事情非常相似 请注意,至少,对于最近的 chrome(例如)如果您更新第一个 ,则只有它会被重排【参考方案3】:

React 中虚拟 DOM 的工作是创建虚拟 DOM 树,并在每个事件循环结束时,将当前的 V-DOM 树与之前的 V-DOM 树进行比较,然后获取补丁和操作真实的 DOM。 如果在一个事件循环中,用户多次修改同一个组件,React 将计算最终结果并操作真实的 DOM,这称为“批处理”

所以实际上,并不是每个案例都会利用 React 的 V-DOM 优势。在您的示例中,React 可能会使用 innerHTML 来操作真实的 DOM。如果你经常更改元素之一,React 会进行批处理。

你可以参考下面的文章 http://calendar.perfplanet.com/2013/diff/

【讨论】:

【参考方案4】:

Virtual DOM 是真实 DOM 的轻量级副本,它通过声明性 API 和 diff 算法在 observables 的帮助下比较那些需要修改的元素,然后只重绘它们。而且,尽管虚拟 DOM 每次都是从头开始创建的,但它只需要不到 50 毫秒,这对于人类的视觉感知来说是不明显的。这种技术有时会加快应用程序的性能,因为它不涉及保留其状态的真实 DOM 的“较重”元素的不必要数量。

这也是ReactJs is fast的原因之一

【讨论】:

以上是关于虚拟 DOM 如何提高 ReactJS 的速度?的主要内容,如果未能解决你的问题,请参考以下文章

ReactJs的虚拟dom是个啥情况?

虚拟DOM (virtual DOM)

2.ReactJS基础(虚拟DOM,JSX语法)

ReactJS虚拟DOM一则例证

全面理解虚拟DOM,实现虚拟DOM

47前端 | 全面理解虚拟DOM,实现虚拟DOM