我找到了问题的答案。
关键是要理解 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 很快”是一个神话。