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

React ag-grid客户端行模型实现滚动底部非冻结加载器咨询

实现客户端行模型下的滚动触发自定义加载提示

我之前也碰到过一模一样的需求,官方的showLoadingOverlay()确实会锁死整个网格,完全不符合滚动加载的交互预期。下面是我摸索出来的实现方案,完全基于客户端行模型,不需要切换到其他行模型:

核心思路

通过监听网格滚动事件,在滚动到第99行附近时触发数据加载,同时在网格底部插入一个全屏的自定义加载行(而非覆盖整个网格的overlay),加载完成后移除该行并追加新数据,全程不阻塞网格的正常交互。

具体实现步骤

1. 初始化状态与网格引用

首先在React组件中维护必要的状态,并保存网格API的引用:

import { useState, useRef, useCallback } from 'react';
import { AgGridReact } from 'ag-grid-react';
import 'ag-grid-community/styles/ag-grid.css';
import 'ag-grid-community/styles/ag-theme-alpine.css';
import _ from 'lodash';

const MyGrid = () => {
  const [rowData, setRowData] = useState([]);
  const [isLoading, setIsLoading] = useState(false);
  const [hasMoreData, setHasMoreData] = useState(true); // 标记是否还有更多数据可加载
  const gridApiRef = useRef(null);

  // 网格就绪时保存API引用
  const onGridReady = (params) => {
    gridApiRef.current = params.api;
    // 加载初始数据
    loadInitialData();
  };

2. 配置网格与自定义加载行渲染

在网格配置中,启用全屏行(fullWidthRow)并自定义加载行的渲染内容:

const gridOptions = {
    getRowNodeId: (data) => data.id, // 必须设置,方便后续精准移除加载行
    onBodyScroll: throttledHandleScroll, // 节流后的滚动事件处理
    fullWidthCellRenderer: (params) => {
      // 判断是否为加载行,渲染自定义spinner和提示文本
      if (params.data.isLoading) {
        return (
          <div style={{ padding: '20px', textAlign: 'center' }}>
            <div className="spinner"></div>
            <span>One moment please</span>
          </div>
        );
      }
      return null;
    },
    // 你的其他网格配置(列定义、高度等)
    columnDefs: [
      { headerName: 'ID', field: 'id' },
      { headerName: '名称', field: 'name' },
      // 其他业务列...
    ],
  };

3. 滚动事件处理与节流

为了避免滚动时频繁触发加载请求,对滚动事件做节流处理,并判断是否到达触发加载的位置:

// 节流处理滚动事件(300ms内只触发一次,避免频繁调用API)
  const throttledHandleScroll = useCallback(
    _.throttle(() => {
      if (isLoading || !hasMoreData) return;

      const api = gridApiRef.current;
      if (!api) return;

      // 根据行索引判断:第99行之后触发(索引从0开始,所以判断>=98)
      const lastDisplayedRow = api.getLastDisplayedRow();
      if (lastDisplayedRow >= 98) {
        loadMoreData();
      }

      // 也可以用滚动距离判断(更通用,适合任意初始数据量)
      // const gridBody = api.getGridBodyElement();
      // const scrollThreshold = 50; // 可根据行高调整阈值
      // if (gridBody.scrollTop + gridBody.clientHeight >= gridBody.scrollHeight - scrollThreshold) {
      //   loadMoreData();
      // }
    }, 300),
    [isLoading, hasMoreData]
  );

4. 数据加载逻辑

实现加载函数,添加临时加载行、调用API、更新数据:

const loadMoreData = async () => {
    setIsLoading(true);
    // 添加全屏加载行到数据中
    setRowData(prev => [...prev, { id: 'loading-row', fullWidth: true, isLoading: true }]);

    try {
      // 调用你的API,替换成实际接口请求
      const newData = await fetch('/api/your-data-endpoint', {
        method: 'GET',
        // 传递分页参数,比如当前数据长度作为偏移量
        params: { offset: rowData.length - 1 } // 减去加载行的数量
      }).then(res => res.json());

      // 移除加载行,追加新数据
      setRowData(prev => prev.filter(row => row.id !== 'loading-row').concat(newData));

      // 如果返回数据为空,标记没有更多数据
      if (newData.length === 0) {
        setHasMoreData(false);
      }
    } catch (error) {
      console.error('加载数据失败:', error);
      // 加载失败时移除加载行
      setRowData(prev => prev.filter(row => row.id !== 'loading-row'));
    } finally {
      setIsLoading(false);
    }
  };

  // 初始数据加载函数
  const loadInitialData = async () => {
    // 加载第一页数据,逻辑类似loadMoreData
    const initialData = await fetch('/api/initial-data').then(res => res.json());
    setRowData(initialData);
  };

5. 添加Spinner样式

在组件的CSS中添加加载动画样式:

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

.spinner {
  border: 4px solid #f3f3f3;
  border-top: 4px solid #3498db;
  border-radius: 50%;
  width: 30px;
  height: 30px;
  animation: spin 1s linear infinite;
  margin: 0 auto 8px;
}

6. 渲染网格

最后渲染AgGridReact组件:

return (
    <div className="ag-theme-alpine" style={{ height: 600, width: '100%' }}>
      <AgGridReact
        rowData={rowData}
        gridOptions={gridOptions}
        onGridReady={onGridReady}
      />
    </div>
  );
};

export default MyGrid;

关键注意点

  • 必须设置getRowNodeId,否则无法准确移除临时的加载行。
  • 对滚动事件做节流处理,避免短时间内多次触发API请求。
  • 通过fullWidthCellRenderer实现的加载行只会占据网格底部,不会阻塞整个网格的交互。

内容的提问来源于stack exchange,提问作者sandy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 14:32:26