diff算法

152 阅读2分钟

想要了解diff算法,需要认识一下虚拟DOM,那么虚拟DOM是什么?

虚拟DOM就是表示真实DOM的JS对象!

diff算法.png

如果我们修改了文本内容,就会生成一个新的虚拟DOM,如果能快速找到新旧JS之间差异,就可以最小化的更新视图。

因此内部提供了一个算法,就是diff算法,它的目的就是找出差异,最小化更新视图,具体流程如下:

node.png 我们看到,如果在新旧节点都有子节点的时候,就进入了另外一个方法,updataChildren

updataChildren

如果我们想从左边的DOM结构变成右侧的DOM结构,如何最小化的更新DOM

smallnode.png

我们在内部定义了只在同级做对比,减少对比次数,最大化的提高对比性能

smallnode.png

比较规则

  1. 依次比较,当比较成功后退出当前比较;
  2. 渲染结果以newVnode为准;
  3. 每次比较后start点和end点向中间靠拢;
  4. 当旧节点中有一个start点跑到end点右侧时终止比较;
  5. 如果都匹配不到,则旧虚拟DOM key值去比对新虚拟DOM的key值,如果key值相同则复用,并移动到新虚拟DOM的位置;

step1.png

第一次比较

  • oldStart和newStart对比,发现并不相同;
  • 接着oldStart和newEnd比较,发现相同;
  • 因为所匹配新DOM位置在最后,所以真实DOM位置也应移动到新DOM所处位置;

step2.png

第二次比较

  • 接上次匹配,oldStart和newEnd匹配成功,所以oldStart向右移动,newEnd向左移动;
  • 开始匹配,oldStart和newStart比较,发现相同;
  • 因为所匹配新Dom位置在第一个,所以真实DOM位置也应移动到新DOM所处位置;

step3.png

第三次比较

  • 接上次匹配,oldStart和newStart匹配成功,所以oldStart向右移动,newStart也向右移动;
  • 开始匹配,oldStart和newStart比较,发现相同;
  • 移动规则不变;

step4.png

第四次比较

  • 接上次匹配,oldStart和newStart匹配成功,所以oldStart向右移动,newStart也向右移动,此时我们发现oldStart已经超出了匹配范围;
  • 匹配暂停,把newvnode剩余元素,放入真实DOM空位置;
  • 匹配结束,退出匹配;
  • ps:如果新虚拟DOM元素比较少的话,我们就需要删除真实DOM中多余的元素;

step5.png


step6.png