kinda sorta working
This commit is contained in:
		
							parent
							
								
									3f9ca66e38
								
							
						
					
					
						commit
						7682015cda
					
				
					 4 changed files with 47 additions and 21 deletions
				
			
		| 
						 | 
				
			
			@ -17,7 +17,7 @@
 | 
			
		|||
 | 
			
		||||
  let i = -1
 | 
			
		||||
 | 
			
		||||
  const createData = () => fixture.slice(0, 5).map(_ => ({
 | 
			
		||||
  const createData = () => fixture.slice(0, 20).map(_ => ({
 | 
			
		||||
    key: `${++i}`,
 | 
			
		||||
    props: _
 | 
			
		||||
  }))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,11 +1,12 @@
 | 
			
		|||
<:Window bind:scrollY='scrollY'/>
 | 
			
		||||
<:Window bind:scrollY='scrollY' bind:innerHeight='innerHeight' />
 | 
			
		||||
<div class="virtual-list" ref:node style="height: {{$height}}px;">
 | 
			
		||||
  <!-- <div class="virtual-list-viewport" ref:viewport></div> -->
 | 
			
		||||
  {{#each $virtualItems as virtualItem, virtualIndex}}
 | 
			
		||||
  {{#each $visibleItems as item, virtualIndex}}
 | 
			
		||||
    <VirtualListItem :component
 | 
			
		||||
                     props="{{virtualItem.props}}"
 | 
			
		||||
                     index="{{virtualItem.index}}"
 | 
			
		||||
                     key="{{virtualItem.key}}"
 | 
			
		||||
                     offset="{{item.offset}}"
 | 
			
		||||
                     props="{{item.item.props}}"
 | 
			
		||||
                     index="{{item.item.index}}"
 | 
			
		||||
                     key="{{item.item.key}}"
 | 
			
		||||
    />
 | 
			
		||||
  {{/each}}
 | 
			
		||||
</div>
 | 
			
		||||
| 
						 | 
				
			
			@ -20,12 +21,25 @@
 | 
			
		|||
 | 
			
		||||
  export default {
 | 
			
		||||
    oncreate() {
 | 
			
		||||
      console.log('scrollHeight', this.refs.node.scrollHeight)
 | 
			
		||||
      this.store.set({
 | 
			
		||||
        scrollHeight: this.refs.node.scrollHeight,
 | 
			
		||||
      })
 | 
			
		||||
      this.observe('innerHeight', innerHeight => {
 | 
			
		||||
        this.store.set({
 | 
			
		||||
          innerHeight: innerHeight
 | 
			
		||||
        })
 | 
			
		||||
      })
 | 
			
		||||
      this.observe('items', (items) => {
 | 
			
		||||
        this.store.set({'items': items})
 | 
			
		||||
        this.store.set({
 | 
			
		||||
          'items': items
 | 
			
		||||
        })
 | 
			
		||||
      })
 | 
			
		||||
      this.observe('scrollY', (scrollY) => {
 | 
			
		||||
        console.log('scrollY', scrollY)
 | 
			
		||||
        this.store.set({scrollTop: scrollY})
 | 
			
		||||
        this.store.set({
 | 
			
		||||
          scrollTop: scrollY
 | 
			
		||||
        })
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
    data: () => ({
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
<div class="virtual-list-item"
 | 
			
		||||
     ref:node
 | 
			
		||||
     style="transform: translate3d(0, {{itemOffset}}px, 0);"
 | 
			
		||||
     style="transform: translate3d(0, {{offset}}px, 0);"
 | 
			
		||||
     data-virtual-index="{{index}}"
 | 
			
		||||
     data-virtual-key="{{key}}"
 | 
			
		||||
>
 | 
			
		||||
| 
						 | 
				
			
			@ -22,11 +22,6 @@
 | 
			
		|||
      itemHeights[this.get('key')] = this.refs.node.offsetHeight
 | 
			
		||||
      this.store.set({itemHeights: itemHeights})
 | 
			
		||||
    },
 | 
			
		||||
    computed: {
 | 
			
		||||
      itemOffset: ($itemOffsets, key) => {
 | 
			
		||||
        return $itemOffsets[key] || 0
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    store: () => virtualListStore
 | 
			
		||||
  }
 | 
			
		||||
</script>
 | 
			
		||||
| 
						 | 
				
			
			@ -1,6 +1,8 @@
 | 
			
		|||
import { Store } from 'svelte/store.js'
 | 
			
		||||
import { splice } from 'svelte-extras'
 | 
			
		||||
 | 
			
		||||
const RENDER_BUFFER = 1000
 | 
			
		||||
 | 
			
		||||
class VirtualListStore extends Store {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -9,7 +11,8 @@ VirtualListStore.prototype.splice = splice
 | 
			
		|||
const virtualListStore = new VirtualListStore({
 | 
			
		||||
  items: [],
 | 
			
		||||
  itemHeights: {},
 | 
			
		||||
  scrollTop: 0
 | 
			
		||||
  scrollTop: 0,
 | 
			
		||||
  scrollHeight: 0
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
virtualListStore.compute('virtualItems', ['items'], (items) => {
 | 
			
		||||
| 
						 | 
				
			
			@ -20,15 +23,29 @@ virtualListStore.compute('virtualItems', ['items'], (items) => {
 | 
			
		|||
  }))
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
virtualListStore.compute('itemOffsets', ['virtualItems', 'itemHeights'], (virtualItems, itemHeights) => {
 | 
			
		||||
  let itemOffsets = {}
 | 
			
		||||
  let totalHeight = 0
 | 
			
		||||
virtualListStore.compute('visibleItems',
 | 
			
		||||
    ['virtualItems', 'scrollTop', 'height', 'itemHeights', 'innerHeight'],
 | 
			
		||||
    (virtualItems, scrollTop, height, itemHeights, innerHeight) => {
 | 
			
		||||
  let visibleItems = []
 | 
			
		||||
  let currentOffset = 0
 | 
			
		||||
  virtualItems.forEach(item => {
 | 
			
		||||
    let height = itemHeights[item.key] || 0
 | 
			
		||||
    itemOffsets[item.key] = totalHeight
 | 
			
		||||
    totalHeight += height
 | 
			
		||||
    console.log(item.key, 'scrollTop', scrollTop, 'currentOffset', currentOffset, 'innerHeight', innerHeight)
 | 
			
		||||
    if (
 | 
			
		||||
      ((currentOffset < scrollTop)  && (scrollTop - RENDER_BUFFER < currentOffset)) ||
 | 
			
		||||
      ((currentOffset >= scrollTop) && (currentOffset < (scrollTop + innerHeight + RENDER_BUFFER)))
 | 
			
		||||
    ) {
 | 
			
		||||
      console.log('    rendering', item)
 | 
			
		||||
      visibleItems.push({
 | 
			
		||||
        item: item,
 | 
			
		||||
        offset: currentOffset
 | 
			
		||||
      })
 | 
			
		||||
    } else {
 | 
			
		||||
      console.log('not rendering', item)
 | 
			
		||||
    }
 | 
			
		||||
    currentOffset += height
 | 
			
		||||
  })
 | 
			
		||||
  return itemOffsets
 | 
			
		||||
  return visibleItems
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
virtualListStore.compute('height', ['virtualItems', 'itemHeights'], (virtualItems, itemHeights) => {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue