diff算法
TIP
diff算法的前提是有key
isSameVNode方法
判断 vnode中 类型 和 key 是否一致 不一致则不视为同一节点
比较前后节点
如上图
使用四个指针,分别指向两个数组的头和尾,并依次进行比较,相同节点更新即可,直到遇到不同的虚拟节点 可以截取出需要特殊对比方法的两段
如图就是旧的 [2] - [4] , 和新的 [2] - [3] 做对比
特殊情况
头或尾添加节点直接依次添加即可
头或尾删除节点直接依次删除即可
中间部分比较
TIP
基于最长递增子序列实现
c1 代表旧的节点数组
c2 代表新的节点数组
首先
- 创建一个数组用来记录新节点在老节点数组里面的位置, 默认值为0 即表示新节点在老节点数组中不存在
- 创建一个Map,并遍历c2,将c2中的每个节点的key存入Map中,方便后续查找。
- 遍历c1, 若Map存在与c1相同的节点, 则表示新节点在老节点数组中存在, 将其位置记录到数组中并更新dom节点
- 若Map中不存在与c1相同的节点, 则表示新节点在老节点数组中不存在, 直接删除掉该节点
- 现在的数组中记录了新节点在老节点数组中的位置 求出该数组的最长递增子序列
- 遍历需要更新的节点数组, 进行倒叙插入, 如果要插入的虚拟节点对应的真实DOM不存在, 则创建后插入, 如果存在 移动该节点的位置即可 如果索引和最长递增子序列的索引一致, 则表示该节点不需要移动
倒序插入是因为这样可以避免插入操作对后续节点索引的影响,保证在插入前面的节点时,后面尚未处理的节点的索引位置不会因前面的插入而发生变化,从而能准确地进行后续节点的处理。若要插入的虚拟节点对应的真实 DOM 不存在,就创建后插入;若存在则移动该节点的位置,而如果索引和最长递增子序列的索引一致,说明该节点已经在合适的位置上,不需要移动。
TIP
所以获取最长递增子序列的本质是求出移动DOM元素次数最少的方式
仅个人理解