图解vue的diff算法

每次修改或新增数据都要创建渲染一整个真实dom的话要开销大量性能,所以vue用diff算法来实现局部更新。

真实dom和虚拟dom

渲染完真实dom以后,会根据真实dom生成一个虚拟dom

在这里插入图片描述

当树上某个VNODE节点的数据发生改变后,会生成一个新的虚拟dom

在这里插入图片描述

把新旧两个虚拟dom进行对比,把两者的差异更新到真实dom上并渲染这个需要更新的部分,这样就避免了重新渲染一整棵树
然后把旧的虚拟dom删除,新的虚拟dom就成为了下一次要进行对比的旧虚拟dom

虚拟dom的对比过程对树上的节点VNODE进行了遍历对比,而且只会进行同层的比较,先把每一层的比较完才会去对比下一层次的节点

在这里插入图片描述

patch函数

vue认为在不看后代节点的情况下(也就是先不看下一层),两个节点如果key和tag都相同,那这两个节点就是相等的

patch函数就是在这种情况下,对两个节点进行判断

如果不相同,就没有往下一层比较的必要了,把真实dom上的对应的节点的树结构直接替换成新的VNODE(这样做可以尽可能减少比较的次数)
如果相同,就进行更深层的对比,执行patchVnode函数

patchVnode函数

更新的过程中会根据新旧VNODE有子节点(children)还是有文本(text)来做不同的操作,总共有4种情况:

  1. 旧VNODE有子节点,新VNODE没有:直接删掉真实dom的子节点
  2. 旧VNODE没有子节点,新VNODE有子节点:创建新VNODE的子节点,添加到真实dom上
  3. 新/旧VNODE都有文本节点:如果文本内容不同,直接把真实dom的文本改成新VNODE的文本
  4. 新/旧VNODE都有子节点:把两者的children数组单独拎出来对比,对比的过程如下

updateChildren函数

对于这两个子节点数组,会分别声明两个指针指向头尾
在头尾指针不错位的情况下(即头指针始终不到尾指针的右边,尾指针始终不到头指针的左边)
四个头尾指针指向的子节点的对比分成5种

  1. 旧VNODE的头指针和新VNODE的头指针,相等的话指针向中间靠拢,把对应的节点移到相应位置

  2. 旧VNODE的头指针和新VNODE的尾指针,相等的话指针向中间靠拢,把对应的节点移到相应位置

  3. 旧VNODE的尾指针和新VNODE的头指针,相等的话指针向中间靠拢,把对应的节点移到相应位置

  4. 旧VNODE的尾指针和新VNODE的尾指针,相等的话指针向中间靠拢,把对应的节点移到相应位置

在这里插入图片描述

  1. 如果以上4种情况都不符合

拿到新VNODE的头指针,把整个旧VNODE的子节点数组进行遍历,目的是尽可能找到相等的节点,减少创建新节点

  • 如果找到了,就对这个节点进行移动
  • 如果遍历结束还没找到,就不得不创建,创建后根据新VNODE插入对应位置

一旦新/旧VNODE的头尾指针错位了,那就意味着这个结点数组遍历完成
如果新节点比旧结点先遍历完,把真实dom的多余节点删除
如果旧结点比新节点先遍历完,把剩余的新节点创建并添加到真实dom中

图解如下:(假设旧VNODE子节点为[1, 2, 3, 4, 5],新VNODE子节点为[1, 2, 6, 5, 3, 4])

  1. 对比两个头指针指向的节点,发现相同,把对应的节点移到相应位置,指针向右走一步

在这里插入图片描述

  1. 对比两个头指针指向的节点,发现相同,把对应的节点移到相应位置,指针向右走一步

在这里插入图片描述

  1. 前四种比较没有找到相同的,以新VNODE子节点的头指针指向的节点为基准,遍历旧VNODE子节点,发现没找到,创建并插入到正确位置

在这里插入图片描述

  1. 对比旧的尾指针和新的头指针,发现相同,把对应的节点移到相应位置,指针向中间走一步

在这里插入图片描述

  1. 对比两个头指针指向的节点,发现相同,把对应的节点移到相应位置,指针向右走一步

    在这里插入图片描述

  2. 对比两个头/尾指针指向的节点,发现相同,把对应的节点移到相应位置,指针再走下去就错位了,结束对比
    在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值