@@ -11,6 +11,7 @@ const TRANSITION_END_EVENT = 'transitionend'
11
11
export interface CollectionViewDelegate {
12
12
getCount ( ) : number
13
13
configureElement ( element : HTMLElement , index : number ) : void
14
+ invalidateElement ?( element : HTMLElement , index : number ) : void
14
15
onScroll ?( collectionView : CollectionView ) : void
15
16
}
16
17
@@ -162,12 +163,8 @@ export default class CollectionView {
162
163
elementHandler ( element ) )
163
164
}
164
165
165
- this . _elements . forEach ( ( element ) => {
166
- const parent = element . parentElement
167
- if ( parent ) {
168
- parent . removeChild ( element )
169
- }
170
- } )
166
+ this . _elements . forEach ( ( element ) =>
167
+ this . removeElement ( element ) )
171
168
}
172
169
173
170
private get currentContainerSize ( ) : NumberTuple {
@@ -249,8 +246,9 @@ export default class CollectionView {
249
246
this . updateIndices ( this . currentIndices )
250
247
}
251
248
249
+ // update elements when viewport changes (e.g. when scrolling)
252
250
private updateIndices ( newIndices : number [ ] ) : void {
253
- // determine old elements
251
+ // determine old elements. save invalid elements so they can be reused
254
252
const invalidElements : HTMLElement [ ] = [ ]
255
253
256
254
this . _elements . forEach ( ( element , index ) => {
@@ -259,13 +257,18 @@ export default class CollectionView {
259
257
}
260
258
261
259
this . _elements . delete ( index )
260
+ if ( this . delegate . invalidateElement ) {
261
+ this . delegate . invalidateElement ( element , index )
262
+ }
263
+
262
264
invalidElements . push ( element )
263
265
} )
264
266
265
267
// add missing elements
266
268
const currentIndices = this . _visibleIndices
267
269
newIndices . filter ( ( index ) => currentIndices . indexOf ( index ) < 0 )
268
270
. forEach ( ( index ) => {
271
+ // reuse one of the invalid/old elements, or create a new element
269
272
const element = invalidElements . pop ( )
270
273
|| this . createAndAddElement ( )
271
274
this . configureElement ( this . _layout , element , index )
@@ -280,10 +283,7 @@ export default class CollectionView {
280
283
if ( element == null ) {
281
284
return
282
285
}
283
- const parent = element . parentElement
284
- if ( parent ) {
285
- parent . removeChild ( element )
286
- }
286
+ this . removeElement ( element )
287
287
} )
288
288
}
289
289
@@ -384,6 +384,8 @@ export default class CollectionView {
384
384
}
385
385
386
386
setTimeout ( ( ) => {
387
+ this . updateIndices ( futureIndices )
388
+
387
389
if ( completion ) {
388
390
completion ( )
389
391
}
@@ -420,6 +422,15 @@ export default class CollectionView {
420
422
requestAnimationFrame ( scroll )
421
423
}
422
424
425
+ private removeElement ( element : HTMLElement ) {
426
+ const parent = element . parentElement
427
+ if ( ! parent ) {
428
+ return ;
429
+ }
430
+
431
+ parent . removeChild ( element )
432
+ }
433
+
423
434
public changeIndices ( removedIndices : number [ ] , addedIndices : number [ ] , movedIndexMap : Map < number , number > ) : void {
424
435
425
436
// handle legacy Object
@@ -489,12 +500,16 @@ export default class CollectionView {
489
500
490
501
element . classList . add ( this . disappearingClassName )
491
502
element . style . zIndex = '0'
503
+
504
+ // NOTE: notify delegate about invalidation after element was removed
505
+ // (animation finished), not immediately when stopping to keep track of it
492
506
setTimeout ( ( ) => {
493
- const parent = element . parentElement
494
- if ( parent ) {
495
- parent . removeChild ( element )
496
- }
497
- } , this . animationDuration )
507
+ this . removeElement ( element )
508
+ if ( this . delegate . invalidateElement ) {
509
+ this . delegate . invalidateElement ( element , index )
510
+ }
511
+ } ,
512
+ this . animationDuration )
498
513
this . _elements . delete ( index )
499
514
} )
500
515
0 commit comments