1. 程式人生 > 實用技巧 >深度解析dom diff演算法(一)

深度解析dom diff演算法(一)

最近公司內部正好要準備技術分享,所以花了大概三個月的時間去學習關於domdiff演算法的知識,文章會結合原始碼和圖片儘量的深入淺出,把整個過程說的明白、講的清晰。

文章分三篇:

  • 認識virtual dom && diff演算法演進史
  • react的dom diff策略
  • vue的dom diff策略

什麼是virtual dom?

簡單一句話,就是用javascript模擬出來的dom物件

為什麼要有virtual dom?

1、實際應用中會頻繁操作dom節點
2、操作dom節點的成本很高(jquery時代),每次操作會導致頁面的重繪和重排
3、而單純操作js的成本很低(v8引擎),如果能利用js從而有效減少重繪重排的次數,那麼我們頁面效能會大幅度提升

dom diff演算法是什麼?

因為有了vdom,那怎麼樣才能減少節點操作的次數,diff演算法就應運而生了。它的核心功能就是對比操作前後兩個dom樹和節點的異同,將差異記錄到差異patch佇列中最後將更新一步到位。整個diif流程分為三步,如下圖,patch就是將記錄的差異佇列同步到真實dom的過程。

在這裡插入圖片描述

dom diff演算法演進史

有夥伴想做深入研究的話可以去看看每種演算法的原始碼,我們核心講解vue和react的diff實現,相關連結在文章末尾,這裡要強調一點的是我們目前主流前端框架的diff演算法都是在snabbdom.js基礎上優化來的。

在這裡插入圖片描述

傳統diff演算法

傳統diff演算法就是將新舊兩棵樹的節點依次進行對比,然後進行dom樹的更新

在這裡插入圖片描述

上圖所示,傳統diff演算法時間複雜度為O(n的三次方),原因如下,假定新舊樹的節點數目都為n:
1、新dom樹中某一個節點和舊樹所有節點依次遍歷比較,複雜度為O(n)
2、新dom總共n個節點,每個節點遍歷n次,複雜度為O(n)
3、遍歷完成發現舊dom中的某個節點被刪除/新增/更新,這裡需要進行最小距離轉換(transform cost), 時間複雜度均為O(n)。
這裡嚴格來講複雜度其實是O(m*(1+logmn)),但是我們假定這裡的前提是m=n
4、綜上,複雜度變為O(n
n*n)

前兩個n的複雜度很好理解,最後的最小轉換方式的複雜度怎麼算出來的呢?這裡涉及到了一個叫做最小編輯距離演算法,如果深入講解的話又是萬字長文。一篇有參考性的文章,有興趣的夥伴可以去研究:https://www.zhihu.com/question/66851503

參考文章連結:

https://github.com/joelrich/citojs 【cito.js】
https://github.com/snabbdom/snabbdom/blob/v0.7.3/src/snabbdom.ts#L179【snabbdom.js】