直接操做DOM必定比虛擬DOM操做耗時,diff算法,key值,虛擬 DOM的定義

直接操做DOM必定比虛擬DOM操做耗時嗎?算法

或者一次直接DOM操做必定比一次虛擬DOM操做耗時嗎?segmentfault

 

1)虛擬DOM的本質就是一個JS對象,虛擬DOM減小了真實DOM的操做,當修改數據的時候,就是修改虛擬DOM產生全新的虛擬DOM,數組

新舊虛擬DOM使用diff算法,獲得patch(也就是須要修改的部分),而後將這個patch打到瀏覽器的DOM上瀏覽器

(減小重繪和迴流,從而達到性能優化的目的)緩存

2)每次DOM操做會引發重繪或者回流,頻繁的真實DOM的修改會觸發屢次的排版和重繪至關耗性能(徹底增刪改)性能優化

 

一)、虛擬DOMdom

1)DOM的本質是什麼?異步

DOM是瀏覽器中的概念,用js對象表示頁面上的元素,並提供操做DOM對象的API性能

 

2)React中的虛擬DOM是什麼?優化

虛擬DOM就是一個JS對象(數據+JXS模板),用一個js對象來描述真實的DOM

 

虛擬DOM爲何會提升性能?
虛擬DOM提升性能,不是說不操做DOM,而是減小操做DOM的次數,減小回流和重繪

虛擬 dom 至關於在 js 和真實 dom 中間加了一個緩存,利用 dom diff 算法避免了沒有必要的 dom 操做,從而提升性能

1)用 JavaScript 對象結構表示 DOM 樹的結構;

2)而後用這個樹構建一個真正的 DOM 樹,插到文檔當中

3)當狀態變動的時候,從新構造一棵新的對象樹

4)而後用新的樹和舊的樹進行比較,記錄兩棵樹差別

5)把 2所記錄的差別應用到步驟 2)所構建的真正的 DOM 樹上,視圖就更新了

 

使用diff算法比較新舊虛擬DOM----即比較兩個js對象不怎麼耗性能,而比較兩個真實的DOM比較耗性能,從而虛擬DOM極大的提高了性能

 

虛擬DOM發生比對的時機:當數據發生變化的時候會發生虛擬DOM的比對(props和state發生變化,而props的變化是父組件的state發生變化,歸根結底就是調用setState()的時候state發生變化,而後虛擬DOM發生比對)。

setState()方法是異步的,從而提高性能-----例如調用3次setState()變動數據,而調用時間間隔小,React能夠將3次setState合併成一次setState,只作一次虛擬DOM比對,而後對DOM更新,從而省去兩次額外虛擬DOM比對的性能損耗

 

調用setState()以後發生了什麼?

1)首先,React 將setState()方法中傳入的參數對象與組件當前的狀態合併

2)而後,觸發調和過程(Reconciliation)

3)通過調和過程後,React 會以相對高效的方式,根據新的狀態構建 React 元素樹

4)在 React 獲得元素樹以後,React 會自動計算出新的樹與老樹的節點差別,而後根據差別對界面進行最小化重渲染。

在差別計算算法中,React 可以相對精確地知道哪些位置發生了改變以及應該如何改變,這就保證了按需更新,而不是所有從新渲染。

 

 

3)虛擬DOM的目的?

實現頁面中DOM元素的高效更新

 

二)、diff算法:同層比對,列表使用不一樣的key值

 

  • 把樹形結構按照層級分解,只比較同級元素。
  • 給列表結構的每一個單元添加惟一的 key 屬性,方便比較。
  • React 只會匹配相同 class 的 component(這裏面的 class 指的是組件的名字)
  • 合併操做,調用 component 的 setState 方法的時候, React 將其標記爲 dirty.到每個事件循環結束, React 檢查全部標記 dirty 的 component ,而後從新繪製.
  • 選擇性子樹渲染。開發人員能夠重寫 shouldComponentUpdate 提升 diff 的性能
  •  

React的DOM是同層比對的

diff算法指的就是兩個虛擬DOM做比對,在diff算法中有個概念就是同級比對,首先比對頂層虛擬DOM節點是否一致,若是同樣就接着比對下一層,若是不同,就中止向下比對,將原始頁面中這個DOM及 下面的DOM所有刪除掉,從新生成新的虛擬DOM,而後替換掉原始頁面的DOM

存在問題:若是第一層虛擬DOM節點不一樣,下面的都同,使用虛擬DOM的diff算法,則這些節點都不能使用了,會形成從新渲染的浪費。

優勢:同層虛擬DOM比對,只須要一層層的比較,算法簡單,比對的速度快

雖然會形成從新渲染的浪費,可是會大大減小兩個虛擬DOM比對的性能消耗

 

列表中的元素使用不一樣的key

虛擬DOM中的列表中同級元素的key值要不一樣,使用diff算法,判斷哪些元素是增刪改,從而提升性能

列表中key的做用:

1)key是React用於跟蹤哪些元素是增長、刪除、修改的輔助標記,須要保證在同級元素中key的惟一性

2) React Diff 算法藉助元素的 Key 值判斷元素是新增、刪除、修改,從而減小沒必要要的元素重渲染。

3)React 還須要藉助 Key 值來判斷元素與本地狀態的關聯關係

 

問題:在循環中key值最好不要用index的緣由?

若是key值使用index的話,就可能沒法使原始的虛擬DOM中的key值和新的虛擬DOM中的key值一致,從而不能充分發揮diff算法的優點。

好比一個數組裏有數據a  b   c,用index表示的key分別爲0  1   2

當刪除a時,b  c的key分別爲0    2,從而致使元素的新舊key值不同,即key值不穩定,因此key值就失去其存在的意義了

比較合適的key值有:id或者不同的內容

 

 

 

1)tree diff

新舊兩顆DOM樹,逐層對比的過程,就是Tree Diff;當整顆DOM樹逐層對比完畢,則全部按需更新的元素都能找到

 

2)component  diff

在進行Tree Diff的時候,每一層中,組件級別的對比,叫作Component Diff

若是對比先後,組件類型相同,則暫時認爲此組件不須要更新;

若是對比先後,組件類型不一樣,則須要移除舊組件。建立新組建,並追加到頁面上

 

3)element  diff

 在進行組件對比的時候,若是兩個組件類型相同,則須要進行元素級別的對比,這叫作element diff

相關文章
相關標籤/搜索