やりたいこと
- データは10件ずつ取得したい
- 上にスクロールして、表示されているデータより前の10件のデータを取得する
- なくなるまで無限スクロールしたい
結論
vue-infinite-loading
というのがよさそうだったので、これで実装しました。
vue-infinite-loadingを導入
yarn add vue-infinite-loading
実装する
<template>
<div>
<v-list
v-if="Object.keys(newsList).length > 0"
>
<v-list-item
v-for="(data) in newsList"
:key="data.id"
>
<v-list-item-content>
{{ data.title }}
</v-list-item-content>
</v-list-item>
</v-list>
<infinite-loading
ref="infiniteLoading"
spinner="bubbles"
direction="top"
@infinite="infiniteHandler"
>
<div slot="error">エラーが発生しました。</div>
<div slot="no-more"></div>
<div slot="no-results"></div>
</infinite-loading>
</div>
</template>
import InfiniteLoading from 'vue-infinite-loading'
export default {
components: {
InfiniteLoading
},
computed: {
...mapGetters('modules/news', [
'newsList',
'firstNewsId'
])
},
infiniteHandler ($state) {
if (process.client) {
setTimeout(() => {
if (Object.keys(this.newsList).length > 0) {
if (Number(this.firstNewsId) !== Number(Object.keys(this.newsList).slice()[0])) {
this.$emit('addNews', Object.keys(this.newsList).slice()[0])
$state.loaded()
} else {
$state.complete()
}
}
}, 200)
}
}
}
そのユーザーに表示されるべきデータを取得し、規定のIDになるまで取得するようにしています。
this.$emit('addNews', Object.keys(this.newsList).slice()[0])
で、addNews
に現在取得済みの一番小さいIDを渡して、APIで前の10件を取得する処理を書いています。
$state.loaded()
で、取得継続して、
$state.complete()
で終了。
上にスクロールしたいときは
direction="top"
とすると良いらしい。
エラー発生時やこれ以上表示するものがない時のメッセージは↓で設定してやる。
<div slot="error">エラーが発生しました。</div>
<div slot="no-more"></div>
<div slot="no-results"></div>
データ取得中のローディングは↓で設定可能。
spinner="bubbles"
process.client
は、documentがundefinedだとエラーが出たので入れています。