@@ -132,6 +132,12 @@ module.exports = {
132132 this . buildItem ( )
133133 this . initiated = true
134134 }
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+
135141 collection = this . collection = collection || [ ]
136142 this . vms = [ ]
137143 if ( this . childId ) {
@@ -143,11 +149,25 @@ module.exports = {
143149 if ( ! collection . __observer__ ) Observer . watchArray ( collection )
144150 collection . __observer__ . on ( 'mutate' , this . mutationListener )
145151
146- // create child-vms and append to DOM
152+ // create new VMs and append to DOM
147153 if ( collection . length ) {
148154 collection . forEach ( this . buildItem , this )
149155 if ( ! init ) this . changed ( )
150156 }
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
151171 } ,
152172
153173 /**
@@ -174,33 +194,58 @@ module.exports = {
174194 */
175195 buildItem : function ( data , index ) {
176196
177- var el = this . el . cloneNode ( true ) ,
178- ctn = this . container ,
197+ var ctn = this . container ,
179198 vms = this . vms ,
180199 col = this . collection ,
181- ref , item , primitive
200+ el , i , ref , item , primitive , noInsert
182201
183202 // append node into DOM first
184203 // so v-if can get access to parentNode
185204 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+
186235 ref = vms . length > index
187236 ? vms [ index ] . $el
188237 : this . ref
189238 // make sure it works with v-if
190239 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 )
200245 }
201246 }
202247
203- item = new this . Ctor ( {
248+ item = item || new this . Ctor ( {
204249 el : el ,
205250 data : data ,
206251 compilerOptions : {
@@ -228,15 +273,17 @@ module.exports = {
228273 }
229274 } ,
230275
231- reset : function ( ) {
276+ reset : function ( destroyAll ) {
232277 if ( this . childId ) {
233278 delete this . vm . $ [ this . childId ]
234279 }
235280 if ( this . collection ) {
236281 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+ }
240287 }
241288 }
242289 var ctn = this . container ,
@@ -248,6 +295,6 @@ module.exports = {
248295 } ,
249296
250297 unbind : function ( ) {
251- this . reset ( )
298+ this . reset ( true )
252299 }
253300}
0 commit comments