@@ -85,19 +85,26 @@ export function createPatchFunction (backend) {
85
85
}
86
86
87
87
let inPre = 0
88
- function createElm ( vnode , insertedVnodeQueue , nested ) {
89
- let i
88
+ function createElm ( vnode , insertedVnodeQueue , parentElm , refElm , nested ) {
89
+ let i , isReactivated
90
90
const data = vnode . data
91
91
vnode . isRootInsert = ! nested
92
92
if ( isDef ( data ) ) {
93
- if ( isDef ( i = data . hook ) && isDef ( i = i . init ) ) i ( vnode )
93
+ if ( isDef ( i = data . hook ) && isDef ( i = i . init ) ) {
94
+ isReactivated = i ( vnode , false /* hydrating */ , parentElm , refElm )
95
+ }
94
96
// after calling the init hook, if the vnode is a child component
95
97
// it should've created a child instance and mounted it. the child
96
98
// component also has set the placeholder vnode's elm.
97
99
// in that case we can just return the element and be done.
98
100
if ( isDef ( i = vnode . child ) ) {
99
101
initComponent ( vnode , insertedVnodeQueue )
100
- return vnode . elm
102
+ if ( isReactivated ) {
103
+ // unlike a newly created component,
104
+ // a reactivated keep-alive component doesn't insert itself
105
+ insert ( parentElm , vnode . child . $el , refElm )
106
+ }
107
+ return
101
108
}
102
109
}
103
110
const children = vnode . children
@@ -125,25 +132,61 @@ export function createPatchFunction (backend) {
125
132
? nodeOps . createElementNS ( vnode . ns , tag )
126
133
: nodeOps . createElement ( tag , vnode )
127
134
setScope ( vnode )
128
- createChildren ( vnode , children , insertedVnodeQueue )
129
- if ( isDef ( data ) ) {
130
- invokeCreateHooks ( vnode , insertedVnodeQueue )
135
+
136
+ if ( __WEEX__ ) {
137
+ // Detect long lists:
138
+ // If the list is longer than a certain threshold, it may take to long
139
+ // to compute the whole tree before being able to send messages to the
140
+ // native client. When we detect such a case, we will append the parent
141
+ // element FIRST, so that each child can be drawn as soon as possible
142
+ // by the native client, resulting in faster initial render and better
143
+ // perceived UX.
144
+ const isLongList =
145
+ Array . isArray ( children ) &&
146
+ children . length >= backend . LONG_LIST_THRESHOLD
147
+ if ( isLongList ) {
148
+ if ( isDef ( data ) ) {
149
+ invokeCreateHooks ( vnode , insertedVnodeQueue )
150
+ }
151
+ insert ( parentElm , vnode . elm , refElm )
152
+ }
153
+ createChildren ( vnode , children , insertedVnodeQueue )
154
+ if ( ! isLongList ) {
155
+ if ( isDef ( data ) ) {
156
+ invokeCreateHooks ( vnode , insertedVnodeQueue )
157
+ }
158
+ insert ( parentElm , vnode . elm , refElm )
159
+ }
160
+ } else {
161
+ createChildren ( vnode , children , insertedVnodeQueue )
162
+ if ( isDef ( data ) ) {
163
+ invokeCreateHooks ( vnode , insertedVnodeQueue )
164
+ }
165
+ insert ( parentElm , vnode . elm , refElm )
131
166
}
167
+
132
168
if ( process . env . NODE_ENV !== 'production' && data && data . pre ) {
133
169
inPre --
134
170
}
135
171
} else if ( vnode . isComment ) {
136
172
vnode . elm = nodeOps . createComment ( vnode . text )
173
+ insert ( parentElm , vnode . elm , refElm )
137
174
} else {
138
175
vnode . elm = nodeOps . createTextNode ( vnode . text )
176
+ insert ( parentElm , vnode . elm , refElm )
177
+ }
178
+ }
179
+
180
+ function insert ( parent , elm , ref ) {
181
+ if ( parent ) {
182
+ nodeOps . insertBefore ( parent , elm , ref )
139
183
}
140
- return vnode . elm
141
184
}
142
185
143
186
function createChildren ( vnode , children , insertedVnodeQueue ) {
144
187
if ( Array . isArray ( children ) ) {
145
188
for ( let i = 0 ; i < children . length ; ++ i ) {
146
- nodeOps . appendChild ( vnode . elm , createElm ( children [ i ] , insertedVnodeQueue , true ) )
189
+ createElm ( children [ i ] , insertedVnodeQueue , vnode . elm , null , true )
147
190
}
148
191
} else if ( isPrimitive ( vnode . text ) ) {
149
192
nodeOps . appendChild ( vnode . elm , nodeOps . createTextNode ( vnode . text ) )
@@ -200,9 +243,9 @@ export function createPatchFunction (backend) {
200
243
}
201
244
}
202
245
203
- function addVnodes ( parentElm , before , vnodes , startIdx , endIdx , insertedVnodeQueue ) {
246
+ function addVnodes ( parentElm , refElm , vnodes , startIdx , endIdx , insertedVnodeQueue ) {
204
247
for ( ; startIdx <= endIdx ; ++ startIdx ) {
205
- nodeOps . insertBefore ( parentElm , createElm ( vnodes [ startIdx ] , insertedVnodeQueue ) , before )
248
+ createElm ( vnodes [ startIdx ] , insertedVnodeQueue , parentElm , refElm )
206
249
}
207
250
}
208
251
@@ -271,7 +314,7 @@ export function createPatchFunction (backend) {
271
314
let newEndIdx = newCh . length - 1
272
315
let newStartVnode = newCh [ 0 ]
273
316
let newEndVnode = newCh [ newEndIdx ]
274
- let oldKeyToIdx , idxInOld , elmToMove , before
317
+ let oldKeyToIdx , idxInOld , elmToMove , refElm
275
318
276
319
// removeOnly is a special flag used only by <transition-group>
277
320
// to ensure removed elements stay in correct relative positions
@@ -305,7 +348,7 @@ export function createPatchFunction (backend) {
305
348
if ( isUndef ( oldKeyToIdx ) ) oldKeyToIdx = createKeyToOldIdx ( oldCh , oldStartIdx , oldEndIdx )
306
349
idxInOld = isDef ( newStartVnode . key ) ? oldKeyToIdx [ newStartVnode . key ] : null
307
350
if ( isUndef ( idxInOld ) ) { // New element
308
- nodeOps . insertBefore ( parentElm , createElm ( newStartVnode , insertedVnodeQueue ) , oldStartVnode . elm )
351
+ createElm ( newStartVnode , insertedVnodeQueue , parentElm , oldStartVnode . elm )
309
352
newStartVnode = newCh [ ++ newStartIdx ]
310
353
} else {
311
354
elmToMove = oldCh [ idxInOld ]
@@ -318,7 +361,7 @@ export function createPatchFunction (backend) {
318
361
}
319
362
if ( elmToMove . tag !== newStartVnode . tag ) {
320
363
// same key but different element. treat as new element
321
- nodeOps . insertBefore ( parentElm , createElm ( newStartVnode , insertedVnodeQueue ) , oldStartVnode . elm )
364
+ createElm ( newStartVnode , insertedVnodeQueue , parentElm , oldStartVnode . elm )
322
365
newStartVnode = newCh [ ++ newStartIdx ]
323
366
} else {
324
367
patchVnode ( elmToMove , newStartVnode , insertedVnodeQueue )
@@ -330,8 +373,8 @@ export function createPatchFunction (backend) {
330
373
}
331
374
}
332
375
if ( oldStartIdx > oldEndIdx ) {
333
- before = isUndef ( newCh [ newEndIdx + 1 ] ) ? null : newCh [ newEndIdx + 1 ] . elm
334
- addVnodes ( parentElm , before , newCh , newStartIdx , newEndIdx , insertedVnodeQueue )
376
+ refElm = isUndef ( newCh [ newEndIdx + 1 ] ) ? null : newCh [ newEndIdx + 1 ] . elm
377
+ addVnodes ( parentElm , refElm , newCh , newStartIdx , newEndIdx , insertedVnodeQueue )
335
378
} else if ( newStartIdx > newEndIdx ) {
336
379
removeVnodes ( parentElm , oldCh , oldStartIdx , oldEndIdx )
337
380
}
@@ -462,7 +505,7 @@ export function createPatchFunction (backend) {
462
505
}
463
506
}
464
507
465
- return function patch ( oldVnode , vnode , hydrating , removeOnly ) {
508
+ return function patch ( oldVnode , vnode , hydrating , removeOnly , parentElm , refElm ) {
466
509
if ( ! vnode ) {
467
510
if ( oldVnode ) invokeDestroyHook ( oldVnode )
468
511
return
@@ -473,12 +516,13 @@ export function createPatchFunction (backend) {
473
516
const insertedVnodeQueue = [ ]
474
517
475
518
if ( ! oldVnode ) {
476
- // empty mount, create new root element
519
+ // empty mount (likely as component) , create new root element
477
520
isInitialPatch = true
478
- createElm ( vnode , insertedVnodeQueue )
521
+ createElm ( vnode , insertedVnodeQueue , parentElm , refElm )
479
522
} else {
480
523
const isRealElement = isDef ( oldVnode . nodeType )
481
524
if ( ! isRealElement && sameVnode ( oldVnode , vnode ) ) {
525
+ // patch existing root node
482
526
patchVnode ( oldVnode , vnode , insertedVnodeQueue , removeOnly )
483
527
} else {
484
528
if ( isRealElement ) {
@@ -507,14 +551,15 @@ export function createPatchFunction (backend) {
507
551
// create an empty node and replace it
508
552
oldVnode = emptyNodeAt ( oldVnode )
509
553
}
554
+
555
+ // replacing existing element
510
556
elm = oldVnode . elm
511
557
parent = nodeOps . parentNode ( elm )
558
+ createElm ( vnode , insertedVnodeQueue , parent , nodeOps . nextSibling ( elm ) )
512
559
513
- createElm ( vnode , insertedVnodeQueue )
514
-
515
- // component root element replaced.
516
- // update parent placeholder node element, recursively
517
560
if ( vnode . parent ) {
561
+ // component root element replaced.
562
+ // update parent placeholder node element, recursively
518
563
let ancestor = vnode . parent
519
564
while ( ancestor ) {
520
565
ancestor . elm = vnode . elm
@@ -528,7 +573,6 @@ export function createPatchFunction (backend) {
528
573
}
529
574
530
575
if ( parent !== null ) {
531
- nodeOps . insertBefore ( parent , vnode . elm , nodeOps . nextSibling ( elm ) )
532
576
removeVnodes ( parent , [ oldVnode ] , 0 , 0 )
533
577
} else if ( isDef ( oldVnode . tag ) ) {
534
578
invokeDestroyHook ( oldVnode )
0 commit comments