通过同层的树节点进行比较而非对树进行逐层搜索遍历的方式,所以时间复杂度只有O(n),是一种相当高效的算法
同层级只做三件事:增删改。
具体规则是:
- new VNode不存在就删;
- old VNode不存在就增;
- 都存在就 比较类型,类型不同直接替换、类型相同执行更新
两个VNode类型相同,就执行更新操作,包括三种类型操作:属性更新PROPS、文本更新TEXT、子节点更新REORDER
如果新旧VNode都是静态的,那么只需要替换elm以及componentInstance即可。
新老节点均有children子节点,则对子节点进行diff操作,调用updateChildren
如果老节点没有子节点而新节点存在子节点,先清空老节点DOM的文本内容,然后为当前DOM节
点加入子节点。
当新节点没有子节点而老节点有子节点的时候,则移除该DOM节点的所有子节点。
当新老节点都无子节点的时候,只是文本的替换。
⚠️ 下面诠释顺口溜打开:src/core/vdom/patch.js文件
一、开始游标<=结束游标
首先oldStartVnode、oldEndVnode与newStartVnode、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最前面。 

二、老游标先结束oldStartIdx > oldEndIdx批量添加
当结束时
oldStartIdx > oldEndIdx,这个时候旧的VNode节点已经遍历完了,但是新的节点还没有。说
明了新的VNode节点实际上比老的VNode节点多,需要将剩下的VNode对应的DOM插入到真实DOM
中,此时调用addVnodes(批量调用createElm接口)。 

三、新游标先结束newStartIdx > newEndIdx批量删除
当结束时
newStartIdx > newEndIdx时,说明新的VNode节点已经遍历完了,但是老的节点还有
剩余,需要从文档中删 的节点删除。 

四、连贯起来

