<div class="virtual-list" style="height: {{$height}}px;"> {{#each $visibleItems as item @key}} <VirtualListItem :component offset="{{item.offset}}" props="{{item.props}}" key="{{item.key}}" /> {{/each}} </div> <style> .virtual-list { position: relative; } </style> <script> import VirtualListItem from './VirtualListItem' import { virtualListStore } from '../_utils/virtualListStore' const DISTANCE_FROM_BOTTOM_TO_FIRE = 400 export default { oncreate () { this.observe('items', (items) => { this.store.set({ items: items }) }) let observedOnce = false this.observe('distanceFromBottom', (distanceFromBottom) => { if (!observedOnce) { observedOnce = true // TODO: the first time is always 0... need better way to handle this return } if (distanceFromBottom >= 0 && distanceFromBottom <= DISTANCE_FROM_BOTTOM_TO_FIRE) { this.fire('scrollToBottom') } }) }, data: () => ({ component: null }), store: () => virtualListStore, components: { VirtualListItem }, computed: { distanceFromBottom: ($scrollHeight, $scrollTop, $offsetHeight) => { return $scrollHeight - $scrollTop - $offsetHeight } } } </script>