Vue diff算法

一、简介

Vuediff算法是同层比较,不会跨层比较,时间复杂度为O(N)。
虚拟DOM层级比较
主要使用首尾比较法(头-头,头-尾,尾-头,尾-尾)。Vue2Vue3diff算法主要区别是处理完首尾节点后,对剩余节点的处理方式。
首尾比较法

二、Vue2 diff算法过程

  1. 新旧虚拟DOM分别创建首尾两个指针
  2. 依次头-头,头-尾,尾-头,尾-尾(startIndex1,startIndex2,endIndex1,endIndex2)比较,若在比较过程中发现指向的节点内容一致,则直接复用旧结点作为diff创建的节点。若这四种情况都不满足,则diff将创建当前新虚拟DOM的节点插入到diff队列后面,并且将新虚拟DOMstartIndex2指向下一个节点。
  3. 当其中一条虚拟DOMendStart < startIndex,比较结束。
  4. 随后根据新老节点的数目,来进行插入或删除操作。若新节点数目大于老节点则需要把多出来的节点创建出来加入到真实 DOM中,反之若老节点数目大于新节点则需要把多出来的老节点从真实 DOM中删除。
  5. 至此整个 diff 过程就已经全部完成了。

三、Vue3 diff算法过程

  1. 新旧节点从头开始比较,相同直接复用执行patch,直到比较到两节点不同为止。

  2. 新旧节点从尾开始比较,相同直接复用执行patch,直到比较到两节点不同为止。

  3. 处理完以上两种情况,剩下3种情况。

  4. 老节点先遍历完,新节点还剩余:创建剩余新节点。

  5. 新节点先遍历完,老节点还剩余:删除剩余旧节点。

  6. 新老节点都有剩余:在新老剩余节点中寻找可复用节点。创建新节点剩余节点对应的映射表keyToNewIndexMap。再创建一个数组newIndexToOldIndexMap,用来存储新节点数组中的剩余节点在旧节点数组上的索引,后面将使用它计算出一个最长递增子序列,并初始化数组为0。
    在这里插入图片描述

  7. 遍历老节点,存储新节点数组中的剩余节点在旧节点数组上的索引。
    在这里插入图片描述

  8. 计算newIndexToOldIndexMap数组,得到最长增长子序列(贪心 + 二分)。
    在这里插入图片描述

  9. 遍历新节点,根据最长增长子序列进行移动、添加、删除节点。第一个节点为h,在newIndexToOldIndexMap中值为0,说明是新增的节点,创建。第二个节点为e,索引为3,与最长增长子序列中3命中,跳过。第三个节点为d,索引为2,与最长增长子序列中2命中,跳过
    第四个节点为c,索引为1,与最长增长子序列中1命中,跳过。第五个节点为f,索引为0,均不符合,进行hostInsert,将节点f的真实dom移动到节点nextChild节点c的前面。遍历结束完成 。

四、总结

  • vue2、vue3 的 diff 算法实现差异主要体现在:处理完首尾节点后,对剩余节点的处理方式。
  • vue2 是通过对旧节点列表建立一个 { key, oldVnode }的映射表,然后遍历新节点列表的剩余节点,根据newVnode.key在旧映射表中寻找可复用的节点,然后打补丁并且移动到正确的位置。
  • vue3 则是建立一个存储新节点数组中的剩余节点在旧节点数组上的索引的映射关系数组,建立完成这个数组后也即找到了可复用的节点,然后通过这个数组计算得到最长递增子序列,这个序列中的节点保持不动,然后将新节点数组中的剩余节点移动到正确的位置。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值