做为一个初入前端的小菜鸟来说,突然接到需求要实现某一列表数据的滚动加载功能时,当时是很蒙蔽和彷徨的,好在有丰富的网络资源供我查阅,最终完成了该功能,现在就把该功能实现的代码分享给大家,望各位前端大佬不吝赐教。
思路是给Table设置一个监听滚动条的事件(onScrollEvent),方便时刻检查滚动条是否触底而调用后台加载数据,在滚动条触底后将新请求的数据追加到上一次的dataSource中,并重新渲染页面
<div onScrollCapture={onScrollEvent}>
<Table
columns={columns}
scroll={{ x: 1800, y: 480 }}
dataSource={dataSource}
rowKey='id'
loading={loading}
pagination={false}
sticky={true}
ref={(c) => { scrollRef.current = c }}
/>
</div>
// 滚动条处理逻辑
const onScrollEvent = async () => {
// 如果正在加载数据中,不重复进行操作
if (loading) return;
// 获取表格dom元素
const table = ReactDOM.findDOMNode(scrollRef.current);
const tableBody = (table as Element)?.querySelector('.ant-table-body');
// 容器可视区高度
const tableBodyHeight: number = tableBody?.clientHeight ? tableBody?.clientHeight : 0;
// 内容高度
const contentHeight = tableBody?.scrollHeight ? tableBody?.scrollHeight : 0;
// 距离顶部的高度
const toTopHeight = tableBody?.scrollTop ? tableBody?.scrollTop : 0;
// 如果后端数据总条数小于50 或者后端数据条数等于当前页面展示的总条数并且滚动条没有出现,不需要再去调用后端去请求数据
if ((dataSource.length === totalElements && toTopHeight === 0) || totalElements <= 50) {
return;
}
// 如果是横向滚动条变化,则不触发后续接口调用
if (tableScrollLeft !== tableBody?.scrollLeft) {
setTableScrollLeft(tableBody?.scrollLeft ? tableBody?.scrollLeft : 0);
return;
}
// 当距离底部只有1时,重新获取数据
if (contentHeight - (toTopHeight + tableBodyHeight) <= 1) {
// 如果当前页数据大于等于总页数,则代表没有数据了
if (currentPageIndex >= totalPages || dataSource.length === totalElements) {
message.success('已经是最后一页了', 2);
return;
}
setTableDataLoading(() => true);
// 加载数据
const res = await dispatch(getList({
pageIndex: currentPageIndex + 1,
pageSize: 50
}));
// 将新的数据进行拼接
setDataSource((preState: any) => {
return [...preState, ...res?.list]
});
// 让滚动条重回顶部
resetToTopHeight();
setCurrentPageIndex((preState: any) => preState + 1);
message.success(`加载了${res.list.length}条数据!`);
setTableDataLoading(() => false);
}
}
// 滚动条重回顶部的函数
const resetToTopHeight = () => {
//console.log('滚动条重回顶部');
const table = ReactDOM.findDOMNode(tableScrollRef.current);
// 获取表格dom元素
const tableBody: any = (table as Element)?.querySelector('.ant-table-body');
// 距离顶部的高度
if (tableBody?.scrollTop) {
tableBody.scrollTop = 0;
}
//const toTopHeight = tableBody?.scrollTop ? tableBody?.scrollTop : 0;
}