react diff策略

React通過引入Virtual DOM的概念,極大地避免無效的Dom操作。將時間複雜度從O3降到了O1,歸功於react的 diff策略。

實現原理:

  • Web UI中DOM節點跨層級的移動操作特別少,可以忽略不計
  • 擁有相同類的兩個組件將會生成相似的樹形結構,擁有不同類的兩個組件將會生成不同的樹形結構
  • 對於同一層級的一組子節點,它們可以通過唯一 id 進行區分

在上面三個策略的基礎上,React 分別將對應的tree diff、component diff 以及 element diff 進行算法優化,極大地提升了diff效率。

 

tree diff

React 對樹的算法進行了簡潔明瞭的優化,即對樹進行分層比較,兩棵樹只會對同一層次的節點進行比較。相同層的元素,如果是同一類元素(同一種html標籤),則不會銷燬該dom,而會根據新的dom屬性來更新舊的dom的屬性,如果不是同一種標籤則會直接銷燬並且銷燬其所有子節點,然後創建新的dom插入。

component diff

  • 如果是同一類型的組件,按照原策略繼續比較 Virtual DOM 樹即可。
  • 如果不是,則將該組件判斷爲 dirty component,從而替換整個組件下的所有子節點。
  • 對於同一類型的組件,有可能其 Virtual DOM 沒有任何變化,如果能夠確切知道這點,那麼就可以節省大量的 diff 運算時間。因此,React允許用戶通過shouldComponentUpdate()來判斷該組件是否需要進行diff算法分析,但是如果調用了forceUpdate方法,shouldComponentUpdate則失效。

element diff

當節點處於同一層級時,diff 提供了 3 種節點操作,分別爲 INSERT_MARKUP (插入)、MOVE_EXISTING (移動)和 REMOVE_NODE (刪除)。

相同的節點,僅僅是位置發生了變化,但卻需要進行繁雜低效的刪除、創建操作,其實只要對這些節點進行位置移動即可。React針對這一現象提出了一種優化策略:允許開發者對同一層級的同組子節點,添加唯一 key 進行區分

如果新舊dom樹上的同一層級裏存在相同key的dom則會直接實用原來的key的元素並且移動dom的位置,然後繼續比對dom的類型和屬性並更新,這會減少很多dom的創建和銷燬,大部分情況下是可以提高性能的,但是在極端情況下並不會帶來性能的提示,比如將最後一個元素提到第一位,react實際上是把所有前面的元素都挪了一遍位置,將它們移動到後面,如果不加key,react則只會更新最後一個dom的屬性,反而得不償失。所以在使用key的時候可以考慮下場景,是否真的能提高性能(99%的情況會提高,除非是很簡單的一個基本標籤,但這也就無所謂了,主要爲了組件的key,防止組件頻繁的創建和銷燬,因爲組件裏往往有着比較深的下級dom,全部銷燬和創建比較浪費性能,並且會觸發組件的生命週期)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章