當前位置:編程學習大全網 - 源碼下載 - React之Diff算法

React之Diff算法

diff算法的作用

計算出Virtual DOM中真正變化的部分,並只針對該部分進行原生DOM操作,而非重新渲染整個頁面。

傳統diff算法

通過循環遞歸對節點進行依次對比,算法復雜度達到 O(n^3) ,n是樹的節點數,這個有多可怕呢?——如果要展示1000個節點,得執行上億次比較。。即便是CPU快能執行30億條命令,也很難在壹秒內計算出差異。

diff算法

React 通過制定大膽的策略,將 O(n^3) 復雜度的問題轉換成 O(n) 復雜度的問題。

diff 策略

兩棵樹只會對同壹層次的節點進行比較。

既然 DOM 節點跨層級的移動操作少到可以忽略不計,React只會對同級節點進行比較。當發現節點已經不存在,則該節點及其子節點會被完全刪除掉,不會用於進壹步的比較。這樣只需要對樹進行壹次遍歷,便能完成整個 DOM 樹的比較。

最高效的算法應該是直接將 A 子樹移動到 D 節點,但這樣就涉及到跨層級比較,時間復雜度會陡然上升。React 的做法比較簡單,它會先刪除整個 A 子樹,然後再重新創建壹遍。結合到實際的使用場景,改變壹個組件的從屬關系的情況也是很少的。

註意:在開發組件時,保持穩定的 DOM 結構會有助於性能的提升。例如,可以通過 CSS 隱藏或顯示節點,而不是真的移除或添加 DOM 節點。

同樣道理,當 D 組件改為 G 組件時,整棵 D 子樹也會被刪掉,E、F 節點會重新創建。

三種方法:插入,移動,刪除

INSERT_MARKUP插入,新的 component 類型不在老集合裏, 即是全新的節點,需要對新節點執行插入操作。

MOVE_EXISTING移動,在老集合有新 component 類型,且 element 是可更新的類型,這種情況下 prevChild=nextChild,就需要做移動操作,可以復用以前的 DOM 節點。

REMOVE_NODE刪除,老 component 類型,在新集合裏也有,但對應的 element 不同則不能直接復用和更新,需要執行刪除操作,或者老 component 不在新集合裏的,也需要執行刪除操作。

對於列表的 Diff,節點的 key 有助於節點的重用:

如上圖所示,當沒有 key 的時候,如果中間插入壹個新節點,Diff 過程中從第三個節點開始的節點都是刪除舊節點,創建新節點。當有 key 的時候,除了第三個節點是新創建外,第四和第五個節點都是通過移動實現的。

為什麽會有上述兩種情況的區別呢?

對於第壹種情況:

key = {index}在更新前後是相同的,都是1,2,3

但是對比,key相同時,元素不同,則刪除插入

對於第二種情況;

key = {item} key分別是 'll','ww','kk' ,更新後虛擬dom key分別是kk ll ww,在進行element diff時,發現kk元素節點在更新前後是相同的,無需創建,會進行移動

說明:

對於第壹種情況,其實和沒有key是壹樣的,除非其順序和key保持壹致;

針對這壹現象,React 提出優化策略:允許開發者對同壹層級的同組子節點,添加唯壹 key 進行區分,雖然只是小小的改動,性能上卻發生了翻天覆地的變化!

  • 上一篇:winform webbrowser 如何控制新窗口打開和通過windowns.open()方式打開?
  • 下一篇:什麽是單峰密度?
  • copyright 2024編程學習大全網