虚拟 DOM - React JS 中的差异制造者
介绍
当今网站面临的最大挑战之一是响应时间。具体来说,就是用户能够多快导航到网页并完成任务。随着许多 UI 库的出现,它们每个都试图以独特的方式解决上述问题。在本指南中,您将看到 React 如何使用称为虚拟 DOM 的概念解决此问题,以及该算法如何使 React JS 成为众多 UI 库中最受欢迎的一个。
快速类比
在深入讨论技术细节之前,让我们先快速地类比一下虚拟 DOM。想象一对情侣要去参加派对。两人都花了充足的时间打扮得漂漂亮亮,以适应派对,并处理一些小细节。当他们走出房间看到最好的朋友时,她给了她一个快速的建议,让她戴上一件不同的珠宝。想象一下,如果她回到房间,从头开始化妆,而不是只换珠宝。当 UI 尝试重新绘制整个网页以进行小改动,而不是只更新网页的那部分时,就会发生这种情况。
什么是虚拟 DOM?
首先,重要的是要了解虚拟 DOM 不是一种规范,它只是与 DOM 交互的最佳方式。虚拟 DOM 是整个 HTML 文档的 JavaScript 对象表示。为了与此对象模型交互,每个库都有自己独特的实现方式,以提高网页渲染和重新渲染的性能。
虚拟 DOM 与真实 DOM
如果更新 DOM 对象很慢,那么是什么让更新虚拟 DOM 更快呢?虚拟 DOM 不是另一个 DOM 对象吗?当然是。虚拟 DOM 只是另一个 DOM 对象。但它与呈现它的网页没有紧密耦合。让我们看看幕后发生了什么。
您看到的每个网页都有一个等效的 DOM 表示,即包含所有 UI 组件的树结构。对于 UI 状态的任何细微更改,都需要更改其对应的 DOM 表示,并且需要重新渲染 UI。更新 DOM 本身并不是一个昂贵的过程,但渲染和重新渲染 UI 才是其昂贵的原因。考虑到我们现在看到的大多数 SPA(单页应用程序)的大小,不是元素的复杂性,而是包含这些元素的树结构的大小使得渲染 UI 耗时。
使用虚拟 DOM 进行优化
在任何时间点,React 库都会维护虚拟 DOM 的两个副本;我们将其中一个称为原始版本,另一个称为脏版本。每当 UI 中的状态发生变化时,React 都会跟踪更改并开始批处理它们。这些更改不会应用于实际 DOM,而是应用于虚拟 DOM 的脏版本。在 React 确定的特定时间,它将在原始版本和脏版本之间执行 diff 操作并计算增量。稍后,此增量将应用于真实 DOM,以便只更新网页的所需部分,而不是重新绘制整个网页。
让我们更深入地解释一下,看看幕后发生了什么。以下是 React 渲染算法的关键操作。
高效的 diff 算法
对 render() 方法的任何调用都会创建一个 React 元素树。如果状态发生变化并再次调用 render() 方法,它将返回不同的 React 元素树。现在,挑战是有效地更新 UI 以匹配新生成的树。对于具有“n”个元素的树,复杂度为 O(n3)。React 根据两个假设实现了优化的 O(n) 算法:
- 不同类型的元素会产生不同的树结构。
如果根元素的类型不同,React 将用新树替换旧树元素。如果两个 React 元素的类型相同,它将比较属性并仅更新已修改的属性。让我们看一个打印“I love ReactJS”的简单 React 组件。如果我们更改
class Hello extends React.component {
render() {
return(
<div className="test1">
<Hello />
</div>
)
}
}
function Hello() {
return <h1>I love ReactJS</h1>;
}
- Using a key prop to hint the child elements that may be stable across different renders.
While generating the diff between the dirty and pristine virtual DOM, React just iterates over both the tree parallelly and generates a mutation when it finds a difference. So, if the developer can hint React using the keys attribute to identify an element, React will use this key to match the elements between two trees and minimize unnecessary mutations.
Breadth-First Search
React traverses the DOM tree using the breadth-first search algorithm. In this algorithm, nodes are traversed from top to bottom and left to right. If React finds any element that is modified, it will, by default, re-render that subtree without proceeding pain further to check the depth of the tree.
In the above example of a DOM tree, though both elements B and B11 are modified, once React finds that element B is modified, it will flag the tree and the subtree underneath is modified.
Batched Update Operations
We need to remember that JavaScript is a single thread model and all the events that happen against a DOM tree are added to call stack and the event loop executes the calls that are added. The key is, no matter how many times setState() is called against a component, inside a React event handler, they will produce only a single re-render at the end of the event.
Conclusion
By leveraging the above algorithms in an efficient way, we can safely say that React has an almost perfected UI rendering using virtual DOM and the proof of this is in the number of companies that have been adopting React and the continuous growth in its adoption in the last few years.
免责声明:本内容来源于第三方作者授权、网友推荐或互联网整理,旨在为广大用户提供学习与参考之用。所有文本和图片版权归原创网站或作者本人所有,其观点并不代表本站立场。如有任何版权侵犯或转载不当之情况,请与我们取得联系,我们将尽快进行相关处理与修改。感谢您的理解与支持!
请先 登录后发表评论 ~