@@ -379,8 +379,243 @@ function createPatchFunction(backend){
379
379
} else {
380
380
if (isUndef (oldKeyToIdx)){ oldKeyToIdx = createKeyToOldIdx (oldCh, oldStartIdx, oldEndIdx); }
381
381
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
+ }
382
615
}
383
616
}
617
+ invokeInsertHook (vnode, insertedVnodeQueue, isInitialPatch);
618
+ return vnode .elm ;
384
619
}
385
620
}
386
621
```
0 commit comments