Vue源码之patch顺口溜了解一下

经过同层的树节点进行比较而非对树进行逐层搜索遍历的方式,因此时间复杂度只有O(n),是一种至关高效的算法node


同层级只作三件事:增删改。

具体规则是:算法

  • new VNode不存在就删;
  • old VNode不存在就增;
  • 都存在就 比较类型,类型不一样直接替换、类型相同执行更新 

两个VNode类型相同,就执行更新操做,包括三种类型操做:属性更新PROPS、文本更新TEXT、子节点更新REORDER dom

  1. 若是新旧VNode都是静态的,那么只须要替换elm以及componentInstance便可。 spa

  2. 新老节点均有children子节点,则对子节点进行diff操做,调用updateChildren 3d

  3. 若是老节点没有子节点而新节点存在子节点,先清空老节点DOM的文本内容,而后为当前DOM节 code

    点加入子节点。 component

  4. 当新节点没有子节点而老节点有子节点的时候,则移除该DOM节点的全部子节点。 cdn

  5. 当新老节点都无子节点的时候,只是文本的替换。 blog

⚠️  下面诠释顺口溜打开:src/core/vdom/patch.js文件

1、开始游标<=结束游标

首先oldStartVnode、oldEndVnodenewStartVnode、newEndVnode两两交叉比较(1-4) 接口

1. 旧头对新头,排着队伍完后走

oldStartVnode newStartVnode  知足 sameVnode ,直接将该 VNode 节点进行 patchVnode 便可,不需再遍历就完成了一次循环 




2. 旧尾对新尾,拉着尾巴顺着走

当  oldEndVnode newEndVnode 知足 sameVnode ,直接将该 VNode 节点进行 patchVnode 便可,不需再遍历就完成了一次循环 




3. 旧头对新尾,按着新尾排排队

若是 oldStartVnode newEndVnode 知足 sameVnode 。说明 oldStartVnode 已经跑到了 oldEndVnode 后面去了,进行 patchVnode 的同时还须要将真实DOM节点移动到 oldEndVnode 的后面。 




4. 旧尾对新头,揪着旧尾前面走

若是 oldEndVnode newStartVnode 知足 sameVnode ,说明 oldEndVnode 跑到了 oldStartVnode 的前面,进行 patchVnode 的同时要将 oldEndVnode 对应DOM移动到 oldStartVnode 对应DOM的前面。 



5. 综上皆无果,老实循环接个来

若是以上状况均不符合,则在old VNode中找与 newStartVnode 知足 sameVnode vnodeToMove ,若 存在执行patchVnode,同时将 vnodeToMove 对应DOM移动到 oldStartVnode 对应的DOM的前面。 


固然也有可能 newStartVnode 在old VNode节点中找不到一致的key,或者是即使key相同却不是 sameVnode ,这个时候会调用 createElm 建立一个新的DOM节点放到old VNode最前面。 



2、老游标先结束oldStartIdx > oldEndIdx批量添加

当结束时 oldStartIdx > oldEndIdx ,这个时候旧的VNode节点已经遍历完了,可是新的节点尚未。说 明了新的VNode节点实际上比老的VNode节点多,须要将剩下的VNode对应的DOM插入到真实DOM 中,此时调用 addVnodes (批量调用createElm接口)。 



3、新游标先结束newStartIdx > newEndIdx批量删除

当结束时 newStartIdx > newEndIdx 时,说明新的VNode节点已经遍历完了,可是老的节点还有 剩余,须要从文档中删 的节点删除。 




相关文章
相关标签/搜索