Vue原始碼之patch順口溜了解一下

藤蔓繞竹發表於2019-11-05

通過同層的樹節點進行比較而非對樹進行逐層搜尋遍歷的方式,所以時間複雜度只有O(n),是一種相當高效的演算法

Vue原始碼之patch順口溜了解一下

同層級只做三件事:增刪改。

具體規則是:

  • new VNode不存在就刪;
  • old VNode不存在就增;
  • 都存在就 比較型別,型別不同直接替換、型別相同執行更新 

兩個VNode型別相同,就執行更新操作,包括三種型別操作:屬性更新PROPS、文字更新TEXT、子節點更新REORDER

  1. 如果新舊VNode都是靜態的,那麼只需要替換elm以及componentInstance即可。

  2. 新老節點均有children子節點,則對子節點進行diff操作,呼叫updateChildren

  3. 如果老節點沒有子節點而新節點存在子節點,先清空老節點DOM的文字內容,然後為當前DOM節

    點加入子節點。

  4. 當新節點沒有子節點而老節點有子節點的時候,則移除該DOM節點的所有子節點。

  5. 當新老節點都無子節點的時候,只是文字的替換。 

⚠️  下面詮釋順口溜開啟:src/core/vdom/patch.js檔案

一、開始遊標<=結束遊標

首先oldStartVnode、oldEndVnodenewStartVnode、newEndVnode兩兩交叉比較(1-4) 

1. 舊頭對新頭,排著隊伍完後走

oldStartVnodenewStartVnode  滿足sameVnode,直接將該 VNode節點進行patchVnode即可,不需再遍歷就完成了一次迴圈 

Vue原始碼之patch順口溜了解一下

Vue原始碼之patch順口溜了解一下


2. 舊尾對新尾,拉著尾巴順著走

當 oldEndVnodenewEndVnode滿足sameVnode,直接將該 VNode節點進行patchVnode即可,不需再遍歷就完成了一次迴圈 

Vue原始碼之patch順口溜了解一下

Vue原始碼之patch順口溜了解一下


3. 舊頭對新尾,按著新尾排排隊

如果oldStartVnodenewEndVnode滿足sameVnode。說明oldStartVnode已經跑到了oldEndVnode 後面去了,進行patchVnode的同時還需要將真實DOM節點移動到oldEndVnode的後面。 

Vue原始碼之patch順口溜了解一下

Vue原始碼之patch順口溜了解一下


4. 舊尾對新頭,揪著舊尾前面走

如果oldEndVnodenewStartVnode滿足sameVnode,說明oldEndVnode跑到了oldStartVnode的前面,進行patchVnode的同時要將oldEndVnode對應DOM移動到oldStartVnode對應DOM的前面。 

Vue原始碼之patch順口溜了解一下

Vue原始碼之patch順口溜了解一下

5. 綜上皆無果,老實迴圈接個來

如果以上情況均不符合,則在old VNode中找與newStartVnode滿足sameVnodevnodeToMove,若 存在執行patchVnode,同時將vnodeToMove對應DOM移動到oldStartVnode對應的DOM的前面。 

Vue原始碼之patch順口溜了解一下

當然也有可能newStartVnode在old VNode節點中找不到一致的key,或者是即便key相同卻不是 sameVnode,這個時候會呼叫createElm建立一個新的DOM節點放到old VNode最前面。 

Vue原始碼之patch順口溜了解一下

Vue原始碼之patch順口溜了解一下

二、老遊標先結束oldStartIdx > oldEndIdx批量新增

當結束時oldStartIdx > oldEndIdx,這個時候舊的VNode節點已經遍歷完了,但是新的節點還沒有。說 明瞭新的VNode節點實際上比老的VNode節點多,需要將剩下的VNode對應的DOM插入到真實DOM 中,此時呼叫addVnodes(批量呼叫createElm介面)。 

Vue原始碼之patch順口溜了解一下

Vue原始碼之patch順口溜了解一下

三、新遊標先結束newStartIdx > newEndIdx批量刪除

當結束時newStartIdx > newEndIdx時,說明新的VNode節點已經遍歷完了,但是老的節點還有 剩餘,需要從文件中刪 的節點刪除。 

Vue原始碼之patch順口溜了解一下



Vue原始碼之patch順口溜了解一下

四、連貫起來

Vue原始碼之patch順口溜了解一下

相關文章