直接操做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值
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