Django REST+React+AG-GRID百万级商品数据高效分页实现咨询
实现方案
一、AG-GRID 按需拉取分页逻辑修改
你当前用的是AG-GRID默认的客户端分页模式,只会基于已加载到前端的数据生成分页,要改成支持按需拉取的逻辑,按如下步骤修改:
1. 新增状态变量
首先新增三个状态:
// 存储后端返回的总数据条数 const [totalCount, setTotalCount] = useState(0); // 存储已拉取的批次缓存,key是后端的page值,value是对应1000条数据 const [fetchedBatches, setFetchedBatches] = useState(new Map()); // 控制加载态 const [isLoading, setIsLoading] = useState(false);
2. 封装数据拉取逻辑
封装统一的请求方法,自动判断是否需要请求新的批次:
const fetchBatchIfNeeded = useCallback(async (targetFrontendPage) => { // 前端每页20条,计算目标数据的全局偏移量 const globalOffset = targetFrontendPage * 20; // 计算对应后端的批次page(每批次1000条) const backendPage = Math.floor(globalOffset / 1000); // 已拉取过的批次直接复用 if (fetchedBatches.has(backendPage)) { return; } setIsLoading(true); try { const result = await jwtAxios(`http://localhost:8000/${ID}/products?page=${backendPage}`); if (result?.data?.data?.length) { // 存储新拉取的批次 setFetchedBatches(prev => new Map(prev).set(backendPage, result.data.data)); // 首次请求时设置总条数和列配置 if (totalCount === 0) { setTotalCount(result.data.count); const columnDefs = Object.keys(result.data.data[0]).map(fieldName => ({ headerName: fieldName, field: fieldName })); setColumnData(columnDefs); } // 合并所有已拉取的批次到rowData const allData = Array.from(fetchedBatches.values()).flat(); setRowData(allData); } } catch (e) { console.error('拉取数据失败', e); } finally { setIsLoading(false); } }, [ID, fetchedBatches, totalCount]);
3. 监听AG-GRID分页变更事件
给AgGridReact组件新增onPaginationChanged属性,监听用户翻页动作:
const onPaginationChanged = useCallback((params) => { if (params.api.paginationGetCurrentPage() !== undefined) { fetchBatchIfNeeded(params.api.paginationGetCurrentPage()); } }, [fetchBatchIfNeeded]);
同时给AgGridReact新增总条数配置:
<AgGridReact // 原有配置保留 pagination={true} paginationPageSize={20} // 新增以下配置 rowCount={totalCount} onPaginationChanged={onPaginationChanged} loading={isLoading} />
4. 首次加载触发
修改原有useEffect,首次加载时拉取第一批次数据:
useEffect(() => { // 清空旧缓存 setFetchedBatches(new Map()); setRowData([]); setTotalCount(0); // 拉取第一批次(对应前端前50页) fetchBatchIfNeeded(0); }, [catalogID, fetchBatchIfNeeded]);
二、后端代码优化建议
你当前Django接口代码有两个可优化点:
- 语法错误:
total_count: collection.count()应改为total_count = collection.count() - 百万级数据下
skip性能极低,建议改成游标分页:每次请求携带上一批最后一条数据的_id,查询条件改为_id > last_id,无需跳过大量文档,查询速度提升10倍以上。
三、更优的大数据展示方案
- 批次预加载方案:就是你当前的逻辑,可额外增加提前拉取相邻批次的逻辑,用户翻页无感知,适合翻页频率高的内部系统场景
- 无限滚动模式:关闭AG-GRID的分页,开启
rowModelType="infinite",用户滚动到表格底部自动加载下一批数据,操作更流畅,适合移动端、C端场景 - 全服务端行模型:如果需要支持全表筛选、排序,直接开启AG-GRID的
serverSide行模型,所有筛选、排序、分页参数都传给后端处理,前端只渲染当前页的20条数据,内存占用最低,适合超大规模数据集、复杂查询场景。
内容的提问来源于stack exchange,提问作者bdemirka
相关产品推荐
相关产品推荐

