由于接收到要求,项目由vue2
切换成vue3,
要前台列表使用无限滚动展示数据,我在查阅资料后发现原来官方推荐的方法是vue-infinite-scroll
这个现在已经不在维护的插件,虽然vue-infinite-scroll
确实挺好的,但就是不支持vue3,所以我使用的是原生的scroll标签实现的。相当于滚动加载下一页的数据。
上代码:
import { ref } from 'vue'
我自己做了一个简单的列表
<!-- 数据表格 -->
<el-table ref="businessTable" :data="sourceBusiness.list" style="width: 100%; max-height: 400px; overflow-y: auto" @scroll.enter="handleScroll">
<el-table-column prop="businessCode" label="业务属性代码" />
<el-table-column prop="businessName" label="分类名称" />
<el-table-column prop="describes" label="描述" />
<el-table-column label="操作">
<template #default="{ row }">
<el-button type="primary" @click="editBusiness(row)">编辑</el-button>
<el-button type="danger" @click="deleteBusiness(row)">删除</el-button>
</template>
</el-table-column>
</el-table>
data() {
return {
loading: false,
scrollTimer: null,
showLoadMoreButton: true, //是否显示加载更多数据
scrollPosition: 0, //记录滚动条位置
businessRequest: {
businessCode: '',
businessName: '',
pageNum: 1,
pageSize: 10
},
sourceBusiness: {
list: [],
total: 0
},
// 其他数据信息...
}
created() {
this.loadData()
},
methods:
//滚动事件
handleScroll() {
//这是使用setTimeOut函数来延迟执行,以便在滚动表格的时候节省资源和优化性能
//设置一个定时器scrollTimer,判断如果之前设置过定时器会清除之前的定时器,以免多次触发滚动事件
if (this.scrollTimer) {
clearTimeout(this.scrollTimer);
}
//设置定时器scrollTimer延迟200毫秒后执行回调函数
this.scrollTimer = setTimeout(() => {
const tableEl = this.$refs.businessTable.$el //表格的DOM元素
const scrollContainerHeight = tableEl.clientHeight //获取表格容器的高度,即当前可见区域的高度
const scrollContentHeight = tableEl.scrollHeight //获取表格内容的高度,即所有行的高度
const scrollTop = tableEl.scrollTop //获取表格容器滚动的距离,即当前可见区域顶部距离表格顶部的距离
//判断是否到达底部并且当前没有正在加载更多数据,如果是,则执行方法loadMoreData()
if (scrollTop + scrollContentHeight >= scrollContainerHeight && !this.loading) {
this.loadMoreData()
}
//将当前滚动位置保存到组件实例的scrollPosition中,以便下次执行定时器能够正确判断滚动事件
this.scrollPosition = scrollTop
},200)
},
//这个方法用于从后端加载数据并将其添加到当前显示数据的末尾
loadData() {
//表示正在加载数据
this.loading = true
//根据currentPage 和 pageSize 从后端加载数据
//发起请求,更新businessData
useBusinessApi(this.businessRequest).then(res => {
//将获取到的数据添加到当前已经显示的数据末尾,这里使用concat函数将两个数据合并
this.sourceBusiness.list = this.sourceBusiness.list.concat(res.data.list)
console.log(this.sourceBusiness.total)
//表示数据加载完成
this.loading = false
//使用$nextTick函数延迟执行一段回调函数
this.$nextTick(() => {
//回复滚动位置
const tableEl = this.$refs.businessTable.$el
//将表格的滚动位置设置为新的scrollPosition属性,以保持在加载数据时的滚动位置保持不变
tableEl.scrollTop = this.scrollPosition
})
})
.catch(error => {
//发生错误,控制台打印错误信息,并将 loading 属性设置为 false,表示数据加载完成
console.error(error)
this.loading = false
})
},
//滚动到底部时加载更多数据
loadMoreData() {
//将请求类的页码的pageNum加一,以获取下一页的数据
this.businessRequest.pageNum++
//加载数据到后端,以实现无限滚动效果
this.loadData()
},
后端是使用MyBatisPlus实现的普通的分页列表:
@PostMapping("/page")
@Operation(summary = "分页")
public Result<PageResult<SourceBusiness>> page(@RequestBody BusinessRequest businessRequest){
PageResult<SourceBusiness> result = businessService.page(businessRequest);
return Result.ok(result);
}
展示效果: