Skip to content

Commit 640cf4e

Browse files
committed
vda
1 parent f2588b6 commit 640cf4e

File tree

1 file changed

+235
-0
lines changed

1 file changed

+235
-0
lines changed

12-VirtualDom_algorithm.md

Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,8 +379,243 @@ function createPatchFunction(backend){
379379
} else{
380380
if(isUndef(oldKeyToIdx)){ oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx); }
381381
idxInOld = isDef(newStartVnode.key) ? oldKeyToIdx[newStartVnode.key] : null;
382+
if(isUndef(idxInOld)){
383+
createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm);
384+
newStartVnode = newCh[++newStartIdx];
385+
} else{
386+
elmToMove = oldCh[idxInOld];
387+
// dev-mode
388+
if('development' !== 'production' && !elmToMove){
389+
warn(
390+
'It seems there are duplicate keys that is causing an update error. ' +
391+
'Make sure each v-for item has a unique key.'
392+
);
393+
}
394+
if(sameVnode(elmToMove, newStartVnode)){
395+
patchVnode(elmToMove, newStartVnode, insertedVnodeQueue);
396+
oldCh[idxInOld] = undefined;
397+
canMove && nodeOps.insertBefore(parentElm, newStartVnode.elm, oldStartVnode.elm);
398+
newStartVnode = newCh[++newStartIdx];
399+
} else{
400+
createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm);
401+
newStartVnode = newCh[++newStartIdx];
402+
}
403+
}
404+
}
405+
}
406+
if(oldStartIdx > oldEndIdx){
407+
refElm = isUndef(newCh[newEndIdx + 1]) ? null : newCh[newEndIdx + 1].elm;
408+
addVnodes(parentElm, refElm, newCh, newStartIdx, newEndIdx, insertedVnodeQueue);
409+
} else if(newStartIdx > newEndIdx){
410+
removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx);
411+
}
412+
}
413+
414+
// patchVnode
415+
function patchVnode(oldVnode, vnode, insertedVnodeQueue, removeOnly){
416+
if(oldVnode === vnode){
417+
return ;
418+
}
419+
//
420+
if(isTrue(vnode.isStatic) &&
421+
isTrue(oldVnode.isStatic) &&
422+
vnode.key === oldVnode.key &&
423+
(isTrue(vnode.isCloned) || isTrue(vnode.isOnce))
424+
){
425+
vnode.elm = oldVnode.elm;
426+
vnode.componentInstance = oldVnode.componentInstance;
427+
return ;
428+
}
429+
var i;
430+
var data = vnode.data;
431+
if(isDef(data) && isDef(i = data.hook) && isDef(i = i.prepatch)){
432+
i(oldVnode, vnode);
433+
}
434+
var elm = vnode.elm = oldVnode.elm;
435+
var oldCh = oldVnode.children;
436+
var ch = vnode.children;
437+
if(isDef(data) && isPatchable(vnode)){
438+
for(i = 0; i < cbs.update.length; ++i) { cbs.update[i](oldVnode, vnode); }
439+
if(isDef(i = data.hook) && isDef(i = i.update)){ i(oldVnode, vnode); }
440+
}
441+
if(isUndef(vnode.text)){
442+
if(isDef(oldCh) && isDef(ch)){
443+
if(oldCh !== ch) { updateChildren(elm, oldCh, ch, insertedVnodeQueue, removeOnly); }
444+
} else if(isDef(ch)){
445+
if(isDef(oldVnode.text)) { nodeOps.setTextContent(elm, ''); }
446+
addVnodes(elm, null, ch, 0, ch.length - 1, insertedVnodeQueue);
447+
} else if(isDef(oldCh)){
448+
removeVnodes(elm, oldCh, 0, oldCh.length - 1);
449+
} else if(isDef(oldVnode.text)){
450+
nodeOps.setTextContent(elm, '');
451+
}
452+
} else if(oldVnode.text !== vnode.text){
453+
nodeOps.setTextContent(elm, vnode.text);
454+
}
455+
if(isDef(data)){
456+
if(isDef(i = data.hook) && isDef(i = i.postpatch)) { i(oldValue, vnode); }
457+
}
458+
}
459+
460+
//
461+
function invokeInsertHook(vnode, queue, initial){
462+
if(isTrue(initial) && isDef(vnode.parent)){
463+
vnode.parent.data.pendingInsert = queue;
464+
} else{
465+
for(var i = 0; i < queue.length; ++i){
466+
queue[i].data.hook.insert(queue[i]);
467+
}
468+
}
469+
}
470+
471+
//
472+
var bailed = false;
473+
// 已渲染模块
474+
var isRenderedModule = makeMap('attrs,style,class,staticClass,staticStyle,key');
475+
476+
// 仅在浏览器执行的函数
477+
function hydrate(elm, vnode, insertedVnodeQueue){
478+
if(!assertNodeMatch(elm, vnode)){
479+
return false;
480+
}
481+
vnode.elm = elm;
482+
var tag = vnode.tag;
483+
var data = vnode.data;
484+
var children = vnode.children;
485+
if(isDef(data)){
486+
if(isDef(i = data.hook) && isDef(i = i.init)) { i(vnode, true); }
487+
if(isDef(i = vnode.componentInstance)){
488+
initComponent(vnode, insertedVnodeQueue);
489+
return true;
490+
}
491+
}
492+
if(isDef(tag)){
493+
if(isDef(children)){
494+
if(!elm.hasChildNodes()){
495+
createChildren(vnode, children, insertedVnodeQueue);
496+
} else{
497+
var childrenMatch = true;
498+
var childNode = elm.firstChild;
499+
for(var i$1 = 0; i$1 < children.length; i$1++){
500+
if(!childNode || !hydrate(childNode, children[i$1], insertedVnodeQueue)){
501+
childrenMatch = false;
502+
break;
503+
}
504+
childNode = childNode.nextSibling;
505+
}
506+
// warning
507+
if(!childrenMatch || childNode){
508+
if('development' !== 'production' &&
509+
typeof console !== 'undefined' &&
510+
!bailed
511+
){
512+
bailed = true;
513+
console.warn('Parent: ', elm);
514+
console.warn('Mismatching childNodes vs. VNodes: ', elm.childNodes, children);
515+
}
516+
return false;
517+
}
518+
}
519+
}
520+
if(isDef(data)){
521+
for(var key in data){
522+
if(!isRenderedModule(key)){
523+
invokeCreateHooks(vnode, insertedVnodeQueue);
524+
break;
525+
}
526+
}
527+
}
528+
} else if(elm.data !== vnode.text){
529+
elm.data = vnode.text;
530+
}
531+
return true;
532+
}
533+
534+
// assertNodeMatch
535+
function assertNodeMatch(node, vnode){
536+
if(isDef(vnode.tag)){
537+
return (
538+
vnode.tag.indexOf('vue-component') === 0 ||
539+
vnode.tag.toLowerCase() === (node.tagName && node.tagName.toLowerCase())
540+
);
541+
} else{
542+
// 8 => comment
543+
// 3 => text
544+
return node.nodeType === (vnode.isComment ? 8 : 3);
545+
}
546+
}
547+
548+
//
549+
return function patch(oldVnode, vnode, hydrating, removeOnly, parentElm, refElm){
550+
if(isUndef(vnode)){
551+
if(isDef(oldVnode)){ invokeDestroyHook(oldVnode); }
552+
return ;
553+
}
554+
var isInitialPatch = false;
555+
var insertedVnodeQueue = [];
556+
557+
if(isUndef(oldVnode)){
558+
isInitialPatch = true;
559+
createElm(vnode, insertedVnodeQueue, parentElm, refElm);
560+
} else{
561+
var isRealElement = isDef(oldVnode.nodeType);
562+
if(!isRealElement && sameVnode(oldVnode, vnode)){
563+
patchVnode(oldVnode, vnode, insertedVnodeQueue, removeOnly);
564+
} else{
565+
if(isRealElement){
566+
if(oldVnode.nodeType === 1 && oldVnode.hasAttribute('server-rendered')){
567+
oldVnode.removeAttribute('server-rendered');
568+
hydrating = true;
569+
}
570+
if(isTrue(hydrating)){
571+
if(hydrate(oldVnode, vnode, insertedVnodeQueue)){
572+
invokeInsertHook(vnode, insertedVnodeQueue, true);
573+
return oldVnode;
574+
} else{
575+
warn(
576+
'The client-side rendered virtual DOM tree is not matching ' +
577+
'server-rendered content. This is likely caused by incorrect ' +
578+
'HTML markup, for example nesting block-level elements inside ' +
579+
'<p>, or missing <tbody>. Bailing hydration and performing ' +
580+
'full client-side render.'
581+
);
582+
}
583+
}
584+
//
585+
oldVnode = emptyNodeAt(oldVnode);
586+
}
587+
//
588+
var oldElm = oldVnode.elm;
589+
var parentElm$1 = nodeOps.parentNode(oldElm);
590+
createElm(
591+
vnode,
592+
insertedVnodeQueue,
593+
//
594+
oldElm._leaveCb ? null : parentElm$1,
595+
nodeOps.nextSibling(oldElm)
596+
);
597+
598+
if(isDef(vnode.parent)){
599+
var ancestor = vnode.parent;
600+
while(ancestor){
601+
ancestor.elm = vnode.elm;
602+
ancestor = ancestor.parent;
603+
}
604+
if(isPatchable(vnode)){
605+
for(var i = 0; i < cbs.create.length; ++i){
606+
cbs.create[i](emptyNode, vnode.parent);
607+
}
608+
}
609+
}
610+
if(isDef(parentElm$1)){
611+
removeVnodes(parentElm$1, [oldVnode], 0, 0);
612+
} else if(isDef(oldVnode.tag)){
613+
invokeDestroyHook(oldVnode);
614+
}
382615
}
383616
}
617+
invokeInsertHook(vnode, insertedVnodeQueue, isInitialPatch);
618+
return vnode.elm;
384619
}
385620
}
386621
```

0 commit comments

Comments
 (0)