day102-vuejs源码-patchVnode

前言

主要是讲新旧节点是怎么判断进行替换的。

  • 先理一下思路,这类的条件语句比较多,主要是节点和文本的替换,但是理完下来感觉还是蛮清爽的。
  • 判断新旧节点同时存在,又是同一个节点,而且只能渲染一次,那么只需要相互替换组件实例就行
  • 通过钩子,判断新老节点都有子节点oldCh的话,就对子节点进行diff,调用updateChildren方法
  • 新旧节点,新节点有子节点,但是旧的没有,就清空旧的文本内容后,为当前DOM节点插入新节点
  • 新旧节点,新节点没有子节点,但是旧的有,就移除该DOM节点的所有子节点
  • 新旧节点都没有子节点的时候,就只是文本的替换


代码

function patchVnode(oldVnode, vnode, insertedVnodeQueue, removeOnly) {
if (oldVnode === vnode) {
return
}
// reuse(重用) element for static trees
// note we only do this if the vnode is cloned -
// if the new node is not cloned it means the render functions have been
// reset by the hot-reload-api and we need to do a proper re-render.
// 比较新旧是否相同且新节点是否标记了once
// 第一步
if (isTrue(vnode.isStatic) &&
isTrue(oldVnode.isStatic) &&
vnode.key === oldVnode.key &&
(isTrue(vnode.isCloned) || isTrue(vnode.isOnce))) {
vnode.elm = oldVnode.elm
vnode.componentInstance = oldVnode.componentInstance
return
}
// 第二步
let i
const data = vnode.data
// 判断钩子是否存在
if (isDef(data) && isDef(i = data.hook) && isDef(i = i.prepatch)) {
i(oldVnode, vnode)
}
const elm = vnode.elm = oldVnode.elm
const oldCh = oldVnode.children
const ch = vnode.children
// 判断是否有子节点存在?
if (isDef(data) &&isPatchable(vnode)) {
for (i = 0; i < cbs.update.length; ++i) {
cbs.update[i](oldVnode, vnode)
}
if (isDef(i = data.hook) && isDef(i = i.update)) {
i(oldVnode, vnode)
}
}
// 有文本内容存在
if (isUndef(vnode.text)) {
if(isDef(oldCh) && isDef(ch)) {
if (oldCh !== ch) {
updateChildren(elm, oldCh, ch, insertedVnodeQueue, removeOnly)
}
} else if (isDef(ch)) {
// 第三步
if (isDef(oldVnode.text)) {
nodeOps.setTextContent(elm, '')
}
// 注意,这里要添加节点了!
addVnodes(elm, null, ch, 0, ch.length - 1, insertedVnodeQueue)
} else if (isDef(oldCh)) {
removeVnodes(elm, oldCh, 0, oldCh.length -1)
} else if (isDef(oldVnode.text)) {
// 只有老节点有子节点
nodeOps.setTextContent(elm, '')
}
} else if (oldVnode.text !== vnode.text) {
// 设置文本内容,条件语句走到最后
nodeOps.setTextContent(elm, vnode.text)
}
// 调用postpatch钩子
if (isDef(data)) {
if(isDef(i = data.hook) && isDef(i = i.postpatch)) {
i(oldVnode, vnode)
}
}
}
文章作者: lmislm
文章链接: http://lmislm.com/2019/04/24/2019-04-24/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 LMISLMのBlog