1 diff演算法到底是什么?
diff演算法是一種通過同層的樹節點進行比較的高效演算法,它可以不用頻繁操作DOM,而是選用虛擬DOM節點操作,說人話就是專門用來處理虛擬DOM節點的,

2 操作流程?
為了更好理解Vue的diff演算法,請先看一位B站大佬精心制作的
影片演示,
通過上面視頻可以很好理解diff演算法的比較流程,清楚在回圈從左右兩邊向中間比較的更新、插入、洗掉、查詢操作,
它的操作本質就是:
分別遍歷新舊虛擬DOM節點的陣列,接著通過回圈左右雙指標比較判斷,
新的頭 newStartIndex 和老的頭 oldStartIndex 對比
新的尾 newEndIndex 和老的尾 oldEndIndex 對比
新的頭 newStartIndex 和老的尾 oldEndIndex 對比
新的尾 newEndIndex 和老的頭 oldStartIndex 對比

3 決議github原始碼
我看到掘金的一篇講的很不錯,可以看看,深入淺出虛擬 DOM 和 Diff 演算法,及 Vue2 與 Vue3 中的區別,我就只負責總結一下學習筆記吧,
而且它講的Vue3涉及到diff的內容也很易理解,
3.1 patch函式:對比新舊虛擬DOM
3.1.1 什么時候觸發?
在頁面首次渲染的時候會呼叫一次 patch 并創建新的 vnode,不會進行更深層次的比較,
在組件中資料發生變化時:
- 先觸發
setter然后通過Notify通知Watcher, - 對應的
Watcher會通知更新并執行更新函式,它會執行render函式獲取新的虛擬DOM, - 執行
patch對比上次渲染結果的老的虛擬DOM,并計算出最小的變化,然后再去根據這個最小的變化去更新真實的DOM,也就是視圖View
3.1.2 patch的更新流程流程(原始碼第700行)

3.2 patchVnode函式:對比節點文本變化或子節點變化
- 如果
oldVnode和vnode的參考地址是一樣的,就表示節點沒有變化,直接回傳, - 通過
oldVnode的isAsyncPlaceholder判斷注釋、v-if和異步函式的情況,選擇跳過異步組件的檢查,直接回傳, - 如果
oldVnode和vnode都是靜態節點,有相同的keyvnode是克隆節點或者v-once指令控制的節點時- 把
oldVnode.elm和oldVnode.child都復制到vnode上,然后回傳,
- 把
- 如果
vnode不是文本節點也不是注釋的情況下:- 如果
vnode文本為undefined,就刪掉vnode.elm文本 - 如果
vnode和oldVnode都有子節點,而且子節點不一樣的話,就呼叫updateChildren更新子節點 - 如果只有
vnode有子節點,就呼叫addVnodes創建子節點 - 如果只有
oldVnode有子節點,就呼叫removeVnodes洗掉該子節點
- 如果
- 如果
vnode是文本節點但是和oldVnode文本內容不一樣,就更新文本
3.3 updateChildren:對比子節點的函式
當每輪回圈對比時都不能滿足找到對應的key值與標簽值一致的情況時,那么要不斷拿 新的開始節點 的 key 去 老的開始節點的子節點 children 找,
- 如果沒找到,就創建一個新的節點
- 如果找到了,再對比標簽是不是同一個節點
- 如果是同一個節點,就呼叫 patchVnode 進行后續對比,然后把這個節點插入到 老的開始節點 前面,并且移動新的開始下標,繼續下一輪回圈對比
- 如果不是相同節點,就創建一個新的節點
- 如果老的 vnode 先遍歷完,就添加新的 vnode 沒有遍歷的節點
- 如果新的 vnode 先遍歷完,就洗掉老的 vnode 沒有遍歷的節點
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/503140.html
標籤:其他
