implement batchUpdate()

This commit is contained in:
Nolan Lawson 2018-01-17 19:41:37 -08:00
parent 0f69df592a
commit bfe0f1255a
2 changed files with 31 additions and 26 deletions

View File

@ -21,44 +21,20 @@
<script> <script>
import { virtualListStore } from '../_utils/virtualListStore' import { virtualListStore } from '../_utils/virtualListStore'
import { AsyncLayout } from '../_utils/AsyncLayout' import { AsyncLayout } from '../_utils/AsyncLayout'
import { mark, stop } from '../_utils/marks'
let updateItemHeights = {}
let promise = Promise.resolve()
const asyncLayout = new AsyncLayout(node => node.getAttribute('virtual-list-key')) const asyncLayout = new AsyncLayout(node => node.getAttribute('virtual-list-key'))
export default { export default {
oncreate() { oncreate() {
let key = this.get('key') let key = this.get('key')
// TODO: implement batchUpdate
// TODO: fix resize on media
asyncLayout.observe(key, this.refs.node, (rect) => { asyncLayout.observe(key, this.refs.node, (rect) => {
updateItemHeights[key] = rect.height
promise = promise.then(() => {
// update all item heights in one microtask batch for better perf // update all item heights in one microtask batch for better perf
let updatedKeys = Object.keys(updateItemHeights) this.store.batchUpdate('itemHeights', key, rect.height)
if (!updatedKeys.length) {
return
}
mark('batch update VirtualListItem')
// batch all updates to itemHeights for better perf
let itemHeights = this.store.get('itemHeights')
for (key of updatedKeys) {
itemHeights[key] = updateItemHeights[key]
}
this.store.set({
itemHeights: itemHeights
})
updateItemHeights = {}
stop('batch update VirtualListItem')
})
}) })
}, },
ondestroy() { ondestroy() {
let key = this.get('key') let key = this.get('key')
asyncLayout.unobserve(key, this.refs.node) asyncLayout.unobserve(key, this.refs.node)
delete updateItemHeights[key]
}, },
store: () => virtualListStore, store: () => virtualListStore,
computed: { computed: {

View File

@ -2,6 +2,35 @@ import { Store } from 'svelte/store.js'
import { mark, stop } from '../_utils/marks' import { mark, stop } from '../_utils/marks'
class VirtualListStore extends Store { class VirtualListStore extends Store {
constructor(obj) {
super(obj)
this._batches = {}
}
batchUpdate(key, subKey, value) {
let batch = this._batches[key]
if (!batch) {
batch = this._batches[key] = {}
}
batch[subKey] = value
requestAnimationFrame(() => {
let updatedKeys = Object.keys(batch)
if (!updatedKeys.length) {
return
}
mark('batchUpdate()')
let obj = this.get(key)
for (let otherKey of updatedKeys) {
obj[otherKey] = batch[otherKey]
}
delete this._batches[key]
let toSet = {}
toSet[key] = obj
this.set(toSet)
stop('batchUpdate()')
})
}
} }
const virtualListStore = new VirtualListStore({ const virtualListStore = new VirtualListStore({