forked from cybrespace/pinafore
implement AsyncLayout
This commit is contained in:
parent
b58033203d
commit
0f69df592a
|
@ -20,28 +20,20 @@
|
|||
</style>
|
||||
<script>
|
||||
import { virtualListStore } from '../_utils/virtualListStore'
|
||||
import { AsyncLayout } from '../_utils/AsyncLayout'
|
||||
import { mark, stop } from '../_utils/marks'
|
||||
|
||||
let updateItemHeights = {}
|
||||
let promise = Promise.resolve()
|
||||
let onIntersectionCallbacks = {}
|
||||
|
||||
let intersectionObserver = new IntersectionObserver(entries => {
|
||||
entries.forEach(entry => {
|
||||
let key = entry.target.getAttribute('virtual-list-key')
|
||||
onIntersectionCallbacks[key](entry)
|
||||
})
|
||||
})
|
||||
const asyncLayout = new AsyncLayout(node => node.getAttribute('virtual-list-key'))
|
||||
|
||||
export default {
|
||||
oncreate() {
|
||||
let key = this.get('key')
|
||||
// TODO: implement AsyncLayout
|
||||
// TODO: implement batchUpdate
|
||||
// TODO: fix resize on media
|
||||
onIntersectionCallbacks[key] = entry => {
|
||||
console.log('onIntersection', key, entry.boundingClientRect.height)
|
||||
let rect = entry.boundingClientRect
|
||||
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
|
||||
|
@ -61,22 +53,13 @@
|
|||
updateItemHeights = {}
|
||||
stop('batch update VirtualListItem')
|
||||
})
|
||||
this.set({ unobserved: true })
|
||||
intersectionObserver.unobserve(this.refs.node)
|
||||
}
|
||||
intersectionObserver.observe(this.refs.node)
|
||||
})
|
||||
},
|
||||
ondestroy() {
|
||||
let key = this.get('key')
|
||||
if (!this.get('unobserved')) {
|
||||
intersectionObserver.unobserve(this.refs.node)
|
||||
}
|
||||
delete onIntersectionCallbacks[key]
|
||||
asyncLayout.unobserve(key, this.refs.node)
|
||||
delete updateItemHeights[key]
|
||||
},
|
||||
data: () => ({
|
||||
unobserved: false
|
||||
}),
|
||||
store: () => virtualListStore,
|
||||
computed: {
|
||||
'shown': ($itemHeights, key) => $itemHeights[key] > 0
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
// Use intersection observer to calculate rects asynchronously
|
||||
class AsyncLayout {
|
||||
constructor(generateKeyFromNode) {
|
||||
this._onIntersectionCallbacks = {}
|
||||
|
||||
this._intersectionObserver = new IntersectionObserver(entries => {
|
||||
entries.forEach(entry => {
|
||||
let key = generateKeyFromNode(entry.target)
|
||||
this._onIntersectionCallbacks[key](entry)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
observe(key, node, callback) {
|
||||
this._onIntersectionCallbacks[key] = (entry) => {
|
||||
callback(entry.boundingClientRect)
|
||||
this.unobserve(key, node)
|
||||
}
|
||||
this._intersectionObserver.observe(node)
|
||||
}
|
||||
|
||||
unobserve(key, node) {
|
||||
if (key in this._onIntersectionCallbacks) {
|
||||
return
|
||||
}
|
||||
this._intersectionObserver.unobserve(node)
|
||||
delete this._onIntersectionCallbacks[key]
|
||||
}
|
||||
}
|
||||
|
||||
export { AsyncLayout }
|
Loading…
Reference in New Issue