make virtual list more effecient using "reselect"
This commit is contained in:
parent
562a58f030
commit
73861c4749
|
@ -1,5 +1,6 @@
|
||||||
import { mark, stop } from '../../_utils/marks'
|
import { mark, stop } from '../../_utils/marks'
|
||||||
import { RealmStore } from '../../_utils/RealmStore'
|
import { RealmStore } from '../../_utils/RealmStore'
|
||||||
|
import { reselect } from '../../_utils/reselect'
|
||||||
|
|
||||||
const VIEWPORT_RENDER_FACTOR = 3
|
const VIEWPORT_RENDER_FACTOR = 3
|
||||||
|
|
||||||
|
@ -21,9 +22,10 @@ virtualListStore.computeForRealm('scrollHeight', 0)
|
||||||
virtualListStore.computeForRealm('offsetHeight', 0)
|
virtualListStore.computeForRealm('offsetHeight', 0)
|
||||||
virtualListStore.computeForRealm('itemHeights', {})
|
virtualListStore.computeForRealm('itemHeights', {})
|
||||||
|
|
||||||
virtualListStore.compute('visibleItems',
|
virtualListStore.compute('rawVisibleItems',
|
||||||
['items', 'scrollTop', 'itemHeights', 'offsetHeight', 'showHeader', 'headerHeight'],
|
['items', 'scrollTop', 'itemHeights', 'offsetHeight', 'showHeader', 'headerHeight'],
|
||||||
(items, scrollTop, itemHeights, offsetHeight, showHeader, headerHeight) => {
|
(items, scrollTop, itemHeights, offsetHeight, showHeader, headerHeight) => {
|
||||||
|
window.rawVisibleItemsComputed = (window.rawVisibleItemsComputed || 0) + 1
|
||||||
mark('compute visibleItems')
|
mark('compute visibleItems')
|
||||||
if (!items) {
|
if (!items) {
|
||||||
return null
|
return null
|
||||||
|
@ -58,6 +60,8 @@ virtualListStore.compute('visibleItems',
|
||||||
return visibleItems
|
return visibleItems
|
||||||
})
|
})
|
||||||
|
|
||||||
|
reselect(virtualListStore, 'visibleItems', 'rawVisibleItems')
|
||||||
|
|
||||||
virtualListStore.compute('heightWithoutFooter',
|
virtualListStore.compute('heightWithoutFooter',
|
||||||
['items', 'itemHeights', 'showHeader', 'headerHeight'],
|
['items', 'itemHeights', 'showHeader', 'headerHeight'],
|
||||||
(items, itemHeights, showHeader, headerHeight) => {
|
(items, itemHeights, showHeader, headerHeight) => {
|
||||||
|
@ -97,6 +101,14 @@ virtualListStore.compute('allVisibleItemsHaveHeight',
|
||||||
|
|
||||||
if (process.browser && process.env.NODE_ENV !== 'production') {
|
if (process.browser && process.env.NODE_ENV !== 'production') {
|
||||||
window.virtualListStore = virtualListStore
|
window.virtualListStore = virtualListStore
|
||||||
|
|
||||||
|
virtualListStore.observe('visibleItems', () => {
|
||||||
|
window.visibleItemsChangedCount = (window.visibleItemsChangedCount || 0) + 1
|
||||||
|
})
|
||||||
|
|
||||||
|
virtualListStore.observe('rawVisibleItems', () => {
|
||||||
|
window.rawVisibleItemsChangedCount = (window.rawVisibleItemsChangedCount || 0) + 1
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
// Avoid re-renders by caching the most recent value of an array
|
||||||
|
// or an object, using an approach similar to https://github.com/reactjs/reselect.
|
||||||
|
// This avoids the issue where Svelte may keep re-rendering because it doesn't
|
||||||
|
// know if an object/array has changed or not.
|
||||||
|
|
||||||
|
import isEqual from 'lodash/isEqual'
|
||||||
|
|
||||||
|
if (process.browser && process.env.NODE_ENV !== 'production') {
|
||||||
|
window.reselectStats = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function reselect (store, outputKey, inputKey) {
|
||||||
|
let prevValue
|
||||||
|
let nextValue
|
||||||
|
let count = 0
|
||||||
|
let countKey = `${outputKey}_reselectCount`
|
||||||
|
|
||||||
|
store.compute(countKey, [inputKey], input => {
|
||||||
|
if (process.browser && process.env.NODE_ENV !== 'production') {
|
||||||
|
window.reselectStats[inputKey] = window.reselectStats[inputKey] || {numInputChanges: 0, numOutputChanges: 0}
|
||||||
|
window.reselectStats[inputKey].numInputChanges++
|
||||||
|
}
|
||||||
|
if (!isEqual(prevValue, input)) {
|
||||||
|
nextValue = input
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
return count
|
||||||
|
})
|
||||||
|
|
||||||
|
store.compute(outputKey, [countKey], () => {
|
||||||
|
if (process.browser && process.env.NODE_ENV !== 'production') {
|
||||||
|
window.reselectStats[inputKey].numOutputChanges++
|
||||||
|
}
|
||||||
|
prevValue = nextValue
|
||||||
|
nextValue = null
|
||||||
|
return prevValue
|
||||||
|
})
|
||||||
|
}
|
Loading…
Reference in New Issue