React 虛擬 Dom 和 diff 算法

React將DOM抽象爲虛擬DOM, 而後經過新舊虛擬DOM 這兩個對象的差別(Diff算法),最終只把變化的部分從新渲染,提升渲染效率的過程; (概念講完再描述一遍)javascript

JS對象2Html.png

JS對象2HTML完整版.png

虛擬DOM的算法步驟.png

一句話: 用 JS 對象的形式,來表現一棵真是的 DOM 樹;java


Diff 算法

    • 當你實際開發使用React的時候,在某個時間點 render() 函數建立了一棵React元素樹,也就模擬一個虛擬 DOM 樹,
    • 在下一個state或者props更新的時候,render() 函數將建立一棵新的React元素樹, 也就模擬了一個新的虛擬 DOM 樹,
    • 既然模擬出了新舊兩棵DOM 樹, 那麼如何高效的進行新舊兩棵樹的對比呢??
    • 固然是使用 DIff 算法...
  1. 傳統的 Diff 算法也是一直都有的;算法

    • 可是它的時間複雜度爲O(n^3) 意思是: 在React中更新10個元素則須要進行1000次的比較。(1000個===10億)
  2. React 經過制定大膽的策略,將 O(n^3) 複雜度的問題轉換成 O(n^1=n) 複雜度的問題。bash

      1. 兩個不一樣類型的元素會產生不一樣的樹
      1. 對於同一層級的一組子節點,它們能夠經過惟一 key 進行區分
    • 基於以上兩個前提策略,React 分別對 tree diff、component diff 以及 element diff 三種 diff 方法是 進行算法優化,
    • 下面介紹優化後的幾種算法

Tree Diff

概念: 將新舊兩顆虛擬 DOM 樹,按照層級對應的關係,從頭至尾的遍歷一遍,,就能找到那些元素是須要更新的,這種方式: Tree Diff函數

Tree Diff 01.png

1 只會對相同顏色方框內(同級)的DOM節點進行比較,即同一父節點下的全部子節點
2 當發現節點已經不存在,則該節點及其子節點會被徹底刪除掉,不會用於進一步的比較
複製代碼

Tree Diff 02.png

  • 執行過程:create A -> create B -> create C -> delete A

Component Diff

不一樣組件之間的對比 概念: 在對比每個層級的時候,會有本身的組件,這種組件的對比方式就叫: Component Diff ;性能

​ 這種對比方法其實比較的就是類型.↓↓↓優化

  • 若是類型相同,暫時不更新,spa

  • 若是類型不相同,就須要更新; ( 刪除舊的組件,再建立一個新的組件,插入到刪除組件的那個位置)code

Component Diff 01.png

  • 執行過程:delete D -> create G

Element Diff

同一層級中元素之間的對比
概念: 在類型相同的組件內, 再繼續對比組件內部的元素,查看內部元素是否相同,若是須要修改,找到須要修改的元素,進行鍼對性的修改! 這種方式就叫: Element Diffcomponent

三種節點操做:
1 INSERT_MARKUP(插入)
2 MOVE_EXISTING(移動)
3 REMOVE_NODE(刪除)

INSERT_MARKUP:新的 component 類型不在老集合裏,須要對新節點執行插入操做。

MOVE_EXISTING:老的集合包含新的 component 類型,就須要作移動操做,能夠複用之前的 DOM 節點。

REMOVE_NODE:老的 component 不在新集合裏的,須要執行刪除操做 或者 老的 component 類型在新集合裏也有,但對應的 element 不一樣則不能直接複用和更新,須要執行刪除操做
複製代碼

Element Diff 01.png

  • 執行過程:B != A,則建立並插入 B,刪除 A;以此類推,建立並插入 A、D、C,刪除 B、C、D

    Element Diff 02.png

  • 執行過程:B、D 不作任何操做,A、C 進行移動操做


diff 算法總結:

  1. 保持完整的結構,有利於性能的提高

  2. 儘可能使用相同類型的組件

  3. 在進行 Element 或Component 級別對比的時候,爲了提升對比的效率, React 推薦咱們爲每一個 for 循環建立出來的元素或者組件,提供一個惟一的 key;

  4. Tree diff :將新舊兩棵 DOM 樹,按照層級對應的關係,這樣只須要對樹進行一次遍歷,就可以找到哪些元素是須要更新的;

  5. Component Diff: 在對比每一層的時候,每一層都有本身的組件, 那麼組件之間的對比,叫作 Component diff , 對比的方式,就是查看兩個組件的類型是否相同,若是相同,則暫時認爲不須要更新,若是類型不一樣,則表示更新(先把舊的組件刪除,再建立一個新的組件,插入到剛纔刪除的位置);

  6. Element Diff:若是新舊 DOM 樹中的組件類型相同,會繼續比較這兩個組件內部的元素是否也相同,若是元素髮生了改變,則找到須要修改的元素,有針對性的修改,這種組件內部元素級別的對比叫: Element Diff;

相關文章
相關標籤/搜索