snabbdom 虛擬Dom diff演算法

2021-10-19 05:04:59 字數 2019 閱讀 3908

虛擬dom中的diff演算法:

渲染真實dom的開銷很大,dom操作會引起瀏覽器的重排和重繪,也就是瀏覽器的重新渲染,瀏覽器的重新渲染頁面十分耗效能,因為要重新繪製整個頁面,當資料變化後,尤其大量資料變化後,比如列表中的資料,如果直接操作dom的話,會讓瀏覽器重新渲染整個列表。虛擬dom中diff的核心是當資料變化後不直接操作dom,而是用js物件描述真實dom,當資料變化後會先比較js物件是否發生變化,找到發生變化的位置,只去最小化的更新變化的位置,從而提高效能。

虛擬dom的diff演算法用來查詢兩棵樹上每乙個節點的差異。diff演算法有很多實現方式,傳統的diff演算法是把第一棵樹上的每乙個節點一次去跟第二棵樹上的每乙個節點去對比,如果有n個節點會對比n的平方次。

在對開始和結束節點比較的時候,總共有四種情況

呼叫 patchvnode() 對比和更新節點

把舊開始和新開始索引往後移動 oldstar++ oldend++

首先根據索引找到舊開始節點和新開始節點,呼叫samevnode方法判斷新舊節點是不是samevnode,即比較 key 和 sel 是否相同 ,如果相同,呼叫 patchvnode 去比較兩個節點內部的差異,然後更新到真實dom。比較完成後,索引移動位置,移動到第二個節點開始比較。把第二個節點作為開始節點比較。

如果開始節點不是 samevnode ,則開始從後往前比較。

比較舊的結束節點和新的結束節點,如果是 samevnode , 呼叫patchvnode方法去比較兩個節點內部的差異,然後更新到真實dom。索引位置往前移動,繼續比較。

注意:這裡兩個節點相同的話,會重用之前舊節點的dom元素,呼叫patchvnode比較的時候,會把差異更新到重用的dom元素上,這個差異可能是文字內容不同或者子元素不同,而當前dom是不用重新建立的。如果文字內容和子元素都相同,是不會進行dom操作的,虛擬dom就是通過這種方式提高效能的

呼叫 patchvnode() 對比和更新節點

把 oldstart 對應的dom元素,移動到右邊,更新索引

比較舊的開始節點和新的結束節點,如果是 samevnode , 呼叫patchvnode方法去比較兩個節點內部的差異,然後更新到真實dom。舊的開始節點索引位置移到最右邊,更新索引,舊開始節點索引移到2也就是下乙個節點,新結束節點往前移動,到5,繼續比較。

呼叫 patchvnode() 對比和更新節點

把oldend對應的dom元素,移動到左邊,更新索引

比較舊的結束節點和新的開始節點,如果是 samevnode , 呼叫patchvnode方法去比較兩個節點內部的差異,然後更新到真實dom。舊的結束節點索引位置移到最前邊,更新索引,舊結束節點索引移到5也就是前乙個節點,新開始節點往後移動,到2,繼續比較。

如果以上條件都不滿足,說明開始節點和結束節點都不相同

遍歷新的開始節點,在舊節點陣列中來查詢是否有相同key值得節點,如果沒有找到,則說明此時的開始節點是乙個新的節點,此時要建立新的dom元素,插入到最前面的位置;

如果新開始節點在舊節點陣列中找到了具有相同key值得節點,並且要判斷新舊節點的sel屬性是否相同,如果sel不相同,不是相同節點的話,要建立新的dom元素,把他插入到最前面的位置;如果sel相同,是相同節點,把找到的這個舊節點賦值給 elmtomove 這個變數,然後通過patchvnode這個方法去比較兩個節點內部的差異,更新真實dom,並把elmtomove這個變數節點插入到最前面的位置。

diff演算法(參考snabbdom庫)

snabbdom 是乙個虛擬 dom 庫,專注提供簡單 模組性的體驗,以及強大的功能和效能,據說vue的diff演算法就是參考它的。這裡記錄一下我這幾天學習snabbdom diff演算法的心得和感悟。我是這樣理解的虛擬dom的,虛擬dom就是將真實dom抽象成乙個物件。當我們要多次操 作dom的時...

snabbdom 原始碼除錯總結

在vue.js 中的虛擬 dom 借鑑了 snabbdom,目的是為了讓開發人員避免複雜的 dom 操作也為了跨不同平台。使用 virtual dom,在首次渲染的時候會影響效能因為要建立額外的物件來描述真實 dom,在更新少量標籤的時候也不會有效能上的提公升,在 dom 結構複雜的時候更新 dom...

3 1 11 Snabbdom 的基本使用

md snabbdom demo cd snabbdom demo yarn init y yarn add parcel bundler scripts index.html package.json src 01 basicusage.js lang en charset utf 8 name ...