Diff 算法执行过程:
在比较开始时首先对新老节点数组的开始和结尾节点设置标记索引,遍历比较时会出现四种情况
-
oldStartVnode/newStartVnode 比较
-
oldEndVnode/newEndVnode 比较
-
oldStartVnode/newEndVnode 比较
-
oldEndVnode/newStartVnode 比较
-
开始节点和结束节点,对应情况 1 和 2
如果新旧节点是 sameVnode(key 和 sel 相同),则调用 patchVnode()对比和更新节点,并将新开始和旧开始索引往后移动 oldStartIdx++/newStartIdx++,再进行比较
-
旧开始节点和新结束节点,对应 3
比较这两个节点,如果是 sameVnode,调用 patchVnode()对比和更新元素,并将 oldStartVnode 旧元素移动到最后,并更新索引
-
旧开始节点和新结束节点,对应 4
比较这两个节点,如果是 sameVnode,调用 patchVnode()对比和更新元素,并将 oldEndVnode 旧元素移动到开始位置,并更新索引
-
非以上四种情况,说明开始和结束节点都不相同
遍历新节点,使用 newStartVnode 的 key 查找是否有相同的节点
如果没有,说明 newStartVnode 是新节点,创建新 DOM 元素,插入到 DOM 树种
如果有,判断新旧节点的 sel 属性是否相同,如果是则将旧节点赋值给 elmToMove 变量,并调用 patchVnode 对比和更新节点差异,最后将 elmToMove 对应的 DOM 移动到最前面;如果不是,说明节点被修改了,重新创建对应的 DOM 元素,插入到 DOM 树中
移动新节点索引,继续循环遍历
遍历结束,会出现两种情况
-
旧节点的子节点个数小于新节点的子节点个数,旧节点先遍历完(oldStartIdx > oldEndIdx),循环结束
此时新节点有剩余,把剩余节点批量插入到右边
-
* 旧节点的子节点个数大于新节点的子节点个数,新节点先遍历完(newStartIdx > newEndIdx),循环结束
此时旧节点有剩余,把剩余节点批量删除
image-20210228173532921.png
网友评论