Skip to content

Commit 0d201a9

Browse files
committed
feat: allow throttling update calls
updateVisibleItems needs to get the value of scrollTop, which can be expensive because of layout calculations. Further, checking the view at 60fps can be overkill, especially if you have a well-sized buffer. Setting updateInterval to a small value such as 100ms drastically reduces CPU usage. Signed-off-by: Varun Patil <[email protected]>
1 parent 86fa98f commit 0d201a9

File tree

2 files changed

+21
-3
lines changed

2 files changed

+21
-3
lines changed

packages/vue-virtual-scroller/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ When the user scrolls inside RecycleScroller, the views are mostly just moved ar
187187
- `prerender` (default: `0`): render a fixed number of items for Server-Side Rendering (SSR).
188188
- `buffer` (default: `200`): amount of pixel to add to edges of the scrolling visible area to start rendering items further away.
189189
- `emitUpdate` (default: `false`): emit a `'update'` event each time the virtual scroller content is updated (can impact performance).
190+
- `updateInterval` (default: `0`): the interval in ms at which the view will be checked for updates after scrolling. When set to `0`, checked will happen during the next animation frame.
190191
- `listClass` (default: `''`): custom classes added to the item list wrapper.
191192
- `itemClass` (default: `''`): custom classes added to each item.
192193
- `listTag` (default: `'div'`): the element to render as the list's wrapper.

packages/vue-virtual-scroller/src/components/RecycleScroller.vue

+20-3
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,11 @@ export default {
148148
default: false,
149149
},
150150
151+
updateInterval: {
152+
type: Number,
153+
default: 0,
154+
},
155+
151156
skipHover: {
152157
type: Boolean,
153158
default: false,
@@ -333,17 +338,29 @@ export default {
333338
handleScroll (event) {
334339
if (!this.$_scrollDirty) {
335340
this.$_scrollDirty = true
336-
requestAnimationFrame(() => {
341+
if (this.$_updateTimeout) return
342+
343+
const requestUpdate = () => requestAnimationFrame(() => {
337344
this.$_scrollDirty = false
338345
const { continuous } = this.updateVisibleItems(false, true)
339346
340347
// It seems sometimes chrome doesn't fire scroll event :/
341348
// When non continous scrolling is ending, we force a refresh
342349
if (!continuous) {
343350
clearTimeout(this.$_refreshTimout)
344-
this.$_refreshTimout = setTimeout(this.handleScroll, 100)
351+
this.$_refreshTimout = setTimeout(this.handleScroll, this.updateInterval + 100)
345352
}
346353
})
354+
355+
requestUpdate()
356+
357+
// Schedule the next update with throttling
358+
if (this.updateInterval) {
359+
this.$_updateTimeout = setTimeout(() => {
360+
this.$_updateTimeout = 0
361+
if (this.$_scrollDirty) requestUpdate();
362+
}, this.updateInterval)
363+
}
347364
}
348365
},
349366
@@ -597,7 +614,7 @@ export default {
597614
// After the user has finished scrolling
598615
// Sort views so text selection is correct
599616
clearTimeout(this.$_sortTimer)
600-
this.$_sortTimer = setTimeout(this.sortViews, 300)
617+
this.$_sortTimer = setTimeout(this.sortViews, this.updateInterval + 300)
601618
602619
return {
603620
continuous,

0 commit comments

Comments
 (0)