14
14
15
15
import config from '../config'
16
16
import VNode from './vnode'
17
- import { isPrimitive , _toString , warn } from '../util/index'
17
+ import { makeMap , isPrimitive , _toString , warn } from '../util/index'
18
18
import { activeInstance } from '../instance/lifecycle'
19
19
import { registerRef } from './modules/ref'
20
20
@@ -468,6 +468,11 @@ export function createPatchFunction (backend) {
468
468
}
469
469
470
470
let bailed = false
471
+ // list of modules that can skip create hook during hydration because they
472
+ // are already rendered on the client or has no need for initialization
473
+ const isRenderedModule = makeMap ( 'attrs,style,class,staticClass,staticStyle,key' )
474
+
475
+ // Note: this is a browser-only function so we can assume elms are DOM nodes.
471
476
function hydrate ( elm , vnode , insertedVnodeQueue ) {
472
477
if ( process . env . NODE_ENV !== 'production' ) {
473
478
if ( ! assertNodeMatch ( elm , vnode ) ) {
@@ -486,36 +491,40 @@ export function createPatchFunction (backend) {
486
491
}
487
492
if ( isDef ( tag ) ) {
488
493
if ( isDef ( children ) ) {
489
- const childNodes = nodeOps . childNodes ( elm )
490
494
// empty element, allow client to pick up and populate children
491
- if ( ! childNodes . length ) {
495
+ if ( ! elm . hasChildNodes ( ) ) {
492
496
createChildren ( vnode , children , insertedVnodeQueue )
493
497
} else {
494
498
let childrenMatch = true
495
- if ( childNodes . length !== children . length ) {
496
- childrenMatch = false
497
- } else {
498
- for ( let i = 0 ; i < children . length ; i ++ ) {
499
- if ( ! hydrate ( childNodes [ i ] , children [ i ] , insertedVnodeQueue ) ) {
500
- childrenMatch = false
501
- break
502
- }
499
+ let childNode = elm . firstChild
500
+ for ( let i = 0 ; i < children . length ; i ++ ) {
501
+ if ( ! childNode || ! hydrate ( childNode , children [ i ] , insertedVnodeQueue ) ) {
502
+ childrenMatch = false
503
+ break
503
504
}
505
+ childNode = childNode . nextSibling
504
506
}
505
- if ( ! childrenMatch ) {
507
+ // if childNode is not null, it means the actual childNodes list is
508
+ // longer than the virtual children list.
509
+ if ( ! childrenMatch || childNode ) {
506
510
if ( process . env . NODE_ENV !== 'production' &&
507
511
typeof console !== 'undefined' &&
508
512
! bailed ) {
509
513
bailed = true
510
514
console . warn ( 'Parent: ' , elm )
511
- console . warn ( 'Mismatching childNodes vs. VNodes: ' , childNodes , children )
515
+ console . warn ( 'Mismatching childNodes vs. VNodes: ' , elm . childNodes , children )
512
516
}
513
517
return false
514
518
}
515
519
}
516
520
}
517
521
if ( isDef ( data ) ) {
518
- invokeCreateHooks ( vnode , insertedVnodeQueue )
522
+ for ( const key in data ) {
523
+ if ( ! isRenderedModule ( key ) ) {
524
+ invokeCreateHooks ( vnode , insertedVnodeQueue )
525
+ break
526
+ }
527
+ }
519
528
}
520
529
}
521
530
return true
@@ -525,7 +534,7 @@ export function createPatchFunction (backend) {
525
534
if ( vnode . tag ) {
526
535
return (
527
536
vnode . tag . indexOf ( 'vue-component' ) === 0 ||
528
- vnode . tag . toLowerCase ( ) === nodeOps . tagName ( node ) . toLowerCase ( )
537
+ vnode . tag . toLowerCase ( ) === node . tagName . toLowerCase ( )
529
538
)
530
539
} else {
531
540
return _toString ( vnode . text ) === node . data
0 commit comments