You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.13 19:51:02