DIFF算法淺析(一)概念


在虛擬dom中diff的實現。

分別從3個方面:

  1. DIFF抽象概念(概述、時間復雜性分析、對比總結)

  2. 在Vue2中的實現(版本2.6.11、必要性、執行方式)

  3. 在React中的實現(版本16.13.1,必要性、執行方式)

1. DIFF抽象概念

diff是廣泛的概念,如git diff,js對象 diff等。兩棵樹做diff,即虛擬DOM中的diff算法。

diff算法的必要性:渲染真實DOM的開銷是很大的,輕微的操作都可能導致頁面重新排版,非常耗性能。 相對於DOM對象,js對象處理起來更快,而且更簡單。 通過diff算法對比新舊vdom之間的差異,可以批量的、最小化的執行 dom操作,從而提高性能。

 

diff時間復雜度分析:

常規:O(n^3) 遍歷樹1; 遍歷樹2; 排序; 1000個節點,十億的量級。

優化:O(n) 只比較同一層級 ;tag不相同,直接刪掉重建; 通過key來標識區分相同節點。

 

1. 只比較同一層級。

Web UI 中 DOM 節點跨層級的移動操作特別少,可以忽略不計。

如圖左,只比較同一層級的,即相同顏色的層級。如右圖,左側P3在右側的P標簽下,不做移動,而是做新增操作和刪除操作。

 

2.tag不相同,直接刪掉重建。

擁有不同類型的兩個組件將會生成不同的樹形結構。

如上圖,D和G節點的子節點相同,但是tag不同,則整棵樹都重新刪除重建。

 

3.通過key來標識區分相同節點。

開發者可以通過 key prop 來暗示哪些子元素在不同的渲染下能保持穩定。

左圖沒有key值,所以老的節點全部刪除,新的節點再全部創建。右圖添加key值,所以只需要醬A移動到B,將C移動到D,就可以得到與新樹一樣的老樹。

 

對比

相同點: 深度優先、同層級比較。 tag不同默認不同。 都借助key。 都有批量新增和刪除等。

不同點: 架構不同,React基於fiber鏈表結構實現,不能雙向查找。Vue基於數組,可以很方便通過下標查找。 react的設計一開始就有,vue演進過程中才出現的。

diff算法總結(5w1h)

what: 是一種對新舊虛擬DOM樹進行比較,得出兩者差異,確定最小DOM更新操作的算法。

why: 減少渲染真實DOM的開銷,提高性能。

When: 頁面更新,重新渲染時用到。

where: Vue中當數據發生改變時,set方法會讓調用Dep.notify通知所有訂閱者Watcher,訂閱者就會調用patch給真實的DOM打補丁。React在下一次 state 或 props 更新時, render()方法會返回一棵不同的樹。在構建fiber時,標記effectTag為Placement、Update、Deletion等。在commitWork構建真實DOM時,按照effectTag規則生成DOM。

Who: Vue(patch、patchVnode、updateChildren)。React(reconcileChildFibers、reconcileChildrenArray、updateHostComponent等)。 how: 深度優先、同層比較。tag不同,生成樹形結構不同。使用key來標識穩定節點。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM