ReactJS - 协调机制 (Reconciliation)



协调机制是 React 库内部的一个流程。众所周知,React 应用会创建一个虚拟 DOM,然后根据虚拟 DOM 更新应用的实际 DOM。每当 React 接收到更新请求时,它都会首先创建一个虚拟 DOM,然后使用不同的 diff 算法将虚拟 DOM 与先前状态进行比较,只有在绝对必要时,才会更新 DOM。

尽管 diff 算法和更新 DOM 是 React 核心内部的,但了解一些内部机制将有助于我们调整应用,以最大限度地利用 React 库。

Diff 算法

本章让我们了解 React 核心应用的一些 diff 算法。

  • 相同类型的元素

  • 每当 React 组件将元素从一种类型更改为另一种类型(例如,从 div 更改为更具体的 p)时,整个 React 虚拟 DOM 树都会发生更改,并触发 DOM 更新。

<!-- Before -->
<div>
   <Content />
</div>
<!-- After -->
<p>
   <Content />
</p>

此处,整个元素将被更新。

  • 相同类型的 DOM 属性。

  • 当元素类型相同时,React 会检查属性是否存在差异。如果 React 发现属性及其值的任何新更改,则它只会更新已更改的属性。

<!-- Before -->
<div className="someClass">
   <Content />
</div>
<!-- After -->
<div className="someOtherClass">
   <Content />
</div>

此处,只会更新 DOM 实例的 class 属性。

  • 相同类型的 DOM 属性(样式)。

  • 当元素类型相同时,并且 React 发现样式属性存在差异时,它只会更新样式的属性。

<!-- Before -->
<div style={{fontFamily: 'Arial'}} />
   <p> ... </p>
</div>
<!-- After -->
<div style={{color: 'red', fontFamily: 'Arial'}} />
   <p> ... </p>
</div>

此处,只会更新 div 元素样式的 color 属性。

  • 相同类型的组件元素 - 每当 React 看到相同类型的 React 组件时,它都会调用组件的 componentWillUpdate 事件和其他更新事件以更新其状态。然后,它将调用组件的 render 方法,算法会递归。

  • 相同类型的子元素集合 - 每当 React 看到相同类型的子元素集合时,它会按顺序检查元素是否存在差异。因此,如果我们有一个新的第一个子元素,则整个集合将被更新。

<!-- Before -->
<ul>
   <li>Peter</li>
   <li>Olivia</li>
</ul>
<!-- After -->
<ul>
   <li>John</li>
   <li>Peter</li>
   <li>Olivia</li>
</ul>

由于第一个元素 (li) 已更新,因此此处将更新所有元素(ul 元素的子元素)。

为了解决这个问题,我们可以引入一个 key 属性,如下面的代码片段所示。React 有一个专门为此目的的 key 属性。

<!-- Before -->
<ul>
   <li key="1">Peter</li>
   <li key="2">Olivia</li>
</ul>
<!-- After -->
<ul>
   <li key="3">John</li>
   <li key="1">Peter</li>
   <li key="2">Olivia</li>
</ul>

总结

React 尝试在每个版本中优化 diff 算法,以确保更新次数最少。更新次数越少,应用程序的性能越好。了解内部机制并遵循最佳实践进行编码,我们可以成倍地提高应用程序的性能。

广告