Vue3源码系列之特殊比较和优化

174 阅读2分钟
  • 如果被挂载过,也就是isMounted为true,触发effect的时候就会走组件更新的逻辑
  • diff算法就是比较两颗树的差异

第一步

我们先拿到老的的tree

Image.png

然后把当前实例上的proxy数据传入render里,再调render方法就拿到了新的tree

Image.png

第二步

调用patch方法,patch方法既有初始化,又有更新的功能

Image.png

传了第一个参数,就是更新,否则就是初始化

Image.png

这时候会走元素更新

Image.png

判断是否值得比较

当走到patch方法的时候,我们就来看看值不值的去比较

Image.png

Image.png

  • 如果n1和n2不是相同的节点,把以前的删掉,换成n2,判断是不是相同,通过type和key
  • 获取下一个节点,最后插入下一个节点的前面

第三步

这个时候我们来比较元素

如果元素是相同节点

Image.png

  • 先复用老的dom节点
  • 然后更新props

patchProps方法

Image.png

  • 如果新属性和老属性不相等
  • 循环新属性对象里的属性,如果和老的不一样,就去更新
  • 再去循环老的,如果老的有,新的没有,那就赋值个null

第四步

更新children

Image.png

patchChildren方法

可能的情况:

  • 老的有儿子,新的没儿子
  • 新的有儿子,老的没儿子
  • 新老都有儿子
  • 新老都是文本

Image.png

  • 取出老的shapeFlag和新的shapeFlag
  • 先判断新的shapeFlag是否是文本,如果是文本,再去判断老的是数组,也就是否包含组件,如果包含组件则会调用组件的销毁方法
  •  然后判断c1和c2是否相同,如果不相同,直接把新的文本插入到容器中
  • 如果现在是元素,之前是文本或者数组,老的是文本其实也会被包装成数组,所以到这里也就是两个数组的比对,也就是核心的diff算法
  • 否则就是没有孩子,直接删除掉孩子
  • 如果上一次是文本,就直接清空,如果这次有儿子,直接挂载上去

对这个方法来个总结

  • 现在是文本之前是数组,销毁之前的所有儿子
  • 两个人都是文本,直接替换
  • 两个人都是数组,进行diff
  • 现在是数组,之前是文本,清空之前文本,挂载现在的所有儿子

下一步,我们就开始详细去分析diff算法

如果您觉得有所收获,麻烦动动小手点个攒,谢谢啦~ 预知后事如何,且听下回分解~