Vue 虛擬節點及diff演算法詳解

2021-10-07 22:51:55 字數 1860 閱讀 1436

vue進入2.0以來在其內部加入了虛擬dom的實現,減少了dom的操作,極大提高了效能,同時其diff演算法的時間複雜度為o(n),效能很高。

首先我們來看下什麼是虛擬dom(virtual dom ),虛擬dom就是提通過js生成乙個dom物件,之後通過diff演算法比較之後生成patch,即補丁,之後虛擬dom通過補丁更新,再渲染成真實dom顯示出來,可以看到只涉及到了一次dom操作,效率、效能無疑很高。

具體實現步驟:

明白了虛擬節點之後我們就以下面**為例來詳細說明下diff的具體操作:

在vue中就會生成虛擬dom結構,大概結構如下:

}]  },

}] },

}] },

]}

假如此時我們對當前dom結構進行reverse操作的話,就會變成以下節點樹:

}]  },

}] },

}] },

]}

此時就進入了本節的重點,新舊虛擬節點樹的diff,我們可以分析下原始碼實現:

src/core/vdom/patch.js

updatechildren方法

let oldstartidx = 0 // 舊節點起始位置

let newstartidx = 0 // 新節點起始位置

let oldendidx = oldch.length - 1 // 舊節點結束位置

let oldstartvnode = oldch[0]

let oldendvnode = oldch[oldendidx]

let newendidx = newch.length - 1 // 新節點結束位置

let newstartvnode = newch[0]

let newendvnode = newch[newendidx]

let oldkeytoidx, idxinold, vnodetomove, refelm

while (oldstartidx <= oldendidx && newstartidx <= newendidx)
// 當前舊開始節點是否存在,沒有的話初始節點的指向往後移動

if (isundef(oldstartvnode)) else if (isundef(oldendvnode))

else if (samevnode(oldstartvnode, newstartvnode))  else if (samevnode(oldendvnode, newendvnode))
else if (samevnode(oldstartvnode, newendvnode))  else if (samevnode(oldendvnode, newstartvnode))
else  else  else 

}newstartvnode = newch[++newstartidx]

}

if (oldstartidx > oldendidx)  else if (newstartidx > newendidx)
function samevnode (a, b)
通過上述詳細解析我們會發現,之前的例子中dom的reverse操作基本不會涉及到到dom元素的建立,全部復用之前那的dom,因此效能較好。

vue 虛擬dom 和 diff 演算法

虛擬dom其實就是乙個js物件,就是用物件的方式取代真實的dom操作,把真實的dom操作放在記憶體當中,在記憶體中的物件裡做模擬操作。當頁面開啟時瀏覽器會解析html元素,構建一顆dom樹,將狀態全部儲存起來,在記憶體當中模擬我們真實的dom操作,操作完後又會生成一顆dom樹,兩顆dom樹進行比較,...

Vue虛擬Dom和diff演算法

到底什麼是虛擬dom呢?誕生的原因舉個栗子 就是下圖所示的這個,詳細的闡述了模板 渲染函式 虛擬dom樹 真實dom的乙個過程 虛擬dom的最終目標是將虛擬節點渲染到檢視上。但是如果直接使用虛擬節點覆蓋舊節點的話,會有很多不必要的dom操作。例如,乙個ul標籤下很多個li標籤,其中只有乙個li有變化...

react 虛擬DOM及diff演算法

在vue,react這些框架中,都是通過監聽資料的變化而相應的去渲染我們的檢視.但是如果每次修改資料就去操作一次dom樹,這在效能上無疑是大打折扣的.虛擬dom的出現就是為了解決這個問題,並且起到協調的作用.本質上就是在js和真實dom樹之間做了乙個快取,具體原理是 每次當資料發生變化時,渲染機制先...