132 lines
		
	
	
		
			No EOL
		
	
	
		
			3.8 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			132 lines
		
	
	
		
			No EOL
		
	
	
		
			3.8 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
<div class="container"
 | 
						|
     on:scroll="onScroll(event)"
 | 
						|
     on:fullscreen="onFullscreenChange()"
 | 
						|
     ref:node>
 | 
						|
  <slot></slot>
 | 
						|
</div>
 | 
						|
<script>
 | 
						|
  import { virtualListStore } from '../_utils/virtualListStore'
 | 
						|
 | 
						|
  import throttle from 'lodash/throttle'
 | 
						|
  import { isFullscreen, attachFullscreenListener, detachFullscreenListener } from '../_utils/fullscreen'
 | 
						|
  import { mark, stop } from '../_utils/marks'
 | 
						|
 | 
						|
  const SCROLL_EVENT_DELAY = 300
 | 
						|
 | 
						|
  const cachedVirtualStores = {}
 | 
						|
 | 
						|
  if (process.browser && process.env.NODE_ENV !== 'production') {
 | 
						|
    window.cachedVirtualStores = cachedVirtualStores
 | 
						|
  }
 | 
						|
 | 
						|
  export default {
 | 
						|
    oncreate() {
 | 
						|
      mark('onCreate VirtualListContainer')
 | 
						|
      let node = this.refs.node
 | 
						|
      let storeKey = this.get('storeKey')
 | 
						|
      let cachedStore
 | 
						|
      if (storeKey && (cachedStore = cachedVirtualStores[storeKey])) {
 | 
						|
        this.store.set({
 | 
						|
          scrollTop: cachedStore.state.scrollTop,
 | 
						|
          scrollHeight: cachedStore.state.scrollHeight,
 | 
						|
          offsetHeight: cachedStore.state.offsetHeight
 | 
						|
        })
 | 
						|
        this.rehydrateScrollTop(cachedStore)
 | 
						|
        this.store.set(cachedStore.state)
 | 
						|
      } else {
 | 
						|
        this.store.set({
 | 
						|
          scrollTop: 0,
 | 
						|
          scrollHeight: node.scrollHeight,
 | 
						|
          offsetHeight: node.offsetHeight
 | 
						|
        })
 | 
						|
      }
 | 
						|
      stop('onCreate VirtualListContainer')
 | 
						|
    },
 | 
						|
    ondestroy() {
 | 
						|
      let storeKey = this.get('storeKey')
 | 
						|
      if (storeKey) {
 | 
						|
        let clonedState = this.store.cloneState()
 | 
						|
        if (process.env.NODE_ENV !== 'production') {
 | 
						|
          console.log('caching scroll top', clonedState.scrollTop)
 | 
						|
        }
 | 
						|
        cachedVirtualStores[storeKey] = {
 | 
						|
          state: clonedState
 | 
						|
        }
 | 
						|
      }
 | 
						|
    },
 | 
						|
    store: () => virtualListStore,
 | 
						|
    events: {
 | 
						|
      scroll(node, callback) {
 | 
						|
        const onScroll = throttle(event => {
 | 
						|
          mark('onScroll')
 | 
						|
          if (this.get('fullscreen')) {
 | 
						|
            return
 | 
						|
          }
 | 
						|
          callback(event)
 | 
						|
          stop('onScroll')
 | 
						|
        }, SCROLL_EVENT_DELAY, {
 | 
						|
          leading: true,
 | 
						|
          trailing: true
 | 
						|
        })
 | 
						|
        node.addEventListener('scroll', onScroll)
 | 
						|
 | 
						|
        return {
 | 
						|
          teardown() {
 | 
						|
            node.removeEventListener('scroll', onScroll)
 | 
						|
          }
 | 
						|
        }
 | 
						|
      },
 | 
						|
      fullscreen(node, callback) {
 | 
						|
        const onFullscreen = (() => {
 | 
						|
          callback()
 | 
						|
        })
 | 
						|
        attachFullscreenListener(onFullscreen)
 | 
						|
        return {
 | 
						|
          teardown() {
 | 
						|
            detachFullscreenListener(onFullscreen)
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    },
 | 
						|
    methods: {
 | 
						|
      onScroll(event) {
 | 
						|
        this.store.set({
 | 
						|
          scrollTop: event.target.scrollTop,
 | 
						|
          scrollHeight: event.target.scrollHeight
 | 
						|
        })
 | 
						|
      },
 | 
						|
      onFullscreenChange() {
 | 
						|
        mark('onFullscreenChange')
 | 
						|
        if (process.env.NODE_ENV !== 'production') {
 | 
						|
          console.log('is fullscreen? ', isFullscreen())
 | 
						|
        }
 | 
						|
        this.set({ fullscreen: isFullscreen() })
 | 
						|
        stop('onFullscreenChange')
 | 
						|
      },
 | 
						|
      rehydrateScrollTop(cachedStore) {
 | 
						|
        let cachedScrollTop = cachedStore.state.scrollTop || 0
 | 
						|
        if (cachedScrollTop === 0) {
 | 
						|
          if (process.env.NODE_ENV !== 'production') {
 | 
						|
            console.log('no need to force scroll top')
 | 
						|
          }
 | 
						|
          return
 | 
						|
        }
 | 
						|
        let initializedScrollTop = false
 | 
						|
        let node = this.refs.node
 | 
						|
        this.store.observe('allVisibleItemsHaveHeight', allVisibleItemsHaveHeight => {
 | 
						|
          if (!initializedScrollTop && allVisibleItemsHaveHeight && node) {
 | 
						|
            initializedScrollTop = true
 | 
						|
            requestAnimationFrame(() => {
 | 
						|
              mark('set scrollTop')
 | 
						|
              if (process.env.NODE_ENV !== 'production') {
 | 
						|
                console.log('forcing scroll top to ', cachedScrollTop)
 | 
						|
              }
 | 
						|
              node.scrollTop = cachedScrollTop
 | 
						|
              stop('set scrollTop')
 | 
						|
            })
 | 
						|
          }
 | 
						|
        })
 | 
						|
      }
 | 
						|
    }
 | 
						|
  };
 | 
						|
</script> |