主要思路通過自定義指令,在視圖初始化完成后,綁定scroll事件。當scrollTop + clientHeight >= scrollHeight時(此時滾定條到了底部)觸發loadMore事件,
<template>
<div class="index" v-scroll="loadMore">
<!-- 列表數據傳遞給子組件,loading表示是否正在加載數據,避免在請求時多次觸發 -->
<my-item :lists="lists" :loading="loading" />
</div>
</template>
<script>
import MyItem from '~/components/Item.vue'
export default {
name: 'Index',
created () {
// 初始化數據
this.$store.dispatch('GET_INDEX_LISTS')
this.lists = this.$store.state.lists
},
data() {
return {
lists: [],
page: 1,
loading: false
}
},
directives: {
scroll: {
bind: function (el, binding){
window.addEventListener('scroll', function() {
if(document.documentElement.scrollTop + document.documentElement.clientHeight >= document.documentElement.scrollHeight) {
let loadData = binding.value
loadData()
}
})
}
}
},
methods: {
async loadMore(){
if(!this.loading){
this.loading = true
// 請求下一頁數據
await this.$store.dispatch('GET_INDEX_LISTS', {
page: this.page++
})
// 重新填充數據
this.lists = this.lists.concat(this.$store.state.lists)
this.loading = false
}
}
},
components: {
MyItem
}
}
</script>
附上一個css loading動畫 , Loading.vue:
<template>
<div class="loading">
<div class="loader-inner line-scale">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>
</template>
<style>
.loading {
text-align: center;
}
.loader-inner {
display: inline-block;
}
@-webkit-keyframes line-scale {
0% {
-webkit-transform: scaley(1);
transform: scaley(1);
}
50% {
-webkit-transform: scaley(0.4);
transform: scaley(0.4);
}
100% {
-webkit-transform: scaley(1);
transform: scaley(1);
}
}
@keyframes line-scale {
0% {
-webkit-transform: scaley(1);
transform: scaley(1);
}
50% {
-webkit-transform: scaley(0.4);
transform: scaley(0.4);
}
100% {
-webkit-transform: scaley(1);
transform: scaley(1);
}
}
.line-scale > div:nth-child(1) {
-webkit-animation: line-scale 1s 0.1s infinite
cubic-bezier(0.2, 0.68, 0.18, 1.08);
animation: line-scale 1s 0.1s infinite cubic-bezier(0.2, 0.68, 0.18, 1.08);
}
.line-scale > div:nth-child(2) {
-webkit-animation: line-scale 1s 0.2s infinite
cubic-bezier(0.2, 0.68, 0.18, 1.08);
animation: line-scale 1s 0.2s infinite cubic-bezier(0.2, 0.68, 0.18, 1.08);
}
.line-scale > div:nth-child(3) {

-webkit-animation: line-scale 1s 0.3s infinite
cubic-bezier(0.2, 0.68, 0.18, 1.08);
animation: line-scale 1s 0.3s infinite cubic-bezier(0.2, 0.68, 0.18, 1.08);
}
.line-scale > div:nth-child(4) {
-webkit-animation: line-scale 1s 0.4s infinite
cubic-bezier(0.2, 0.68, 0.18, 1.08);
animation: line-scale 1s 0.4s infinite cubic-bezier(0.2, 0.68, 0.18, 1.08);
}
.line-scale > div:nth-child(5) {
-webkit-animation: line-scale 1s 0.5s infinite
cubic-bezier(0.2, 0.68, 0.18, 1.08);
animation: line-scale 1s 0.5s infinite cubic-bezier(0.2, 0.68, 0.18, 1.08);
}
.line-scale > div {
background-color: #fe0061;
width: 4px;
height: 30px;
border-radius: 2px;
margin: 2px;
-webkit-animation-fill-mode: both;
animation-fill-mode: both;
display: inline-block;
}
</style>
加載效果圖: