场景:图片等list样式的内容,需要在不翻页的情况下使用加载更多。
方式:页面或div的滚动条滚动到底部或者特定位置后,自动加载更多内容
代码实现
<template>
<div ref="imageList" v-loading="loading" class="image-list">
<div slot="add" class="image-box">
<i class="el-icon-picture-outline" />
自定义上传...
</div>
<div v-for="image in images" :key="image.id" class="image-box">
<img :src="image.url" :alt="image.description" style="width: 100%;">
</div>
</div>
</template>
<script>
import { picture } from '@/APIS/common'
import { debounce, throttle } from 'lodash' // import debounce and throttle functions from Lodash library
export default {
props: {
pictype: {
type: String,
default: 'background'
}
},
data() {
return {
images: [], // array to store loaded images
loading: false, // flag to prevent loading duplicate images
page: 1, // current page number
perPage: 10, // number of images to load per page
imageListRef: null, // reference to the image list element
height: 0, // 图片列表总高度
total_num: 0 // 图片总数
}
},
mounted() {
this.imageListRef = this.$refs.imageList
this.height = this.imageListRef.scrollHeight
// this.imageListRef.clientHeight + this.imageListRef.scrollTop >= this.height
// add scroll event listener to the image list
this.imageListRef?.addEventListener('scroll', this.handleScrollDebounced)
// 加载图片
this.loadImages() // load initial set of images
},
beforeDestroy() {
this.imageListRef?.removeEventListener('scroll', this.handleScrollDebounced) // remove debounced scroll event listener
},
methods: {
async loadImages() {
if (this.loading) return // prevent loading duplicate images
// 判断总数 是否加载完全
if (this.total_num && this.images.length >= this.total_num) {
return
}
const size = this.height / 230 * 3
// 向上取整
const nums = Math.ceil(size)
this.loading = true // set loading flag
const response = await picture({
page_id: this.page,
num_per_page: this.page === 1 ? (nums + 1) : 6,
enable: 1,
type: this.pictype
})
if (response.code === 0) {
const newImages = await response.data.list
this.total_num = response.data.total_num
this.images = [...this.images, ...newImages] // append new images to existing array
this.loading = false // clear loading flag
this.page++ // increment page number for next load
// height 需要计算 images
this.height = Math.ceil(this.images.length / 3) * 230
} else {
this.$message.error(response.msg || '加载失败')
}
},
handleScrollThrottled: throttle(function() {
if (this.imageListRef.clientHeight + this.imageListRef.scrollTop >= this.height) {
this.loadImages() // trigger loading of new images when user has scrolled to the bottom
}
}, 300), // set a minimum interval of 300ms between function calls
handleScrollDebounced: debounce(function() {
this.handleScrollThrottled() // delay the execution of the throttled function by 300ms
}, 300)
}
}
</script>
<style lang="scss" scoped>
.image-list {
padding: 0 8px;
display: flex;
flex-wrap: wrap;
justify-content: start;
align-items: flex-start;
height: 100vh;
/* set the height of the component to the height of the viewport */
width: 440px;
overflow: auto;
&::-webkit-scrollbar {
width: 4px;
// height: 10px;
}
&::-webkit-scrollbar-thumb {
background-color: #B1B1B1;
border-radius: 4px;
height: 10px;
}
}
.image-box {
width: 129px;
height: 230px;
cursor: pointer;
margin: 5px;
img {
border-radius: 6px;
}
}
</style>
滚动条样式可自定义