Skip to content

diff算法

TIP

diff算法的前提是有key

isSameVNode方法

判断 vnode中 类型 和 key 是否一致 不一致则不视为同一节点

比较前后节点

前后先比较

如上图

使用四个指针,分别指向两个数组的头和尾,并依次进行比较,相同节点更新即可,直到遇到不同的虚拟节点 可以截取出需要特殊对比方法的两段

如图就是旧的 [2] - [4] , 和新的 [2] - [3] 做对比

特殊情况

头或尾添加

头或尾添加节点直接依次添加即可


头或尾删除

头或尾删除节点直接依次删除即可

中间部分比较

TIP

基于最长递增子序列实现

c1 代表旧的节点数组

c2 代表新的节点数组

首先

  1. 创建一个数组用来记录新节点在老节点数组里面的位置, 默认值为0 即表示新节点在老节点数组中不存在
  2. 创建一个Map,并遍历c2,将c2中的每个节点的key存入Map中,方便后续查找。
  3. 遍历c1, 若Map存在与c1相同的节点, 则表示新节点在老节点数组中存在, 将其位置记录到数组中并更新dom节点
  4. 若Map中不存在与c1相同的节点, 则表示新节点在老节点数组中不存在, 直接删除掉该节点
  5. 现在的数组中记录了新节点在老节点数组中的位置 求出该数组的最长递增子序列
  6. 遍历需要更新的节点数组, 进行倒叙插入, 如果要插入的虚拟节点对应的真实DOM不存在, 则创建后插入, 如果存在 移动该节点的位置即可 如果索引和最长递增子序列的索引一致, 则表示该节点不需要移动

倒序插入是因为这样可以避免插入操作对后续节点索引的影响,保证在插入前面的节点时,后面尚未处理的节点的索引位置不会因前面的插入而发生变化,从而能准确地进行后续节点的处理。若要插入的虚拟节点对应的真实 DOM 不存在,就创建后插入;若存在则移动该节点的位置,而如果索引和最长递增子序列的索引一致,说明该节点已经在合适的位置上,不需要移动。

TIP

所以获取最长递增子序列的本质是求出移动DOM元素次数最少的方式

仅个人理解