從新學習 React (二) Diffing 算法

前幾天面試問道 react 的相關知識,對我打擊比較大,感受對 react 認識很是膚淺,因此在這裏從新梳理一下,想一想以前沒有仔細思考過的東西。html

另外有說的不對的地方還請幫我指正一下,先謝謝各位啦。react

目錄索引:面試

背景

咱們知道,React 執行 Render() 函數時,會生成一次虛擬 DOM,當組件再次更新時,會再生成一顆新的樹,而後 React 會對比兩棵樹的異同,執行更新算法。React 經過以下方法比較 DOM 的異同,其複雜度爲 O(n):算法

  • 兩個不一樣類型的元素會產生出不一樣的樹
  • 開發者能夠經過 key prop 來暗示哪些子元素在不一樣的渲染下能保持穩定

Diffing 算法

當對比兩顆樹時,React 首先比較兩棵樹的根節點。不一樣類型的根節點元素會有不一樣的形態。redux

比對不一樣類型的元素

當根節點爲不一樣類型的元素時,React 會拆卸原有的樹而且創建起新的樹。舉個例子,當一個元素從 <a> 變成 <img> 或者 DOM 節點被銷燬,都會觸發一個完整的重建流程。數組

比對同一類型的元素

當比對兩個相同類型的 React 元素時,React 會保留 DOM 節點,僅比對及更新有改變的屬性。性能優化

以下所示,當更新 style 屬性時,React 僅更新有所更變的屬性,而 title 屬性不會被修改。函數

<div className="before" title="stuff" />
<div className="after" title="stuff" />
複製代碼

比對同類型的組件元素

當一個組件更新時,組件實例保持不變,這樣 state 在跨越不一樣的渲染時保持一致。React 將更新該組件實例的 props 以跟最新的元素保持一致,而且調用該實例的 componentWillReceiveProps() 和 componentWillUpdate() 方法。源碼分析

key

若是一個列表沒有 key 值,一旦數組增長或者刪除,react 就沒法知道那些元素是不變的,那些的改變了的。可是當子元素擁有 key 時,React 使用 key 來匹配原有樹上的子元素以及最新樹上的子元素。如下例子在新增 key 以後使得以前的低效轉換變得高效:post

<ul>
  <li key="2015">Duke</li>
  <li key="2016">Villanova</li>
</ul>

<ul>
  <li key="2014">Connecticut</li>
  <li key="2015">Duke</li>
  <li key="2016">Villanova</li>
</ul>
複製代碼

如今 React 知道只有帶着 '2014' key 的元素是新元素,帶着 '2015' 以及 '2016' key 的元素僅僅移動了。

結語

關於 key 值,必定要知道其做。本身在寫代碼的時候儘可能不要採用 index 或者隨機數做爲 key,由於這樣不但沒有得到 react 優化算法的加持,並且會讓本身的數據出現錯亂。

相關文章
相關標籤/搜索