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 演算法,以確保更新次數最少。更新次數越少,應用程式的效能越好。瞭解內部機制並遵循最佳實踐進行編碼,我們可以成倍地提高應用程式的效能。

廣告