<div class="virtual-list-item {{shown ? 'shown' : ''}}" virtual-list-key="{{key}}" ref:node style="transform: translate3d(0, {{offset}}px, 0);" > <:Component {component} virtualProps="{{props}}" virtualIndex="{{index}}" virtualLength="{{$numItems}}"/> </div> <style> .virtual-list-item { position: absolute; top: 0; opacity: 0; pointer-events: none; /* will-change: transform; */ /* causes jank in mobile Firefox */ } .shown { opacity: 1; pointer-events: auto; } </style> <script> import { virtualListStore } from '../_utils/virtualListStore' import { AsyncLayout } from '../_utils/AsyncLayout' const asyncLayout = new AsyncLayout(node => node.getAttribute('virtual-list-key')) export default { oncreate() { let key = this.get('key') asyncLayout.observe(key, this.refs.node, (rect) => { // update all item heights in one microtask batch for better perf this.store.batchUpdate('itemHeights', key, rect.height) }) }, ondestroy() { let key = this.get('key') asyncLayout.unobserve(key, this.refs.node) }, store: () => virtualListStore, computed: { 'shown': ($itemHeights, key) => $itemHeights[key] > 0 } } </script>