PrimeReact DataTable虚拟滚动懒加载Skeleton预览显示异常求助
PrimeReact DataTable 虚拟滚动懒加载异常问题及解决方案
问题说明
PrimeReact DataTable的虚拟滚动懒加载功能存在异常:官方示例中向下滚动加载时,现有条目会被全部隐藏,仅显示第一组Skeleton加载骨架,不符合「保留当前条目并新增加载模板」的预期。对比之下,PrimeReact原生VirtualScroller组件的懒加载功能是正常的。
目前尝试使用virtualScrollerOptions.appendOnly属性可以避免加载时清空现有内容,但DataTable没有提供类似原生VirtualScroller的onFetchRows事件来精准控制加载状态UI。我曾考虑在lazyLoad触发时,通过isLoading标记手动向数据列表添加带加载模板的记录,加载完成后切换标记并替换为真实数据,但不确定这个思路是否正确。
问题分析
DataTable的虚拟滚动懒加载逻辑对原生VirtualScroller做了封装,当前实现触发lazyLoad时会直接重置数据集并替换为加载骨架,而非在现有数据基础上追加加载状态的内容。appendOnly模式虽然能保留已有数据,但缺少配套事件来触发加载状态的UI更新,导致无法直接实现「保留旧数据+显示底部加载骨架」的效果。
可行解决方案
手动维护加载状态占位记录的思路是可行的,具体实现步骤如下:
- 状态管理:维护
data数据集、isLoading加载状态、totalRecords总记录数三个核心状态 - 触发加载时添加占位:调用
lazyLoad时,将isLoading设为true,同时向data末尾添加一条标记为加载状态的占位记录 - 加载完成后替换占位:异步获取数据完成后,将
isLoading设为false,移除占位记录并将新数据追加到data中 - 列模板区分渲染:在列的
body模板中,根据记录的加载状态渲染Skeleton或正常内容
代码示例
import { useState } from 'react'; import { DataTable, LazyLoadEvent, Skeleton } from 'primereact'; // 模拟数据获取函数 const fetchNewData = (first: number, rows: number) => { return Array.from({ length: rows }, (_, i) => ({ id: first + i + 1, name: `Item ${first + i + 1}` })); }; const LazyVirtualScrollTable = () => { const [data, setData] = useState<any[]>([]); const [isLoading, setIsLoading] = useState(false); const [totalRecords, setTotalRecords] = useState(100); const lazyLoad = (event: LazyLoadEvent) => { setIsLoading(true); // 添加加载占位记录 setData(prev => [...prev, { isLoading: true }]); // 模拟异步请求 setTimeout(() => { const newData = fetchNewData(event.first!, event.rows!); setIsLoading(false); // 移除占位记录并追加新数据 setData(prev => prev.filter(item => !item.isLoading).concat(newData)); }, 1000); }; const columns = [ { field: 'id', header: 'ID', body: (rowData: any) => rowData.isLoading ? <Skeleton /> : rowData.id }, { field: 'name', header: 'Name', body: (rowData: any) => rowData.isLoading ? <Skeleton /> : rowData.name } ]; return ( <DataTable value={data} lazy onLazyLoad={lazyLoad} totalRecords={totalRecords} scrollable scrollHeight="500px" virtualScrollerOptions={{ appendOnly: true }} columns={columns} /> ); }; export default LazyVirtualScrollTable;
补充说明
- 开启
virtualScrollerOptions.appendOnly是关键,它能阻止DataTable在加载时重置现有数据列表 - 占位记录的标记字段(如
isLoading)需要和真实数据字段区分开,避免冲突 - 若需要更精准的加载位置控制(比如只在底部显示一个加载骨架),可以调整占位记录的数量,或者单独在表格底部渲染Skeleton组件,通过
isLoading控制显示/隐藏
内容的提问来源于stack exchange,提问作者Yan
相关产品推荐
相关产品推荐

