anchors
- 入口
- 新旧vnode不相同
- 以当前旧节点为参考节点,创建新的节点
- 递归更新父占位符节点
- 删除旧节点
- 新旧vnode相同比较children
- 执行 prepatch 钩子函数
- 执行update钩子函数
- patch
- 执行postpatch钩子函数
入口
- 调用sameVnode判断是不是同一个vnode
|
|
|
|
新旧vnode不相同
- 以当前旧节点为参考节点,创建新的节点
|
|
递归更新父占位符节点
123456789101112131415161718192021222324252627282930313233343536function isPatchable (vnode) {while (vnode.componentInstance) {vnode = vnode.componentInstance._vnode;}return isDef(vnode.tag)}// update parent placeholder node element, recursivelyif (isDef(vnode.parent)) {var ancestor = vnode.parent;var patchable = isPatchable(vnode);while (ancestor) {for (var i = 0; i < cbs.destroy.length; ++i) {cbs.destroy[i](ancestor);}ancestor.elm = vnode.elm;if (patchable) {for (var i$1 = 0; i$1 < cbs.create.length; ++i$1) {cbs.create[i$1](emptyNode, ancestor);}// #6513// invoke insert hooks that may have been merged by create hooks.// e.g. for directives that uses the "inserted" hook.var insert = ancestor.data.hook.insert;if (insert.merged) {// start at index 1 to avoid re-invoking component mounted hookfor (var i$2 = 1; i$2 < insert.fns.length; i$2++) {insert.fns[i$2]();}}} else {registerRef(ancestor);}ancestor = ancestor.parent;}}删除旧节点
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263// destroy old nodeif (isDef(parentElm)) {removeVnodes(parentElm, [oldVnode], 0, 0);} else if (isDef(oldVnode.tag)) {invokeDestroyHook(oldVnode);}function removeVnodes (parentElm, vnodes, startIdx, endIdx) {for (; startIdx <= endIdx; ++startIdx) {const ch = vnodes[startIdx]if (isDef(ch)) {if (isDef(ch.tag)) {removeAndInvokeRemoveHook(ch)invokeDestroyHook(ch)} else { // Text noderemoveNode(ch.elm) // 删除文本}}}}function removeAndInvokeRemoveHook (vnode, rm) {if (isDef(rm) || isDef(vnode.data)) {let iconst listeners = cbs.remove.length + 1if (isDef(rm)) {// we have a recursively passed down rm callback// increase the listeners countrm.listeners += listeners} else {// directly removingrm = createRmCb(vnode.elm, listeners)}// recursively invoke hooks on child component root nodeif (isDef(i = vnode.componentInstance) && isDef(i = i._vnode) && isDef(i.data)) {removeAndInvokeRemoveHook(i, rm)}for (i = 0; i < cbs.remove.length; ++i) {cbs.remove[i](vnode, rm)}if (isDef(i = vnode.data.hook) && isDef(i = i.remove)) {i(vnode, rm)} else {rm()}} else {removeNode(vnode.elm) // 删除dom}}// vnode的destroy hookfunction invokeDestroyHook (vnode) {let i, jconst data = vnode.dataif (isDef(data)) {if (isDef(i = data.hook) && isDef(i = i.destroy)) i(vnode)for (i = 0; i < cbs.destroy.length; ++i) cbs.destroy[i](vnode)}if (isDef(i = vnode.children)) {for (j = 0; j < vnode.children.length; ++j) {invokeDestroyHook(vnode.children[j])}}}
新旧vnode相同
- patchVnode
|
|
- 执行 prepatch 钩子函数
- 更新子组件的listener,props数据, resolve slots; 触发子组件重新渲染1234567891011prepatch: function prepatch (oldVnode, vnode) {var options = vnode.componentOptions;var child = vnode.componentInstance = oldVnode.componentInstance;updateChildComponent(child,options.propsData, // updated propsoptions.listeners, // updated listenersvnode, // new parent vnodeoptions.children // new children);},
- 更新子组件的listener,props数据, resolve slots; 触发子组件重新渲染
|
|
执行update钩子函数
1234if (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); }}patch
12345678910111213141516171819var oldCh = oldVnode.children;var ch = vnode.children;if (isUndef(vnode.text)) {if (isDef(oldCh) && isDef(ch)) {if (oldCh !== ch) { updateChildren(elm, oldCh, ch, insertedVnodeQueue, removeOnly); }} else if (isDef(ch)) {if (process.env.NODE_ENV !== 'production') {checkDuplicateKeys(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钩子函数
updateChildren
- dom能移动就不增删
- 查看diff算法