我知道React的虚拟DOM更快有两个理由-

  1. 它只更新那些实际需要更新的元素(使用diff).

  2. 它批量更新,因此我们只更新一次真正的DOM.因此,重新喷漆也只能进行一次,否则会进行多次.

我对这两点都有疑问-

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

  2. 批量更新的具体react 是什么?最终,React还必须使用DOM api来更新真正的DOM.那么,为什么如果我们直接使用DOM api,那么这些更改将不会被批处理,而当React使用它时,它们将被批处理?

推荐答案

我已经找到了我问题的答案.

关键是要理解虚拟DOM的用途.

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

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

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

React采取了不同的方法.每当React组件中出现状态更改时,React都会从头开始重新呈现整个UI(使用更新的状态),而不是找出在哪里进行更改(如AngularJS).

但这种react 方式有一个问题.重新呈现整个UI意味着重新呈现整个DOM树.这是一个问题,因为DOM更新是一个缓慢的过程(由于回流和重新绘制).

这就是React的虚拟DOM的用武之地.虚拟DOM只是javascript对象形式的真实DOM的表示.它只是内存中存在的普通javascript对象的树数据 struct .与真实的DOM相比,虚拟DOM的渲染速度要快得多,因为它从不在屏幕上渲染(无需进行回流或重新绘制).

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

因此,当人们说"使用Virtual DOM React只更新那些需要更新的元素"(我的问题中的第1点)时,这意味着借助Virtual DOM React正在克服其自身方法(从头呈现整个UI的方法)的局限性.

answer也解释了同样的概念.

我看到一些答案表明,使用React进行DOM操作比使用DOM api更快,因为DOM api会重新呈现整个DOM树,而React只会重新呈现DOM树中需要更改的部分.事实并非如此.所有现代浏览器的效率都足以只更新DOM树中需要更改的部分.这可以在浏览器的开发者工具中使用油漆闪烁来验证(也可以参见这answer和这answer).即使我们假设domapi确实重新呈现了整个DOM树,但这种推理仍然是错误的,因为React本身的内部代码必须使用domapi来更新DOM.如果domapi确实重新呈现了整个DOM树,那么React也会重新呈现整个DOM树,因为它最终也会使用domapi来更新DOM.

 
As for the second point, React actually makes batching easier for us.

在React中,虽然读取是在真实的DOM上完成的,但写入(状态更改)不是在真实的DOM上完成的.相反,写入是排队的.然后,当我们所有的读写操作都被处理后,一个新的虚拟DOM将基于写操作构建.然后在旧的和新的虚拟DOM之间进行区分,然后React将所需的更改写入真实DOM以更新它.因此,最终所有在真实DOM上的写入都在一次回流中完成.

但我们也可以手动编写代码,而无需做出react ,这样一来,首先所有的读取都完成了,然后所有的写入都完成了.React使批处理更容易,因为使用React,我们不必关心一起执行读写操作,React将自动为我们批处理写操作.所以React并不能让事情快速发展.这让事情变得更容易.

 
In conclusion we can say that React is not actually faster. It is easier. As Pete Hunt says in this video, "React is not magic. Just like you can drop into assembler with C and beat the C compiler, you can drop into raw DOM operations and DOM API calls and beat React if you wanted to. However, using C or Java or JavaScript is an order of magnitude performance improvement because you don't have to worry...about the specifics of the platform. With React you can build applications without even thinking about performance and the default state is fast.".

Rich Harris的这post篇文章还指出,"虚拟DOM很快"是一个神话.

React-native相关问答推荐

复活的夹子在Panguesture上崩溃

react native调用fetch后如何使用Async Storage在本地保存数据?

react平面列表渲染项

React Native 响应式图像宽度,而图像的宽度/高度比保持不变

React Native Expo - 不再支持 Node.js 版本 11.13.0

react-native 中的layout-only view removal优化是什么?

我如何知道我的代码是否作为 React Native 运行

React-Native:显示加载屏幕直到加载 webview

修复错误:路由 'Home' 的组件必须是 React 组件

React-Native Android 中隐藏(hide)的元素溢出

如何在 react-native 上自动聚焦下一个 TextInput

如何使用react钩子设置状态数组

Yarn 在哪里存储离线包?

React Native:如何获取文件大小、mime 类型和扩展名?

自定义标签栏react Navigation 5

删除某些屏幕的顶部导航栏

React Native Build Error on IOS - typedef 用不同类型重新定义('uint8_t'(又名'unsigned char')与'enum clockid_t')

Super expression must either be null or a function, not undefined

如何从 react-native-fbsdk 获取用户信息(邮箱、姓名等)?

如何在 React Native 中强制禁用 iOS 暗模式