<div class="virtual-list-item list-item {shown ? 'shown' : ''}" aria-hidden={!shown} virtual-list-key={key} ref:node style="transform: translateY({offset}px);" > <svelte:component this={component} virtualProps={props} virtualIndex={index} virtualLength={$length} on:recalculateHeight="doRecalculateHeight()"/> </div> <style> .virtual-list-item { position: absolute; top: 0; opacity: 0; pointer-events: none; transition: opacity 0.333s linear; } .virtual-list-item.shown { opacity: 1; pointer-events: auto; } </style> <script> import { virtualListStore } from './virtualListStore' import { registerResizeListener, unregisterResizeListener } from '../../_utils/resize' import { mark, stop } from '../../_utils/marks' export default { oncreate () { let { key } = this.get() let node = this.refs.node requestAnimationFrame(() => { if (!node || !key) { return } mark('VirtualListItem gBCR') let rect = node.getBoundingClientRect() stop('VirtualListItem gBCR') // update all item heights in one batch for better perf this.store.batchUpdateForRealm('itemHeights', key, rect.height) }) this.doRecalculateHeight = this.doRecalculateHeight.bind(this) registerResizeListener(this.doRecalculateHeight) }, ondestroy () { unregisterResizeListener(this.doRecalculateHeight) }, store: () => virtualListStore, computed: { 'shown': ({ $itemHeights, key }) => $itemHeights[key] > 0 }, methods: { doRecalculateHeight () { // Recalculate immediately because this is done on-demand, e.g. // when clicking the "More" button on a spoiler. let rect = this.refs.node.getBoundingClientRect() let { key } = this.get() let { itemHeights } = this.store.get() itemHeights[key] = rect.height this.store.setForRealm({itemHeights}) } } } </script>