@@ -92,35 +92,6 @@ var mutationHandlers = {
92
92
}
93
93
}
94
94
95
- /**
96
- * Convert an Object to a v-repeat friendly Array
97
- */
98
- function objectToArray ( obj ) {
99
- var res = [ ] , val , data
100
- for ( var key in obj ) {
101
- val = obj [ key ]
102
- data = utils . typeOf ( val ) === 'Object'
103
- ? val
104
- : { $value : val }
105
- def ( data , '$key' , key )
106
- res . push ( data )
107
- }
108
- return res
109
- }
110
-
111
- /**
112
- * Find an object or a wrapped data object
113
- * from an Array
114
- */
115
- function indexOf ( arr , obj ) {
116
- for ( var i = 0 , l = arr . length ; i < l ; i ++ ) {
117
- if ( arr [ i ] === obj || ( obj . $value && arr [ i ] . $value === obj . $value ) ) {
118
- return i
119
- }
120
- }
121
- return - 1
122
- }
123
-
124
95
module . exports = {
125
96
126
97
bind : function ( ) {
@@ -178,8 +149,7 @@ module.exports = {
178
149
// force a compile so that we get all the bindings for
179
150
// dependency extraction.
180
151
if ( ! this . initiated && ( ! collection || ! collection . length ) ) {
181
- this . buildItem ( )
182
- this . initiated = true
152
+ this . dryBuild ( )
183
153
}
184
154
185
155
// keep reference of old data and VMs
@@ -205,17 +175,7 @@ module.exports = {
205
175
}
206
176
207
177
// destroy unused old VMs
208
- if ( oldVMs ) {
209
- var i = oldVMs . length , vm
210
- while ( i -- ) {
211
- vm = oldVMs [ i ]
212
- if ( vm . $reused ) {
213
- vm . $reused = false
214
- } else {
215
- vm . $destroy ( )
216
- }
217
- }
218
- }
178
+ if ( oldVMs ) destroyVMs ( oldVMs )
219
179
this . old = this . oldVMs = null
220
180
} ,
221
181
@@ -236,6 +196,20 @@ module.exports = {
236
196
} )
237
197
} ,
238
198
199
+ /**
200
+ * Run a dry buildItem just to collect bindings
201
+ */
202
+ dryBuild : function ( ) {
203
+ new this . Ctor ( {
204
+ el : this . el . cloneNode ( true ) ,
205
+ compilerOptions : {
206
+ repeat : true ,
207
+ parentCompiler : this . compiler
208
+ }
209
+ } ) . $destroy ( )
210
+ this . initiated = true
211
+ } ,
212
+
239
213
/**
240
214
* Create a new child VM from a data object
241
215
* passing along compiler options indicating this
@@ -246,103 +220,92 @@ module.exports = {
246
220
var ctn = this . container ,
247
221
vms = this . vms ,
248
222
col = this . collection ,
249
- el , i , existing , ref , item , primitive , detached
223
+ el , oldIndex , existing , item , nonObject
224
+
225
+ // get our DOM insertion reference node
226
+ var ref = vms . length > index
227
+ ? vms [ index ] . $el
228
+ : this . ref
229
+
230
+ // if reference VM is detached by v-if,
231
+ // use its v-if ref node instead
232
+ if ( ! ref . parentNode ) {
233
+ ref = ref . vue_if_ref
234
+ }
250
235
251
- // append node into DOM first
252
- // so v-if can get access to parentNode
253
- // TODO: logic here is a total mess.
254
- if ( data ) {
236
+ // check if data already exists in the old array
237
+ oldIndex = this . old ? indexOf ( this . old , data ) : - 1
238
+ existing = oldIndex > - 1
255
239
256
- if ( this . old ) {
257
- i = indexOf ( this . old , data )
258
- }
259
- existing = i > - 1
260
-
261
- if ( existing ) { // existing, reuse the old VM
262
-
263
- item = this . oldVMs [ i ]
264
- // mark, so it won't be destroyed
265
- item . $reused = true
266
- el = item . $el
267
- // existing VM's el can possibly be detached by v-if.
268
- // in that case don't insert.
269
- detached = ! el . parentNode
270
-
271
- } else { // new data, need to create new VM
272
-
273
- el = this . el . cloneNode ( true )
274
- // process transition info before appending
275
- el . vue_trans = utils . attr ( el , 'transition' , true )
276
- el . vue_anim = utils . attr ( el , 'animation' , true )
277
- el . vue_effect = utils . attr ( el , 'effect' , true )
278
- // wrap primitive element in an object
279
- if ( utils . typeOf ( data ) !== 'Object' ) {
280
- primitive = true
281
- data = { $value : data }
282
- }
240
+ if ( existing ) {
283
241
284
- }
242
+ // existing, reuse the old VM
243
+ item = this . oldVMs [ oldIndex ]
244
+ // mark, so it won't be destroyed
245
+ item . $reused = true
285
246
286
- ref = vms . length > index
287
- ? vms [ index ] . $el
288
- : this . ref
289
-
290
- // if ref VM's el is detached by v-if
291
- // use its v-if ref node instead
292
- if ( ! ref . parentNode ) {
293
- ref = ref . vue_if_ref
294
- }
247
+ } else {
295
248
296
- if ( existing ) {
297
- // existing node
298
- // if not detached, just re-insert to new location
299
- // else re-insert its v-if ref node
300
- ctn . insertBefore ( detached ? el . vue_if_ref : el , ref )
301
- } else {
302
- // new node, prepare it for v-if
303
- el . vue_if_parent = ctn
304
- el . vue_if_ref = ref
249
+ // new data, need to create new VM.
250
+ // there's some preparation work to do...
251
+
252
+ // first clone the template node
253
+ el = this . el . cloneNode ( true )
254
+ // then we provide the parentNode for v-if
255
+ // so that it can still work in a detached state
256
+ el . vue_if_parent = ctn
257
+ el . vue_if_ref = ref
258
+ // wrap non-object value in an object
259
+ nonObject = utils . typeOf ( data ) !== 'Object'
260
+ if ( nonObject ) {
261
+ data = { $value : data }
305
262
}
306
- // set index so vm can init with it
307
- // and do not trigger stuff early
263
+ // set index so vm can init with the correct
264
+ // index instead of undefined
308
265
data . $index = index
309
- }
310
-
311
- item = item || new this . Ctor ( {
312
- el : el ,
313
- data : data ,
314
- compilerOptions : {
315
- repeat : true ,
316
- parentCompiler : this . compiler
317
- }
318
- } )
319
- item . $index = index
320
-
321
- if ( ! data ) {
322
- // this is a forced compile for an empty collection.
323
- // let's remove it...
324
- item . $destroy ( )
325
- } else {
326
- vms . splice ( index , 0 , item )
327
-
328
- // for primitive values, listen for value change
329
- if ( primitive ) {
266
+ // initialize the new VM
267
+ item = new this . Ctor ( {
268
+ el : el ,
269
+ data : data ,
270
+ compilerOptions : {
271
+ repeat : true ,
272
+ parentCompiler : this . compiler
273
+ }
274
+ } )
275
+ // for non-object values, listen for value change
276
+ // so we can sync it back to the original Array
277
+ if ( nonObject ) {
330
278
item . $compiler . observer . on ( 'set' , function ( key , val ) {
331
279
if ( key === '$value' ) {
332
280
col [ item . $index ] = val
333
281
}
334
282
} )
335
283
}
336
284
337
- // new instance and v-if doesn't want it detached
338
- // good to insert.
339
- if ( ! existing && el . vue_if !== false ) {
285
+ }
286
+
287
+ // put the item into the VM Array
288
+ vms . splice ( index , 0 , item )
289
+ // update the index
290
+ item . $index = index
291
+
292
+ // Finally, DOM operations...
293
+ el = item . $el
294
+ if ( existing ) {
295
+ // we simplify need to re-insert the existing node
296
+ // to its new position. However, it can possibly be
297
+ // detached by v-if. in that case we insert its v-if
298
+ // ref node instead.
299
+ ctn . insertBefore ( el . parentNode ? el : el . vue_if_ref , ref )
300
+ } else {
301
+ if ( el . vue_if !== false ) {
340
302
if ( this . compiler . init ) {
341
- // do not transition on initial compile.
342
- ctn . insertBefore ( item . $el , ref )
303
+ // do not transition on initial compile,
304
+ // just manually insert.
305
+ ctn . insertBefore ( el , ref )
343
306
item . $compiler . execHook ( 'attached' )
344
307
} else {
345
- // transition in.. .
308
+ // give it some nice transition .
346
309
item . $before ( ref )
347
310
}
348
311
}
@@ -401,8 +364,6 @@ module.exports = {
401
364
var key = vm . $key ,
402
365
val = vm . $value || vm . $data
403
366
if ( action > 0 ) { // new property
404
- // make key ienumerable
405
- delete vm . $data . $key
406
367
obj [ key ] = val
407
368
Observer . convert ( obj , key )
408
369
} else {
@@ -412,22 +373,65 @@ module.exports = {
412
373
}
413
374
} ,
414
375
415
- reset : function ( destroyAll ) {
376
+ reset : function ( destroy ) {
416
377
if ( this . childId ) {
417
378
delete this . vm . $ [ this . childId ]
418
379
}
419
380
if ( this . collection ) {
420
381
this . collection . __emitter__ . off ( 'mutate' , this . mutationListener )
421
- if ( destroyAll ) {
422
- var i = this . vms . length
423
- while ( i -- ) {
424
- this . vms [ i ] . $destroy ( )
425
- }
382
+ if ( destroy ) {
383
+ destroyVMs ( this . vms )
426
384
}
427
385
}
428
386
} ,
429
387
430
388
unbind : function ( ) {
431
389
this . reset ( true )
432
390
}
391
+ }
392
+
393
+ // Helpers --------------------------------------------------------------------
394
+
395
+ /**
396
+ * Convert an Object to a v-repeat friendly Array
397
+ */
398
+ function objectToArray ( obj ) {
399
+ var res = [ ] , val , data
400
+ for ( var key in obj ) {
401
+ val = obj [ key ]
402
+ data = utils . typeOf ( val ) === 'Object'
403
+ ? val
404
+ : { $value : val }
405
+ def ( data , '$key' , key )
406
+ res . push ( data )
407
+ }
408
+ return res
409
+ }
410
+
411
+ /**
412
+ * Find an object or a wrapped data object
413
+ * from an Array
414
+ */
415
+ function indexOf ( arr , obj ) {
416
+ for ( var i = 0 , l = arr . length ; i < l ; i ++ ) {
417
+ if ( arr [ i ] === obj || ( obj . $value && arr [ i ] . $value === obj . $value ) ) {
418
+ return i
419
+ }
420
+ }
421
+ return - 1
422
+ }
423
+
424
+ /**
425
+ * Destroy some VMs, yeah.
426
+ */
427
+ function destroyVMs ( vms ) {
428
+ var i = vms . length , vm
429
+ while ( i -- ) {
430
+ vm = vms [ i ]
431
+ if ( vm . $reused ) {
432
+ vm . $reused = false
433
+ } else {
434
+ vm . $destroy ( )
435
+ }
436
+ }
433
437
}
0 commit comments