65 lines
		
	
	
		
			No EOL
		
	
	
		
			1.8 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			65 lines
		
	
	
		
			No EOL
		
	
	
		
			1.8 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
<!-- TODO: setting height is hacky, just make this element the scroller -->
 | 
						|
<div class="virtual-list" style="height: {{$height}}px;">
 | 
						|
  {{#each $visibleItems as item @key}}
 | 
						|
  <VirtualListItem :component
 | 
						|
                   offset="{{item.offset}}"
 | 
						|
                   props="{{item.props}}"
 | 
						|
                   key="{{item.key}}"
 | 
						|
                   index="{{item.index}}"
 | 
						|
  />
 | 
						|
  {{/each}}
 | 
						|
</div>
 | 
						|
<style>
 | 
						|
  .virtual-list {
 | 
						|
    position: relative;
 | 
						|
  }
 | 
						|
</style>
 | 
						|
<script>
 | 
						|
  import VirtualListItem from './VirtualListItem'
 | 
						|
  import { virtualListStore } from '../_utils/virtualListStore'
 | 
						|
  import throttle from 'lodash/throttle'
 | 
						|
  import { mark, stop } from '../_utils/marks'
 | 
						|
 | 
						|
  const DISTANCE_FROM_BOTTOM_TO_FIRE = 400
 | 
						|
  const SCROLL_TO_BOTTOM_DELAY = 1000
 | 
						|
 | 
						|
  export default {
 | 
						|
    oncreate () {
 | 
						|
      this.observe('items', (items) => {
 | 
						|
        mark('set items')
 | 
						|
        this.store.set({
 | 
						|
          items: items
 | 
						|
        })
 | 
						|
        stop('set items')
 | 
						|
        this.fireScrollToBottom = throttle(() => {
 | 
						|
          this.fire('scrollToBottom')
 | 
						|
        }, SCROLL_TO_BOTTOM_DELAY)
 | 
						|
      })
 | 
						|
 | 
						|
      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.fireScrollToBottom()
 | 
						|
        }
 | 
						|
      })
 | 
						|
    },
 | 
						|
    data: () => ({
 | 
						|
      component: null
 | 
						|
    }),
 | 
						|
    store: () => virtualListStore,
 | 
						|
    components: {
 | 
						|
      VirtualListItem
 | 
						|
    },
 | 
						|
    computed: {
 | 
						|
      distanceFromBottom: ($scrollHeight, $scrollTop, $offsetHeight) => {
 | 
						|
        return $scrollHeight - $scrollTop - $offsetHeight
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
</script> |