Vue里面的patch和patchVnode

1,076 阅读1分钟

vm.update的时候会执行以下代码

Vue.prototype._update = function (vnode, hydrating) {
	if (!prevVnode) {
      // initial render
      vm.$el = vm.__patch__(vm.$el, vnode, hydrating, false /* removeOnly */);
    } else {
      // updates
      vm.$el = vm.__patch__(prevVnode, vnode);
    }
}

vm.patch 在非Server端就是patch

// install platform patch function
   Vue.prototype.__patch__ = inBrowser ? patch : noop;
return patch (oldVnode, vnode, hydrating, removeOnly)

patch方法主要分以下情况 0wsKts.png

以下是patchVnode的代码

function patchVnode (
   oldVnode,
   vnode,
   insertedVnodeQueue,
   ownerArray,
   index,
   removeOnly
 ) {
   if (oldVnode === vnode) {
     return
   }

   if (isDef(vnode.elm) && isDef(ownerArray)) {
     // clone reused vnode
     vnode = ownerArray[index] = cloneVNode(vnode);
   }

   var elm = vnode.elm = oldVnode.elm;

   var i;
   var data = vnode.data;
   if (isDef(data) && isDef(i = data.hook) && isDef(i = i.prepatch)) {
     i(oldVnode, vnode);
   }

   var oldCh = oldVnode.children;
   var 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)) {
     	// 1
       if (oldCh !== ch) { updateChildren(elm, oldCh, ch, insertedVnodeQueue, removeOnly); }
     } else if (isDef(ch)) {
       {
         checkDuplicateKeys(ch);
       }
       // 3
       if (isDef(oldVnode.text)) { nodeOps.setTextContent(elm, ''); }
       // 2,3
       addVnodes(elm, null, ch, 0, ch.length - 1, insertedVnodeQueue);
     } else if (isDef(oldCh)) {
       //4
       removeVnodes(oldCh, 0, oldCh.length - 1);
     } else if (isDef(oldVnode.text)) {
       //5
       nodeOps.setTextContent(elm, '');
     }
   } else if (oldVnode.text !== vnode.text) {
    // 6
     nodeOps.setTextContent(elm, vnode.text);
   }
   if (isDef(data)) {
     if (isDef(i = data.hook) && isDef(i = i.postpatch)) { i(oldVnode, vnode); }
   }
 }

patchVnode的逻辑主要分以下情况(下面的几种情况序号分别对应上面代码的标记处) 0wERYV.png

关于updateChildren

下面连接的视频大概描述了updateChildren的过程 updateChildren的过程

还有之前写过一篇文章关于 Duplicate keys导致update时报错