@@ -277,8 +277,10 @@ export default {
277277 created () {
278278 this .$_startIndex = 0
279279 this .$_endIndex = 0
280+ // Visible views by their key
280281 this .$_views = new Map ()
281- this .$_unusedViews = new Map ()
282+ // Pools of recycled views, by view type
283+ this .$_recycledPools = new Map ()
282284 this .$_scrollDirty = false
283285 this .$_lastUpdateScrollPosition = 0
284286
@@ -318,7 +320,17 @@ export default {
318320 },
319321
320322 methods: {
321- addView (pool , index , item , key , type ) {
323+ getRecycledPool (type ) {
324+ const recycledPools = this .$_recycledPools
325+ let recycledPool = recycledPools .get (type)
326+ if (! recycledPool) {
327+ recycledPool = []
328+ recycledPools .set (type, recycledPool)
329+ }
330+ return recycledPool
331+ },
332+
333+ createView (pool , index , item , key , type ) {
322334 const nr = markRaw ({
323335 id: uid++ ,
324336 index,
@@ -335,18 +347,31 @@ export default {
335347 return view
336348 },
337349
338- unuseView (view , fake = false ) {
339- const unusedViews = this .$_unusedViews
340- const type = view .nr .type
341- let unusedPool = unusedViews .get (type)
342- if (! unusedPool) {
343- unusedPool = []
344- unusedViews .set (type, unusedPool)
350+ getRecycledView (type ) {
351+ const recycledPool = this .getRecycledPool (type)
352+ if (recycledPool && recycledPool .length ) {
353+ const view = recycledPool .pop ()
354+ view .nr .used = true
355+ return view
356+ } else {
357+ return null
345358 }
346- unusedPool .push (view)
347- if (! fake) {
348- view .nr .used = false
349- view .position = - 9999
359+ },
360+
361+ removeAndRecycleView (view ) {
362+ const type = view .nr .type
363+ const recycledPool = this .getRecycledPool (type)
364+ recycledPool .push (view)
365+ view .nr .used = false
366+ view .position = - 9999
367+ this .$_views .delete (view .nr .key )
368+ },
369+
370+ removeAndRecycleAllViews () {
371+ this .$_views .clear ()
372+ this .$_recycledPools .clear ()
373+ for (let i = 0 , l = this .pool .length ; i < l; i++ ) {
374+ this .removeAndRecycleView (this .pool [i])
350375 }
351376 },
352377
@@ -397,7 +422,7 @@ export default {
397422 }
398423 },
399424
400- updateVisibleItems (checkItem , checkPositionDiff = false ) {
425+ updateVisibleItems (itemsChanged , checkPositionDiff = false ) {
401426 const itemSize = this .itemSize
402427 const gridItems = this .gridItems || 1
403428 const itemSecondarySize = this .itemSecondarySize || itemSize
@@ -408,7 +433,6 @@ export default {
408433 const count = items .length
409434 const sizes = this .sizes
410435 const views = this .$_views
411- const unusedViews = this .$_unusedViews
412436 const pool = this .pool
413437 const itemIndexByKey = this .itemIndexByKey
414438 let startIndex, endIndex
@@ -522,19 +546,30 @@ export default {
522546
523547 const continuous = startIndex <= this .$_endIndex && endIndex >= this .$_startIndex
524548
525- // Unuse views that are no longer visible
526- if (continuous) {
549+ if (this .$_continuous !== continuous) {
550+ if (continuous) {
551+ views .clear ()
552+ unusedViews .clear ()
553+ for (let i = 0 , l = pool .length ; i < l; i++ ) {
554+ view = pool[i]
555+ this .unuseView (view)
556+ }
557+ }
558+ this .$_continuous = continuous
559+ } else if (continuous) {
527560 for (let i = 0 , l = pool .length ; i < l; i++ ) {
528561 view = pool[i]
529562 if (view .nr .used ) {
530563 // Update view item index
531564 if (checkItem) {
532- view .nr .index = itemIndexByKey[view .item [keyField]]
565+ view .nr .index = items .findIndex (
566+ item => keyField ? item[keyField] === view .item [keyField] : item === view .item ,
567+ )
533568 }
534569
535570 // Check if index is still in visible range
536571 if (
537- view .nr .index == null ||
572+ view .nr .index === - 1 ||
538573 view .nr .index < startIndex ||
539574 view .nr .index >= endIndex
540575 ) {
@@ -546,11 +581,13 @@ export default {
546581
547582 const unusedIndex = continuous ? null : new Map ()
548583
549- let item, type
584+ let item, type, unusedPool
550585 let v
551586 for (let i = startIndex; i < endIndex; i++ ) {
587+ const elementSize = itemSize || sizes[i].size
588+ if (! elementSize) continue
552589 item = items[i]
553- const key = keyField ? item[keyField] : item
590+ const key = keyField ? item[keyField] : i
554591 if (key == null ) {
555592 throw new Error (` Key is ${ key} on item (keyField is '${ keyField} ')` )
556593 }
@@ -561,17 +598,20 @@ export default {
561598 continue
562599 }
563600
564- type = item[typeField]
565-
566- let unusedPool = unusedViews .get (type)
567- let newlyUsedView = false
568-
569601 // No view assigned to item
570602 if (! view) {
603+ type = item[typeField]
604+ unusedPool = unusedViews .get (type)
605+
571606 if (continuous) {
572607 // Reuse existing view
573608 if (unusedPool && unusedPool .length ) {
574609 view = unusedPool .pop ()
610+ view .item = item
611+ view .nr .used = true
612+ view .nr .index = i
613+ view .nr .key = key
614+ view .nr .type = type
575615 } else {
576616 view = this .addView (pool, i, item, key, type)
577617 }
@@ -588,7 +628,13 @@ export default {
588628 }
589629
590630 view = unusedPool[v]
631+ view .item = item
632+ view .nr .used = true
633+ view .nr .index = i
634+ view .nr .key = key
635+ view .nr .type = type
591636 unusedIndex .set (type, v + 1 )
637+ v++
592638 }
593639
594640 // Assign view to item
@@ -601,16 +647,8 @@ export default {
601647
602648 newlyUsedView = true
603649 } else {
604- // View already assigned to item
605- if (! view .nr .used ) {
606- view .nr .used = true
607- view .nr .index = i
608- newlyUsedView = true
609- if (unusedPool) {
610- const index = unusedPool .indexOf (view)
611- if (index !== - 1 ) unusedPool .splice (index, 1 )
612- }
613- }
650+ view .nr .used = true
651+ view .item = item
614652 }
615653
616654 // Always set item in case it's a new object with the same key
0 commit comments