start on infinite scrolling
This commit is contained in:
		
							parent
							
								
									5e3e56d454
								
							
						
					
					
						commit
						e670b57381
					
				
					 3 changed files with 42 additions and 13 deletions
				
			
		| 
						 | 
				
			
			@ -1,6 +1,7 @@
 | 
			
		|||
<div class="timeline">
 | 
			
		||||
  <VirtualList component="{{StatusListItem}}" items="{{statuses}}" />
 | 
			
		||||
  <button type="button" on:click="addMoreItems()">Add more items</button>
 | 
			
		||||
  <VirtualList component="{{StatusListItem}}"
 | 
			
		||||
               items="{{statuses}}"
 | 
			
		||||
               on:scrollToBottom="addMoreItems()" />
 | 
			
		||||
</div>
 | 
			
		||||
<style>
 | 
			
		||||
  .timeline {
 | 
			
		||||
| 
						 | 
				
			
			@ -17,7 +18,7 @@
 | 
			
		|||
 | 
			
		||||
  let i = -1
 | 
			
		||||
 | 
			
		||||
  const createData = () => fixture.slice(0, 20).map(_ => ({
 | 
			
		||||
  const createData = () => fixture.slice(0, 5).map(_ => ({
 | 
			
		||||
    key: `${++i}`,
 | 
			
		||||
    props: _
 | 
			
		||||
  }))
 | 
			
		||||
| 
						 | 
				
			
			@ -35,6 +36,7 @@
 | 
			
		|||
    methods: {
 | 
			
		||||
      splice: splice,
 | 
			
		||||
      addMoreItems() {
 | 
			
		||||
        console.log('addMoreItems')
 | 
			
		||||
        this.splice('statuses', this.get('statuses').length, 0, ...createData())
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,12 +20,15 @@
 | 
			
		|||
  import throttle from 'lodash/throttle'
 | 
			
		||||
 | 
			
		||||
  const THROTTLE_TIME = 500
 | 
			
		||||
  const DISTANCE_FROM_BOTTOM_TO_FIRE = 400
 | 
			
		||||
 | 
			
		||||
  export default {
 | 
			
		||||
    oncreate () {
 | 
			
		||||
      this.observe('innerHeight', throttle(innerHeight => {
 | 
			
		||||
      let container = document.body.querySelector('.container')
 | 
			
		||||
      this.observe('innerHeight', throttle(() => {
 | 
			
		||||
        // respond to window resize events
 | 
			
		||||
        this.store.set({
 | 
			
		||||
          innerHeight: innerHeight
 | 
			
		||||
          offsetHeight: container.offsetHeight
 | 
			
		||||
        })
 | 
			
		||||
      }, THROTTLE_TIME))
 | 
			
		||||
      this.observe('items', (items) => {
 | 
			
		||||
| 
						 | 
				
			
			@ -33,14 +36,27 @@
 | 
			
		|||
          'items': items
 | 
			
		||||
        })
 | 
			
		||||
      })
 | 
			
		||||
      document.body.querySelector('.container').addEventListener('scroll', throttle((e) => {
 | 
			
		||||
      this.store.observe('distanceFromBottom', distanceFromBottom => {
 | 
			
		||||
        console.log('distanceFromBottom', distanceFromBottom)
 | 
			
		||||
        if (distanceFromBottom >= 0 &&
 | 
			
		||||
            distanceFromBottom <= DISTANCE_FROM_BOTTOM_TO_FIRE) {
 | 
			
		||||
          this.fire('scrollToBottom')
 | 
			
		||||
        }
 | 
			
		||||
      })
 | 
			
		||||
      container.addEventListener('scroll', throttle((e) => {
 | 
			
		||||
        this.store.set({
 | 
			
		||||
          scrollTop: e.target.scrollTop
 | 
			
		||||
          scrollTop: e.target.scrollTop,
 | 
			
		||||
          scrollHeight: e.target.scrollHeight
 | 
			
		||||
        }, {
 | 
			
		||||
          leading: false,
 | 
			
		||||
          trailing: true
 | 
			
		||||
        })
 | 
			
		||||
      }, THROTTLE_TIME))
 | 
			
		||||
      this.store.set({
 | 
			
		||||
        scrollTop: container.scrollTop,
 | 
			
		||||
        scrollHeight: container.scrollHeight,
 | 
			
		||||
        offsetHeight: container.offsetHeight
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
    data: () => ({
 | 
			
		||||
      component: null
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,13 +6,12 @@ class VirtualListStore extends Store {
 | 
			
		|||
const virtualListStore = new VirtualListStore({
 | 
			
		||||
  items: [],
 | 
			
		||||
  itemHeights: {},
 | 
			
		||||
  scrollTop: 0
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
virtualListStore.compute('visibleItems',
 | 
			
		||||
    ['items', 'scrollTop', 'height', 'itemHeights', 'innerHeight'],
 | 
			
		||||
    (items, scrollTop, height, itemHeights, innerHeight) => {
 | 
			
		||||
  let renderBuffer = 1.5 * innerHeight
 | 
			
		||||
    ['items', 'scrollTop', 'itemHeights', 'offsetHeight'],
 | 
			
		||||
    (items, scrollTop, itemHeights, offsetHeight) => {
 | 
			
		||||
  let renderBuffer = 1.5 * offsetHeight
 | 
			
		||||
  let visibleItems = []
 | 
			
		||||
  let totalOffset = 0
 | 
			
		||||
  let len = items.length
 | 
			
		||||
| 
						 | 
				
			
			@ -28,7 +27,7 @@ virtualListStore.compute('visibleItems',
 | 
			
		|||
        continue // below the area we want to render
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      if (currentOffset > (scrollTop + innerHeight + renderBuffer)) {
 | 
			
		||||
      if (currentOffset > (scrollTop + offsetHeight + renderBuffer)) {
 | 
			
		||||
        break // above the area we want to render
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -36,12 +35,24 @@ virtualListStore.compute('visibleItems',
 | 
			
		|||
      offset: currentOffset,
 | 
			
		||||
      props: props,
 | 
			
		||||
      key: key,
 | 
			
		||||
      index: i
 | 
			
		||||
      index: i,
 | 
			
		||||
      height: height
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
  return visibleItems
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
virtualListStore.compute('distanceFromBottom',
 | 
			
		||||
    ['scrollHeight', 'scrollTop', 'offsetHeight'],
 | 
			
		||||
    (scrollHeight, scrollTop, offsetHeight) => {
 | 
			
		||||
  if (typeof scrollHeight === 'undefined' ||
 | 
			
		||||
      typeof scrollTop === 'undefined' ||
 | 
			
		||||
      typeof offsetHeight === 'undefined') {
 | 
			
		||||
    return -1
 | 
			
		||||
  }
 | 
			
		||||
  return scrollHeight - scrollTop - offsetHeight
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
virtualListStore.compute('height', ['items', 'itemHeights'], (items, itemHeights) => {
 | 
			
		||||
  let sum = 0
 | 
			
		||||
  let i = -1
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue