AG Grid:autoHeight下虚拟行结合手动无限滚动的性能优化问询
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
Disable
domLayout: 'autoHeight'
Stick with AG Grid's default virtualized rendering (enabled by default forclientSideorinfiniterow models). Don't set thedomLayoutproperty at all.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.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, mimickingautoHeightbehavior.
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., usinggetRowHeightcallback). - Performance: Throttling the scroll event is crucial to prevent excessive calculations. You can use libraries like Lodash's
throttleor implement a simple one yourself. - Infinite Row Model: If you're using the
infiniterow model, you'll adjust the logic to load blocks of rows viasetRowCount()andgetRows()instead ofapplyTransaction, 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

