@@ -132,6 +132,12 @@ module.exports = {
132
132
this . buildItem ( )
133
133
this . initiated = true
134
134
}
135
+
136
+ // keep reference of old data and VMs
137
+ // so we can reuse them if possible
138
+ this . old = this . collection
139
+ var oldVMs = this . oldVMs = this . vms
140
+
135
141
collection = this . collection = collection || [ ]
136
142
this . vms = [ ]
137
143
if ( this . childId ) {
@@ -143,11 +149,25 @@ module.exports = {
143
149
if ( ! collection . __observer__ ) Observer . watchArray ( collection )
144
150
collection . __observer__ . on ( 'mutate' , this . mutationListener )
145
151
146
- // create child-vms and append to DOM
152
+ // create new VMs and append to DOM
147
153
if ( collection . length ) {
148
154
collection . forEach ( this . buildItem , this )
149
155
if ( ! init ) this . changed ( )
150
156
}
157
+
158
+ // destroy unused old VMs
159
+ if ( oldVMs ) {
160
+ var i = oldVMs . length , vm
161
+ while ( i -- ) {
162
+ vm = oldVMs [ i ]
163
+ if ( vm . $reused ) {
164
+ vm . $reused = false
165
+ } else {
166
+ vm . $destroy ( )
167
+ }
168
+ }
169
+ }
170
+ this . old = this . oldVMs = null
151
171
} ,
152
172
153
173
/**
@@ -174,33 +194,58 @@ module.exports = {
174
194
*/
175
195
buildItem : function ( data , index ) {
176
196
177
- var el = this . el . cloneNode ( true ) ,
178
- ctn = this . container ,
197
+ var ctn = this . container ,
179
198
vms = this . vms ,
180
199
col = this . collection ,
181
- ref , item , primitive
200
+ el , i , ref , item , primitive , noInsert
182
201
183
202
// append node into DOM first
184
203
// so v-if can get access to parentNode
185
204
if ( data ) {
205
+
206
+ if ( this . old ) {
207
+ i = this . old . indexOf ( data )
208
+ }
209
+
210
+ if ( i > - 1 ) { // existing, reuse the old VM
211
+
212
+ item = this . oldVMs [ i ]
213
+ // mark, so it won't be destroyed
214
+ item . $reused = true
215
+ el = item . $el
216
+ // don't forget to update index
217
+ data . $index = index
218
+ // existing VM's el can possibly be detached by v-if.
219
+ // in that case don't insert.
220
+ noInsert = ! el . parentNode
221
+
222
+ } else { // new data, need to create new VM
223
+
224
+ el = this . el . cloneNode ( true )
225
+ // process transition info before appending
226
+ el . vue_trans = utils . attr ( el , 'transition' , true )
227
+ // wrap primitive element in an object
228
+ if ( utils . typeOf ( data ) !== 'Object' ) {
229
+ primitive = true
230
+ data = { value : data }
231
+ }
232
+
233
+ }
234
+
186
235
ref = vms . length > index
187
236
? vms [ index ] . $el
188
237
: this . ref
189
238
// make sure it works with v-if
190
239
if ( ! ref . parentNode ) ref = ref . vue_ref
191
- // process transition info before appending
192
- el . vue_trans = utils . attr ( el , 'transition' , true )
193
- transition ( el , 1 , function ( ) {
194
- ctn . insertBefore ( el , ref )
195
- } , this . compiler )
196
- // wrap primitive element in an object
197
- if ( utils . typeOf ( data ) !== 'Object' ) {
198
- primitive = true
199
- data = { value : data }
240
+ // insert node with transition
241
+ if ( ! noInsert ) {
242
+ transition ( el , 1 , function ( ) {
243
+ ctn . insertBefore ( el , ref )
244
+ } , this . compiler )
200
245
}
201
246
}
202
247
203
- item = new this . Ctor ( {
248
+ item = item || new this . Ctor ( {
204
249
el : el ,
205
250
data : data ,
206
251
compilerOptions : {
@@ -228,15 +273,17 @@ module.exports = {
228
273
}
229
274
} ,
230
275
231
- reset : function ( ) {
276
+ reset : function ( destroyAll ) {
232
277
if ( this . childId ) {
233
278
delete this . vm . $ [ this . childId ]
234
279
}
235
280
if ( this . collection ) {
236
281
this . collection . __observer__ . off ( 'mutate' , this . mutationListener )
237
- var i = this . vms . length
238
- while ( i -- ) {
239
- this . vms [ i ] . $destroy ( )
282
+ if ( destroyAll ) {
283
+ var i = this . vms . length
284
+ while ( i -- ) {
285
+ this . vms [ i ] . $destroy ( )
286
+ }
240
287
}
241
288
}
242
289
var ctn = this . container ,
@@ -248,6 +295,6 @@ module.exports = {
248
295
} ,
249
296
250
297
unbind : function ( ) {
251
- this . reset ( )
298
+ this . reset ( true )
252
299
}
253
300
}
0 commit comments