more progress on infinite scroll
This commit is contained in:
parent
e670b57381
commit
eacf28317e
|
@ -1,16 +1,55 @@
|
|||
<:Window bind:innerHeight='innerHeight'/>
|
||||
<Nav page={{page}} />
|
||||
|
||||
<div class="container">
|
||||
<div class="container" on:scroll="onScroll(event)" ref:node>
|
||||
<main>
|
||||
<slot></slot>
|
||||
</main>
|
||||
</div>
|
||||
<script>
|
||||
import Nav from './Nav.html';
|
||||
import { virtualListStore } from '../_utils/virtualListStore'
|
||||
|
||||
import throttle from 'lodash/throttle'
|
||||
const THROTTLE_DELAY = 500
|
||||
|
||||
export default {
|
||||
oncreate() {
|
||||
this.observe('innerHeight', throttle(() => {
|
||||
// respond to window resize events
|
||||
this.store.set({
|
||||
offsetHeight: this.refs.node.offsetHeight
|
||||
})
|
||||
}, THROTTLE_DELAY))
|
||||
this.store.set({
|
||||
scrollTop: this.refs.node.scrollTop,
|
||||
scrollHeight: this.refs.node.scrollHeight,
|
||||
offsetHeight: this.refs.node.offsetHeight
|
||||
})
|
||||
},
|
||||
components: {
|
||||
Nav
|
||||
},
|
||||
store: () => virtualListStore,
|
||||
events: {
|
||||
scroll(node, callback) {
|
||||
const onScroll = throttle(callback, THROTTLE_DELAY)
|
||||
node.addEventListener('scroll', onScroll);
|
||||
|
||||
return {
|
||||
teardown() {
|
||||
node.removeEventListener('scroll', onScroll);
|
||||
}
|
||||
};
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onScroll(event) {
|
||||
this.store.set({
|
||||
scrollTop: event.target.scrollTop,
|
||||
scrollHeight: event.target.scrollHeight
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
let i = -1
|
||||
|
||||
const createData = () => fixture.slice(0, 5).map(_ => ({
|
||||
const createData = () => fixture.slice(0, 20).map(_ => ({
|
||||
key: `${++i}`,
|
||||
props: _
|
||||
}))
|
||||
|
@ -37,7 +37,10 @@
|
|||
splice: splice,
|
||||
addMoreItems() {
|
||||
console.log('addMoreItems')
|
||||
this.splice('statuses', this.get('statuses').length, 0, ...createData())
|
||||
let statuses = this.get('statuses')
|
||||
if (statuses) {
|
||||
this.splice('statuses', statuses.length, 0, ...createData())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
<:Window bind:innerHeight='innerHeight'/>
|
||||
<div class="virtual-list" style="height: {{$height}}px;">
|
||||
<div class="virtual-list">
|
||||
<!-- <div class="virtual-list-viewport" ref:viewport></div> -->
|
||||
{{#each $visibleItems as item @key}}
|
||||
<VirtualListItem :component
|
||||
|
@ -17,46 +16,24 @@
|
|||
<script>
|
||||
import VirtualListItem from './VirtualListItem'
|
||||
import { virtualListStore } from '../_utils/virtualListStore'
|
||||
import throttle from 'lodash/throttle'
|
||||
|
||||
const THROTTLE_TIME = 500
|
||||
const DISTANCE_FROM_BOTTOM_TO_FIRE = 400
|
||||
|
||||
export default {
|
||||
oncreate () {
|
||||
let container = document.body.querySelector('.container')
|
||||
this.observe('innerHeight', throttle(() => {
|
||||
// respond to window resize events
|
||||
this.store.set({
|
||||
offsetHeight: container.offsetHeight
|
||||
})
|
||||
}, THROTTLE_TIME))
|
||||
this.observe('items', (items) => {
|
||||
this.store.set({
|
||||
'items': items
|
||||
items: items
|
||||
})
|
||||
})
|
||||
this.store.observe('distanceFromBottom', distanceFromBottom => {
|
||||
console.log('distanceFromBottom', distanceFromBottom)
|
||||
if (distanceFromBottom >= 0 &&
|
||||
|
||||
this.observe('distanceFromBottom', (distanceFromBottom) => {
|
||||
//console.log('distanceFromBottom', distanceFromBottom)
|
||||
if (distanceFromBottom > 0 && // hack: the first it's reported, it's always 0
|
||||
distanceFromBottom <= DISTANCE_FROM_BOTTOM_TO_FIRE) {
|
||||
this.fire('scrollToBottom')
|
||||
}
|
||||
})
|
||||
container.addEventListener('scroll', throttle((e) => {
|
||||
this.store.set({
|
||||
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
|
||||
|
@ -64,6 +41,11 @@
|
|||
store: () => virtualListStore,
|
||||
components: {
|
||||
VirtualListItem
|
||||
},
|
||||
computed: {
|
||||
distanceFromBottom: ($scrollHeight, $scrollTop, $offsetHeight) => {
|
||||
return $scrollHeight - $scrollTop - $offsetHeight
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -35,7 +35,8 @@
|
|||
oncreate() {
|
||||
let key = this.get('key')
|
||||
onIntersectionCallbacks[key] = entry => {
|
||||
updateItemHeights[key] = entry.boundingClientRect.height
|
||||
let rect = entry.boundingClientRect
|
||||
updateItemHeights[key] = rect.height
|
||||
promise.then(() => {
|
||||
// update all item heights in one microtask batch for better perf
|
||||
let updatedKeys = Object.keys(updateItemHeights)
|
||||
|
|
|
@ -27,7 +27,7 @@ virtualListStore.compute('visibleItems',
|
|||
continue // below the area we want to render
|
||||
}
|
||||
} else {
|
||||
if (currentOffset > (scrollTop + offsetHeight + renderBuffer)) {
|
||||
if (currentOffset > (scrollTop + height + renderBuffer)) {
|
||||
break // above the area we want to render
|
||||
}
|
||||
}
|
||||
|
@ -35,24 +35,12 @@ virtualListStore.compute('visibleItems',
|
|||
offset: currentOffset,
|
||||
props: props,
|
||||
key: key,
|
||||
index: i,
|
||||
height: height
|
||||
index: i
|
||||
})
|
||||
}
|
||||
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…
Reference in New Issue