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

AG Grid:autoHeight下虚拟行结合手动无限滚动的性能优化问询

Combining AG Grid's domLayout: 'autoHeight' Style Growth with Virtual Row Rendering

Great question! The core challenge here is that AG Grid's domLayout: 'autoHeight' and virtual row rendering are natively incompatible—autoHeight requires rendering all rows to calculate the total grid height, while virtualization only renders rows visible in the viewport to keep DOM bloat in check. But we can simulate the "dynamic height growth" behavior you want while retaining virtualization. Here's how:

The Workaround: Simulate Auto-Height with Manual Height Control

Instead of relying on AG Grid's built-in autoHeight, we'll manually manage the grid container's height as we load more rows, while keeping AG Grid's virtualization enabled. This gives you the appearance of a grid that grows with its content, without rendering every row in the DOM.

Step-by-Step Implementation

  1. Disable domLayout: 'autoHeight'
    Stick with AG Grid's default virtualized rendering (enabled by default for clientSide or infinite row models). Don't set the domLayout property at all.

  2. Listen for Scroll Events on the Grid Container
    Detect when the user scrolls near the bottom of the container to trigger loading more rows. Use a throttle to avoid excessive event triggers.

  3. Calculate and Update the Container Height
    After adding new rows, calculate the total height of all loaded rows (including headers) and set this as the grid container's height. This makes the container grow as rows are added, mimicking autoHeight behavior.

Example Code (Vanilla JS)

// Initialize AG Grid
const gridOptions = {
  columnDefs: [
    { field: 'id' },
    { field: 'name' },
    { field: 'value' }
    // Add your column definitions here
  ],
  rowData: initialRowData, // Your initial dataset
  rowModelType: 'clientSide',
  onGridReady: (params) => {
    const gridApi = params.api;
    const gridContainer = document.getElementById('ag-grid-container');

    // Set initial container height
    updateGridContainerHeight(gridApi, gridContainer);

    // Throttled scroll listener to trigger load more
    let isLoading = false;
    gridContainer.addEventListener('scroll', () => {
      // Check if we're near the bottom (adjust the 50px threshold as needed)
      const isNearBottom = gridContainer.scrollTop + gridContainer.clientHeight >= gridContainer.scrollHeight - 50;
      
      if (isNearBottom && !isLoading) {
        isLoading = true;
        // Fetch/load your new rows here
        fetchMoreRows().then(newRows => {
          gridApi.applyTransaction({ add: newRows });
          updateGridContainerHeight(gridApi, gridContainer);
          isLoading = false;
        });
      }
    });
  }
};

// Helper to calculate and set total grid height
function updateGridContainerHeight(gridApi, container) {
  let totalRowHeight = 0;
  const totalDisplayedRows = gridApi.getDisplayedRowCount();

  // Sum heights of all displayed rows (handles dynamic row heights too)
  for (let i = 0; i < totalDisplayedRows; i++) {
    totalRowHeight += gridApi.getRowHeightForRowIndex(i);
  }

  // Add header height to total
  const headerHeight = gridApi.getHeaderHeight();
  const totalGridHeight = totalRowHeight + headerHeight;

  // Set container height
  container.style.height = `${totalGridHeight}px`;
}

// Mock function for loading more rows
function fetchMoreRows() {
  return new Promise(resolve => {
    // Replace with your actual data fetch logic
    setTimeout(() => {
      const newRows = Array.from({ length: 20 }, (_, idx) => ({
        id: Date.now() + idx,
        name: `Row ${Date.now() + idx}`,
        value: Math.random() * 100
      }));
      resolve(newRows);
    }, 500);
  });
}

// Mount the grid
new agGrid.Grid(document.getElementById('ag-grid-container'), gridOptions);

Key Notes

  • Dynamic Row Heights: The example uses getRowHeightForRowIndex() which works even if you have dynamic row heights (e.g., using getRowHeight callback).
  • Performance: Throttling the scroll event is crucial to prevent excessive calculations. You can use libraries like Lodash's throttle or implement a simple one yourself.
  • Infinite Row Model: If you're using the infinite row model, you'll adjust the logic to load blocks of rows via setRowCount() and getRows() instead of applyTransaction, but the height calculation principle remains the same.

Why This Works

By manually setting the container height to match the total height of all loaded rows, we trick the browser into showing a scrollable container that grows as more data is added. Meanwhile, AG Grid continues to only render rows visible in the viewport, keeping the DOM lightweight even with thousands of rows.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:20:06