我知道有两个理由认为React的Virtual DOM更快-

  • 它仅更新那些实际需要更新的元素(使用diff)。
  • 它分批更新,因此我们仅一次更新实际DOM。因此,重新粉刷也仅进行一次,否则将多次进行。

  • 我对这两点都有疑问-
  • 据我所知,所有现代浏览器的效率都足以更新DOM中所需的元素。例如,如果我有两个'p'标签,并且我通过单击按钮更改了p标签之一中的文本,那么只有Safari浏览器会更新该p标签(我已经通过绘画闪烁验证了此内容)。那么,如果第1点已经被浏览器实现,那么它的优势是什么呢?
  • React究竟如何批处理更新?最终,React也将不得不使用DOM API来更新真实的DOM。那么为什么为什么如果我们直接使用DOM api,那么更改将不会被批处理,而当React使用它时,它们将被批处理?
  • 请您参考如下方法:

    我找到了我问题的答案。

    关键是要了解虚拟DOM的目的。

    首先,我们必须看到React使用什么方法来渲染组件。

    不同的javascript框架采用不同的方法来检测数据模型中的更改并将其呈现在 View 上。

    考虑AngularJS。当我们在Angular模板中(例如在类似{{foo.x}}的表达式中)引用数据时,Angular不仅会渲染该数据,还会为该特定值创建一个监视程序。每当我们的应用程序中发生任何事情(单击事件,HTTP响应,超时)时,所有观察程序都将运行。如果观察者中的值已更改,则该值将在UI中重新呈现。通过运行所有观察程序,AngularJS实质上可以确定需要在哪里进行更改。运行这些观察程序的过程称为脏检查。

    React采用了不同的方法。每当React组件中发生状态更改时,React无需找出更改的位置(例如AngularJS),而是从头开始重新渲染整个UI(具有更新的状态)。

    但是React的这种方法有一个问题。重新渲染整个UI意味着重新渲染整个DOM树。这是一个问题,因为DOM更新是一个缓慢的过程(由于重排和重绘)。

    这就是React的虚拟DOM出现的地方。虚拟DOM只是以JavaScript对象形式表示真实DOM的一种表示形式。它只是内存中存在的纯JavaScript对象的树型数据结构。与真实DOM相比,虚拟DOM的呈现要快得多,因为它从未在屏幕上呈现(无需进行重排或重新绘制)。

    那么虚拟DOM如何解决该问题呢?当我们加载应用程序时,React创建一个虚拟DOM,它是真实DOM的精确虚拟副本。只要组件中的状态发生变化,React便会渲染整个新的Virtual DOM(具有更新的状态),而不是重新渲染整个Real DOM。然后,它会在旧的虚拟DOM(真实DOM的初始副本)与新的虚拟DOM(状态更改后呈现)之间进行区分,以找出它们之间的变化,并且仅在真实DOM中进行这些更改。这样,可以重新渲染整个UI(通过渲染整个新的Virtual DOM),但是在Real DOM中仅进行了最小限度的更改。

    因此,当说“使用Virtual DOM React仅更新那些需要更新的元素”(我的问题中的第1点)时,这意味着在Virtual DOM React的帮助下,它克服了其自身方法的局限性(从头开始渲染整个用户界面)。

    此answer也解释了相同的概念。

    我已经看到一些答案,指出使用React进行DOM操作比使用DOM api更快,因为DOM api重新呈现了整个DOM树,而React仅重新呈现了需要更改的DOM树的那些部分。这不是真的。所有现代浏览器的效率都足以更新DOM树中那些需要更改的部分。可以使用浏览器的开发人员工具中的绘画闪烁来验证这一点(另请参见answer和answer)。即使我们假设DOM api确实重新渲染了整个DOM树,该推理仍然是错误的,因为React本身的内部代码必须使用DOM api来更新DOM。如果DOM api确实重新渲染了整个DOM树,那么React也会重新渲染整个DOM树,因为最终它也使用DOM api来更新DOM。

    关于第二点,React实际上使我们更容易进行批处理。

    在React中,虽然读取是在Real DOM上完成的,但是写入(状态更改)却没有在Real DOM上完成。而是将写入排队。然后,当我们所有的读写操作都已完成后,便会基于该写操作构建一个新的虚拟DOM。然后在新旧虚拟DOM之间进行区分,然后React将所需的更改写入到真实DOM进行更新。因此,最终所有对Real DOM的写操作都在一次重排中一起完成。

    但是,我们也可以在没有React的情况下手动编写代码,这样,首先完成所有读取,然后完成所有写入。 React使批处理变得容易,因为有了React,我们不必在意读写操作,React会自动为我们批处理写操作。因此,React不会使事情变得很快。它使事情变得容易。

    总而言之,我们可以说React实际上并不快。更容易。正如Pete Hunt在video中所说:“反应不是魔术。就像您可以使用C进入汇编程序并击败C编译器一样,您也可以进入原始DOM操作和DOM API调用,并在需要时击败React。但是,使用C或Java或JavaScript可以将性能提高一个数量级,因为您不必担心...平台的细节。使用React,您甚至无需考虑性能即可构建应用程序,并且默认状态很快。” 。

    Rich Harris的这首post也指出“虚拟DOM快速”是一个神话。


    评论关闭
    IT虾米网

    微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!