React 的 Virtual DOM 到底有多快?

     2023-02-22     290

关键词:

【中文标题】React 的 Virtual DOM 到底有多快?【英文标题】:How exactly is React's Virtual DOM faster? 【发布时间】:2020-07-29 10:10:52 【问题描述】:

我知道 React 的虚拟 DOM 更快有两个论据 -

    它只更新那些实际需要更新的元素(使用差异)。

    它批量更新,因此我们只更新一次真实的 DOM。因此,重绘也只进行一次,否则会进行多次。

我对这两点都有疑问 -

    据我所知,所有现代浏览器的效率都足以仅更新 DOM 中所需的元素。例如,如果我有两个“p”标签,并且我通过单击按钮更改了其中一个 p 标签中的文本,那么 safari 只会更新那个 p 标签(我已经使用油漆闪烁验证了这一点)。那么如果第 1 点已经被浏览器实现了,那么它有什么优势呢?

    React 究竟是如何批处理更新的?最终 React 还必须使用 DOM api 来更新真实的 DOM。那么为什么如果我们直接使用 DOM api 则更改不会被批处理,而当 React 使用它时,它们会被批处理?

【问题讨论】:

这有助于解释吗? reactjs.org/docs/reconciliation.html @DrewReese 它没有解决我提到的问题。它只解释了差异过程。但它没有提到这是一个优势。它也没有讨论批处理。 差异化是优势;更新虚拟 DOM 更快,因为在内存中更新比在屏幕上更新更快。 @David 解释得很好。对于 #2,react 是开源的,查看代码以了解它们如何批量更新。 @DrewReese 我知道内存中的更新速度更快。但最终你必须在屏幕上更新。这使得内存中的更新只是一种开销。论点是它有助于仅更新那些已更改的元素。我是说浏览器已经这样做了。那么,react 究竟做了什么来提高性能呢? 是的,但不是真的。浏览器只重绘更新的内容。 React 对这些更新进行批处理,因此它不会为 DOM 中更改的 每个 小元素来回切换。正如大卫指出的那样,成本是重新粉刷。重绘的次数越少,框架的效率就越高。 【参考方案1】:

我找到了问题的答案。

关键是要理解 Virtual DOM 的用途。

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

不同的 javascript 框架采用不同的方法来检测数据模型中的变化并将其呈现在视图上。

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

React 采用了不同的方法。每当 React 组件中的状态发生变化时,React 会从头开始重新渲染整个 UI(使用更新的状态),而不是找出在哪里进行更改(如 AngularJS)。

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

这就是 React 的 Virtual DOM 的用武之地。Virtual DOM 只是 Real DOM 以 javascript 对象的形式表示。它只是存在于内存中的普通 javascript 对象的树形数据结构。与 Real DOM 相比,Virtual DOM 的渲染速度要快得多,因为它永远不会在屏幕上渲染(无需进行回流或重绘)。

那么 Virtual DOM 是如何解决这个问题的呢?当我们加载我们的应用程序时,React 会创建一个虚拟 DOM,它是真实 DOM 的精确虚拟副本。每当组件中的状态发生变化时,React 不会重新渲染整个 Real DOM,而是渲染一个全新的 Virtual DOM(具有更新的状态)。然后它在旧的 Virtual DOM(Real DOM 的初始副本)和这个新的 Virtual DOM(在状态更改后渲染)之间进行比较,以找出它们之间的变化,并且它只做 Real DOM 中的那些变化。通过这种方式,整个 UI 被重新渲染(通过渲染一个全新的 Virtual DOM),但只在 Real DOM 中完成了所需的最少更改。

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

这个answer 也解释了同样的概念。

我看到一些回答说使用 React 操作 DOM 比使用 DOM api 更快,因为 DOM api 重新渲染整个 DOM 树,而 React 只重新渲染 DOM 树中需要更改的部分.这不是真的。所有现代浏览器都足够高效,只更新 DOM 树中需要更改的部分。这可以在浏览器的开发者工具中使用paint flashing 来验证(另见answer 和answer)。即使我们假设 DOM api 确实重新渲染了整个 DOM 树,但这种推理仍然是错误的,因为 React 本身的内部代码必须使用 DOM api 来更新 DOM。如果 DOM api 确实重新渲染了整个 DOM 树,那么 React 也会重新渲染整个 DOM 树,因为最终它也使用 DOM api 来更新 DOM。

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

在 React 中,虽然读取是在 Real DOM 上完成的,但写入(状态更改)不是在 Real DOM 上完成的。相反,写入是排队的。然后当我们所有的读写都处理完后,一个新的 Virtual DOM 就会基于这些写来构建。然后在新旧 Virtual DOM 之间进行差异化,然后 React 将所需的更改写入 Real DOM 以更新它。因此,最终 Real DOM 上的所有写入都在一个回流中一起完成。

但是我们也可以在没有 React 的情况下手动编写代码,首先完成所有读取,然后完成所有写入。 React 使批处理更容易,因为使用 React 我们不必关心一起进行读取和写入,React 会自动为我们批处理写入。所以 React 不会让事情变得很快。它使事情变得更容易。

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

Rich Harris 的 post 还指出“虚拟 DOM 很快”是一个神话。

【讨论】:

一个简单的具体例子是很长的列表或表格,有和没有key 属性。浏览器永远无法对此进行优化,因为这不在浏览器的工作范围内。你总是需要一个抽象来实现优化。 @user120242 能详细解释一下这个关键优化吗? 我认为我的问题试图提出的观点(你承认它有一些道理)是 Pete Hunt 在视频中所说的 - “React 不是魔法。你总是可以编写汇编代码击败 C。以类似的方式,您始终可以使用原始 DOM 操作和 DOM api 来击败 React”(释义)。但 React 的目的绝不是打败 Vanilla JS。 React 的目的是将维护状态更改的工作从开发人员转移到库。 浏览器并没有真正“批量”更改,就像在这些框架中一样,DOM 仍然只是浏览器的普通 js 对象。它的作用是将 reflow 延迟到下一次绘制(以显示器刷新率发生)。只有当 js 需要计算值时,它才会同步强制回流。见***.com/questions/47342730/… @anonymous_siva 在 React 中,setState 调用是异步的,它们是batched 一起。因此,您不必担心它们会被批处理,因为 React 会为您做到这一点。【参考方案2】:

一旦 React 知道哪些虚拟 DOM 对象发生了变化,那么 React 只会更新真实 DOM 中的那些对象。与直接操作真实 DOM 相比,这使得性能要好得多。这使得 React 作为高性能 JavaScript 库脱颖而出。

关于批量更新:

React 遵循批量更新机制来更新真实的 DOM。因此,导致性能提高。 这意味着对真实 DOM 的更新是分批发送的,而不是为每次状态更改发送更新。

UI 的重绘是最昂贵的部分,React 有效地确保真正的 DOM 只接收批量更新来重绘 UI。

【讨论】:

“如何”让性能更好?即使没有 React,浏览器也只会更新那些需要更改的对象。反应带来了什么? 粗体字没有回答吗? 关于批量更新,反应用来“批量”更新的机制到底是什么。它如何使用 DOM api 批量发送更新? "然后 React 只更新真实 DOM 中的那些对象。与直接操作真实 DOM 相比,这使得性能要好得多。"不是在粗体文本的上下文中说的,而是在仅更新更改的对象的上下文中说的。 @chetanraina 从历史上看,当 React 被引入时,浏览器中的那些优化并不像现在这样高效。后来的浏览器,随着 React 引入的虚拟 DOM 概念的引入,创建了减轻性能差异的优化。

clickhouse到底有多快?200亿行数据count,group的响应时间

200亿行: count 6.61ssimplegroup37.45scomplexgroup398.55s 查看详情

设计实用的库存管理系统到底可以有多快?

如果举办一场比赛,用什么方式能够最快地设计一个实用的库存管理系统。管理Excel怎么都会是名列前茅的。下面我们将向你演示大约耗时5分钟设计出一个很实用的库存管理系统。系统能够实现:产品管理、出入库登记、每个产... 查看详情

java17到底有多快?(代码片段)

都说Java8是YYDS,那你注意到Java17已经正式发布了吗?目前Java18也已经进入早期开发阶段。Java官方团队已在OpenJDK邮件中确认,8月6号发布的JDK17build35可正式作为GA版本使用,期间没有报告任何P1错误。Java17的14个JEP&#x... 查看详情

手把手教你快速排序算法,看看它到底有多快?

...对比视频(中间那个就是快排),你就知道它到底有多快了,请全屏横屏播放更清晰:啥是快排 查看详情

手把手教你快速排序算法,看看它到底有多快?

...对比视频(中间那个就是快排),你就知道它到底有多快了,请全屏横屏播放更清晰:啥是快排 查看详情

React 的 Virtual DOM 如何比 DOM 快?

】React的VirtualDOM如何比DOM快?【英文标题】:HowisReact\'sVirtualDOMfasterthanDOM?【发布时间】:2018-12-2808:13:20【问题描述】:我知道React创建了一个虚拟DOM并比较了差异,然后只更新了真实DOM的实际元素,但是如果我手动更改它,那如... 查看详情

引擎盖下的 React Virtual Dom

】引擎盖下的ReactVirtualDom【英文标题】:ReactVirtualDomunderthehood【发布时间】:2018-03-0313:39:23【问题描述】:我从消息来源中了解到,如果我更新任何组件的状态而不是整个virtualdom将被渲染?是真的吗?如果是,那为什么不调用... 查看详情

Cycle.js (virtual-dom) 是不是支持 React 的 refs 或 mithril 的 config 属性?

】Cycle.js(virtual-dom)是不是支持React的refs或mithril的config属性?【英文标题】:DoesCycle.js(virtual-dom)supportanythinglikeReact\'srefsormithril\'sconfigproperty?Cycle.js(virtual-dom)是否支持React的refs或mithril的config属性?【发布时间】:2016-07-1223:16 查看详情

Shadow DOM 是不是像 React.js 中的 Virtual DOM 一样快?

】ShadowDOM是不是像React.js中的VirtualDOM一样快?【英文标题】:IsShadowDOMfastlikeVirtualDOMinReact.js?ShadowDOM是否像React.js中的VirtualDOM一样快?【发布时间】:2016-06-3022:47:07【问题描述】:在我的项目中实现ShadowDOM是否会让它们像React使用... 查看详情

什么是 Virtual DOM 以及其他一些 React 疑问

】什么是VirtualDOM以及其他一些React疑问【英文标题】:WhatisVirtualDOMandfewotherReactDoubts【发布时间】:2018-08-0406:30:58【问题描述】:我刚开始学习ReactJS。我之前在所有项目中都使用过jQuery和Javascript,在完成教程之后,我对ReactJS有... 查看详情

5g手机究竟能有多快?如何才能对手机内存有一个入门级了解?

...了!那么问题来了:如果买了5G手机,能达到的理论速率到底是多少呢?从频率带宽上来说,如果我们把移动通信网络比作一个高速公路的话,频段带宽就像是道路的宽度,带宽越大,道路越宽,当然同时能跑的车辆就越多,也... 查看详情

完成 c++ 文件的速度有多快? [复制]

】完成c++文件的速度有多快?[复制]【英文标题】:Howfastc++fileisfulfilled?[duplicate]【发布时间】:2011-12-1513:01:01【问题描述】:可能重复:Howtomeasureexecutiontimeofcommandinwindowscommandline?是否有计算.exe文件执行速度的程序?例如,如果... 查看详情

如何使用 Virtual DOM 在 React / Javascript 中重新加载输入值?

】如何使用VirtualDOM在React/Javascript中重新加载输入值?【英文标题】:HowtoreloadinputvalueinReact/JavascriptwithVirtualDOM?【发布时间】:2014-04-0821:01:00【问题描述】:我在重新加载输入值时遇到问题。<inputtype="email"ref="email"id="email"value=t... 查看详情

当今最先进的 HFT 交易系统有多快?

】当今最先进的HFT交易系统有多快?【英文标题】:HowfastisstateoftheartHFTtradingsystemstoday?【发布时间】:2013-06-1919:30:12【问题描述】:您总是听说高频交易(HFT)以及算法的速度有多快。但我想知道-这些天什么东西快?更新我考虑的... 查看详情

Web Worker 的消息有多快?

】WebWorker的消息有多快?【英文标题】:HowfastareWebWorker\'smessages?【发布时间】:2015-10-2108:23:03【问题描述】:我想知道与网络工作者之间的传输是否会成为瓶颈。我们应该在触发任何类型的事件时发布消息,还是应该小心并尽... 查看详情

ECS fargate 启动容器的速度有多快?

】ECSfargate启动容器的速度有多快?【英文标题】:HowfastcanECSfargatebootacontainer?【发布时间】:2018-06-0822:47:38【问题描述】:AWSECSFargate启动和运行Docker映像的最短/平均时间是多少?为了争论,45MBanapsix/alpine-java图像。我想研究使... 查看详情

大型电子商务网站有多快? [关闭]

】大型电子商务网站有多快?[关闭]【英文标题】:HowlargeeCommercesitesaresofast?[closed]【发布时间】:2012-05-1323:56:25【问题描述】:我一直在做基于NopCommerce的asp.netmvc3电子商务应用。最近我们一直致力于提高网站的性能。该网站有... 查看详情

dom操作成本究竟有多高,htmlcss构建过程,从什么方向出发避免重绘重排)

...在前端工程里用的越来越少。刨根问底,这里说的成本,到底高在哪儿呢?什么是DOMDocumentObjectModel文档对象模型什么是DOM?可能很多人第一反 查看详情