diff 算法 与 patch (第二部分)
What
patchVode:当 vnode 和 oldVnode 都存在、oldVnode 不是真实节点,并且 vnode 和 oldVnode 值得比较时,才会调用 patchVnode 进行 patch
How
1、
/**如果 oldVnode 和 vnode 完全一致,则可认为没有变化,return;
**/
if (oldVnode === vnode) {
return;
}
1
2
3
4
5
2
3
4
5
2、
/**
* vnode.elm 表示当前虚拟节点对应的真实dom节点的引用
* vnode,oldVnode指向同一个真实 DOM 的引用
**/
const elm = (vnode.elm = oldVnode.elm);
1
2
3
4
5
2
3
4
5
3、
/**如果新旧 vnode 都是静态的,同时它们的 key 相同(代表同一节点),并且新的 vnode 是 clone 或者是标记了 once(标记 v-once 属性,只渲染一次),那么只需要替换 elm 以及 componentInstance 即可。
**/
if (
isTrue(vnode.isStatic) &&
isTrue(oldVnode.isStatic) &&
vnode.key === oldVnode.key &&
(isTrue(vnode.isCloned) || isTrue(vnode.isOnce))
) {
vnode.componentInstance = oldVnode.componentInstance;
return;
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
4、如果 vnode 节点没有 text 文本时:
- 4.1 (详见 diff 核心:updateChildren)
/**如果 oldNode,vnode 结点均有 children 子节点,则对子节点进行 diff 操作,调用 updateChildren 更新子节点
**/
updateChildren(elm, oldCh, ch, insertedVnodeQueue, removeOnly);
1
2
3
2
3
- 4.2
/**如果只有 vnode 节点存在子节点,那么先清空 elm 的文本内容,然后为当前节点加入子节点
**/
addVnodes(elm, null, ch, 0, ch.length - 1, insertedVnodeQueue);
1
2
3
2
3
- 4.3
/**如果只有 oldVnode 节点有子节点的时候,则移除所有 elm 的子节点
**/
removeVnodes(elm, oldCh, 0, oldCh.length - 1);
1
2
3
2
3
5、
/**如果 vnode 节点没有 text 文本,但是与 oldVode 节点 text 不一样时,直接替换这段文本
**/
nodeOps.setTextContent(elm, vnode.text);
1
2
3
2
3
注释