Ag-grid-angular树形数据行分组批量展开/折叠渲染卡顿求助
Ag-Grid-Angular 树形数据批量展开/折叠卡顿优化方案
核心问题分析
你的代码中直接遍历所有节点并逐个调用setExpanded(),每个调用都会触发一次网格重绘。一万行数据下会产生上万次重绘操作,直接导致页面冻结。下面是针对性的优化方案:
1. 用batchUpdate批量处理节点状态
Ag-Grid提供batchUpdate()方法,能将所有节点状态变更打包,只触发一次网格重绘,彻底解决频繁重绘的问题。修改后的代码:
expandGrid(level: number) { this.selectedOption = level.toString(); // 批量包裹所有节点操作 this.gridApi.batchUpdate(() => { if (level === 1) { this.gridApi.collapseAll(); } else { this.gridApi.forEachNode(node => { const targetExpanded = node.level <= level - 2; // 仅当状态不一致时才更新,减少无效操作 if (node.expanded !== targetExpanded) { node.setExpanded(targetExpanded); } }); } }); }
2. 开启虚拟滚动减少DOM渲染量
如果你的网格还没开启虚拟滚动,必须配置这项——它让Ag-Grid只渲染当前视口内的行,而非全部一万行,大幅降低DOM节点数量:
在GridOptions中添加配置:
gridOptions: GridOptions = { rowModelType: 'virtual', // 开启虚拟滚动 cacheBlockSize: 100, // 每次加载的行数,可根据需求调整 suppressRowExpandAnimation: true, // 禁用展开/折叠动画,避免卡顿 // 其他原有配置... };
3. 防抖处理避免频繁操作
如果用户快速切换下拉选项,添加防抖逻辑防止短时间内多次触发批量操作:
// 引入lodash的debounce(或自行实现简单防抖) import { debounce } from 'lodash'; // 定义防抖后的处理方法,延迟300ms执行 private debouncedExpand = debounce((level: number) => { this.gridApi.batchUpdate(() => { if (level === 1) { this.gridApi.collapseAll(); } else { this.gridApi.forEachNode(node => { const targetExpanded = node.level <= level - 2; if (node.expanded !== targetExpanded) { node.setExpanded(targetExpanded); } }); } }); }, 300); // 对外暴露的调用方法 expandGrid(level: number) { this.selectedOption = level.toString(); this.debouncedExpand(level); }
4. 额外优化点
- 避免遍历全部节点:如果你的树形结构有明确的层级关系,可通过
forEachNodeAtLevel()直接定位到目标层级的父节点,减少遍历范围。 - 关闭不必要的网格特性:比如排序、过滤的实时触发(如果不需要的话),进一步降低性能消耗。
内容的提问来源于stack exchange,提问作者S8321
相关产品推荐
相关产品推荐

