虚拟dom和diff算法--5(diff算法子节点更新策略☆)

197 阅读4分钟

写在前面,笔记来源于www.bilibili.com/video/BV1iX… 侵删

diff算法提出的四种命中查找,四个指针

①新前与旧前

新前:新的虚拟节点中所有没有处理的开头的节点
旧前:旧的虚拟节点中所有没有处理的开头的节点

②新后与旧后

新后:新的虚拟节点中所有没有处理的结尾的节点
旧后:旧的虚拟节点中所有没有处理的结尾的节点

③新后与旧前

④新前与旧后

需要注意的事,这样的查找方式并不是snabbdom独创的查找方式,但是是diff的经典的算法优化策略,也是diff传统的优化策略。
要注意的是,这里的顺序是从上往下的,如果查找到①了,就不会再往下走了
命中①就不会往下走了,以此类推

image.png

新增:

image.png

旧前->新前  匹配
旧前->新前  匹配
旧前->新前  匹配
旧节点结束,新节点没有结束,新节点剩下的节点直接追加到dom就好

image.png

image.png

删除:

image.png

旧前->新前  匹配
旧前->新前  匹配
旧前->新前  不匹配 ====按照匹配规则==>旧后,新后
旧后->新后  匹配
此时旧节点没结束,新节点已经结束,说明剩下的是要被删除的节点
(再次强调,新前旧前=>新后旧后=>新后旧前=>新前旧后,按照顺序来)

image.png

新前->旧前(AA)  匹配
新前->旧前(BB)  匹配
新前->旧前(CD)  不匹配==更改为新后旧后==>
新后->旧后(DE)  不匹配==更改为新后旧前==>
新后->旧前(DC)  不匹配==更改为新前旧后==>
新前->旧后(DE)  不匹配

四个都不匹配!!
如果都没命中,就需要用循环来进行寻找命中了

image.png

循环旧节点,找key为D的,发现:
循环找到结果了===>先判断成移动位置,
虚拟dom打undefined标志,真实dom移动位置====>循环新节点,
发现新节点结束了(这里老师讲的也有问题),
说明剩下的是要被删除掉的节点,将其他的节点删掉,所以CE被删除掉了
剩余节点就是旧前和新后指针卡住的节点(中间的节点)

image.png

比较复杂的情况

image.png

新前->旧前(AE)  不匹配 ==更改为新后旧后==>
新后->旧后(EM)  不匹配 ==更改为新后旧前==>
新后->旧前(AM)  不匹配 ==更改为新前旧后==>
新前->旧后(EE)   匹配 (④命中了)

当新前旧后(④)命中

image.png

意味着 新前旧后(EE) 匹配到以后 旧节点虚拟节点中的E被标识undefined了,
    E在真实dom节点中出现在了旧前(此时可能旧前前面匹配到了,可能没被匹配,
    换而言之,就是出现在了没被处理没被匹配到的旧节点的前面了!!)的前面了。
    也就是说,此时E出现在了真实dom的第一个位置
也就是说,假设在匹配到情况④之前前三个有被匹配到的话,那么此时E出现在匹配好的节后
    没被匹配的节点前
    
    
 继续往下走:
新前->旧前(CA)  不匹配
新后->旧后(MD)  不匹配
新后->旧前(MB)  不匹配
新前->旧后(CD)  不匹配
循环
在旧节点中找C==>找到了:
  给虚拟节点C加上undefined标识,将真实domC放到没被匹配到的节点最前面(也就是E后面)也就是旧前之前
当前真实dom:EC

image.png (不知道未来的我还能不能看懂!自信点!!!现在看懂了将来的我一定也能看懂!!)

继续往下走:
新前->旧前(MA)  不匹配
新后->旧后(MD)  不匹配
新后->旧前(MA)  不匹配
新前->旧后(MD)  不匹配
循环
在旧节点(ABD)中寻找M==>没找到==>把M插入到旧前之前(没被处理的节点前)
新节点处理结束了
老节点还有剩余==>说明需要删除节点
更复杂的情况

image.png

新前->旧前(AE) 不匹配==更换为新后旧后==>
新后->旧后(EA) 不匹配==更换为新后旧前==>
新后->旧前(AA)  匹配
同样的道理,也是会移动节点,将虚拟节点标识为undefined,移动到真实dom那边
移动旧前A到老节点的旧后后面

继续
新前旧前(BE) 不匹配
新后旧后(BE) 不匹配
新后旧前(BB) 匹配
虚拟节点B标识undefined,真实domB移动到旧后之后
(注意旧后只能时候从后往前走)
.....
同理

如果最后发现新节点那边多了一个,就往旧后之后追加

image.png

贴心的邵老师给了个小总结:

image.png

③情况命中的前提下,旧前就是新后啦。
同样的道理,④情况命中的前提下,新前就是旧后啦~