Skip to content

Commit f502816

Browse files
author
Guillaume Chau
committed
buffer, poolSize now in px + work for both fixed & variable height modes
1 parent 716d20c commit f502816

File tree

1 file changed

+52
-36
lines changed

1 file changed

+52
-36
lines changed

src/components/VirtualScroller.vue

Lines changed: 52 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -81,16 +81,20 @@ export default {
8181
},
8282
buffer: {
8383
type: [Number, String],
84-
default: 2,
84+
default: 200,
8585
},
8686
poolSize: {
8787
type: [Number, String],
88-
default: 1,
88+
default: 2000,
8989
},
9090
prerender: {
9191
type: [Number, String],
9292
default: 0,
9393
},
94+
emitUpdate: {
95+
type: Boolean,
96+
default: false,
97+
},
9498
},
9599
96100
data: () => ({
@@ -123,16 +127,14 @@ export default {
123127
},
124128
125129
watch: {
126-
items: {
127-
handler () {
128-
this.updateVisibleItems(true)
129-
},
130-
deep: true,
130+
heights () {
131+
this.updateVisibleItems(true)
131132
},
132133
pageMode () {
133134
this.applyPageMode()
134135
this.updateVisibleItems(true)
135136
},
137+
itemHeight: 'setDirty',
136138
},
137139
138140
methods: {
@@ -179,6 +181,18 @@ export default {
179181
let startIndex = -1
180182
let endIndex = -1
181183
184+
const buffer = parseInt(this.buffer)
185+
const poolSize = parseInt(this.poolSize)
186+
const scrollTop = ~~((scroll.top - buffer) / poolSize) * poolSize
187+
const scrollBottom = ~~(Math.ceil((scroll.bottom + buffer) / poolSize)) * poolSize
188+
189+
if (!force && scrollTop === this._oldScrollTop && scrollBottom === this._oldScrollBottom) {
190+
return
191+
} else {
192+
this._oldScrollTop = scrollTop
193+
this._oldScrollBottom = scrollBottom
194+
}
195+
182196
// Variable height mode
183197
if (itemHeight === null) {
184198
const heights = this.heights
@@ -192,60 +206,55 @@ export default {
192206
do {
193207
oldI = i
194208
h = heights[i]
195-
if (h < scroll.top) {
209+
if (h < scrollTop) {
196210
a = i
197-
} else if (i < l && heights[i + 1] > scroll.top) {
211+
} else if (i < l && heights[i + 1] > scrollTop) {
198212
b = i
199213
}
200214
i = ~~((a + b) / 2)
201215
} while (i !== oldI)
216+
i < 0 && (i = 0)
202217
startIndex = i
203218
204219
// For containers style
205220
offsetTop = i > 0 ? heights[i - 1] : 0
206221
containerHeight = heights[l - 1]
207222
208223
// Searching for endIndex
209-
for (endIndex = i; endIndex < l && heights[endIndex] < scroll.bottom; endIndex++);
224+
for (endIndex = i; endIndex < l && heights[endIndex] < scrollBottom; endIndex++);
210225
if (endIndex === -1) {
211226
endIndex = items.length - 1
212227
} else {
213228
endIndex++
229+
// Bounds
230+
endIndex > l && (endIndex = l)
214231
}
215232
} else {
216233
// Fixed height mode
217-
const buffer = this.buffer
218-
const poolSize = this.poolSize
219-
startIndex = ~~((~~(scroll.top / itemHeight) - buffer) / poolSize) * poolSize
220-
endIndex = ~~((Math.ceil(scroll.bottom / itemHeight) + buffer) / poolSize) * poolSize
221-
}
234+
startIndex = ~~(scrollTop / itemHeight)
235+
endIndex = Math.ceil(scrollBottom / itemHeight)
222236
223-
if (startIndex < 0) {
224-
startIndex = 0
225-
}
226-
if (endIndex > l) {
227-
endIndex = l
228-
}
237+
// Bounds
238+
startIndex < 0 && (startIndex = 0)
239+
endIndex > l && (endIndex = l)
229240
230-
if (itemHeight !== null) {
231-
// Fixed height mode
232241
offsetTop = startIndex * itemHeight
233242
containerHeight = l * itemHeight
234243
}
235244
236-
if (force || startIndex !== this._startIndex || endIndex !== this._endIndex || l !== this._length) {
237-
this.keysEnabled = !(startIndex > this._endIndex || endIndex < this._startIndex)
238-
this._startIndex = startIndex
239-
this._endIndex = endIndex
240-
this._length = l
241-
this.visibleItems = items.slice(startIndex, endIndex)
242-
this.itemContainerStyle = {
243-
height: containerHeight + 'px',
244-
}
245-
this.itemsStyle = {
246-
marginTop: offsetTop + 'px',
247-
}
245+
this.keysEnabled = !(startIndex > this._endIndex || endIndex < this._startIndex)
246+
this._startIndex = startIndex
247+
this._endIndex = endIndex
248+
this._length = l
249+
this.visibleItems = items.slice(startIndex, endIndex)
250+
this.itemContainerStyle = {
251+
height: containerHeight + 'px',
252+
}
253+
this.itemsStyle = {
254+
marginTop: offsetTop + 'px',
248255
}
256+
257+
this.emitUpdate && this.$emit('update', startIndex, endIndex)
249258
}
250259
},
251260
@@ -259,6 +268,11 @@ export default {
259268
this.$el.scrollTop = scrollTop
260269
},
261270
271+
setDirty () {
272+
this._oldScrollTop = null
273+
this._oldScrollBottom = null
274+
},
275+
262276
applyPageMode () {
263277
if (this.pageMode) {
264278
this.addWindowScroll()
@@ -297,6 +311,8 @@ export default {
297311
created () {
298312
this._ready = false
299313
this._startIndex = 0
314+
this._oldScrollTop = null
315+
this._oldScrollBottom = null
300316
const prerender = parseInt(this.prerender)
301317
if (prerender > 0) {
302318
this.visibleItems = this.items.slice(0, prerender)
@@ -311,7 +327,7 @@ export default {
311327
mounted () {
312328
this.applyPageMode()
313329
this.$nextTick(() => {
314-
this.updateVisibleItems()
330+
this.updateVisibleItems(true)
315331
this._ready = true
316332
this.$nextTick(this.updateVisibleItems)
317333
})

0 commit comments

Comments
 (0)