新旧节点不同
1.销毁旧节点
2.根据新节点的类型 去挂载不同的节点
处理组件
1.先判断子组件是否需要更新
2.如果需要则递归执行子组件的副渲染函数来更新
3.否则仅仅更新一些 vnode 的属性,并让子组件实例保留对组件 vnode 的引用
处理元素
1.更新props
2.更新子节点 子节点有三种类型 纯文本 Vnode数组 和 空
旧节点是纯文本:
1.新节点也是 做简单的替换
2.新节点是空 删除
3.新节点是Vnode数组 批量添加
旧节点是空:
1.如果新子节点是纯文本,那么在旧子节点的父容器下添加新文本节点即可;
2.如果新子节点也是空,那么什么都不需要做
3.如果新子节点是 vnode 数组,那么直接去旧子节点的父容器下添加多个新子节点即可。
旧子节点是 vnode 数组:
1.如果新子节点是纯文本,那么先删除旧子节点,再去旧子节点的父容器下添加新文本节点;
2.如果新子节点是空,那么删除旧子节点即可
3.如果新子节点也是 vnode 数组,那么就需要做完整的 diff 新旧子节点了,这是最复杂的情况,内部运用了核心 diff 算法
新旧节点都是数组
新旧数组之间的对比,无非是通过更新、删除、添加和移除节点来完成的,diff算法的核心以较低的成本完成子节点的更新为目的,求解生成新子节点 DOM 的系列操作。
过程:
1.同步头节点
2.同步尾节点
3.添加新节点 新子节点有剩余
4.删除多余节点 旧节点有剩余
5.处理未知子序列
处理未知子序列
有时会碰到比较复杂的未知子序列:对于移动、删除、添加、更新这些操作,其中最复杂的就是移动操作,Vue针对未知子序列的核心是通过最长递增子序列查找到需要移动的最小值。
在查找过程中需要对比新旧子序列,那么我们就要遍历某个序列,如果在遍历旧子序列的过程中需要判断某个节点是否在新子序列中存在,这就需要双重循环,而双重循环的复杂度是 O(n2) ,为了优化这个复杂度,我们可以用一种空间换时间的思路,建立索引图,把时间复杂度降低到 O(n)。
建立索引图
1.根据for循环中的key建立新子序列中的索引图
2.然后再创建一个新旧子序列索引的映射关系,用于确定最长递增子序列、
3.然后正序遍历旧子序列,看看是否在新子序列的索引图中,如果不再就删除,如果在根据索引去判断这个节点是否在最长递增子序列中,如果在就不需要进行移动,如果不再就要进行移动操作
4.然后在遍历的过程中对新节点打上标记,对于没有被查找的标识为0,需要进行添加操作
帖子还没人回复快来抢沙发