start on infinite scrolling

This commit is contained in:
Nolan Lawson 2018-01-16 21:43:31 -08:00
parent 5e3e56d454
commit e670b57381
3 changed files with 42 additions and 13 deletions

View file

@ -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())
}
}

View file

@ -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

View file

@ -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