Angular CDK 15表格如何结合虚拟滚动组件优化性能?
Angular 15 CDK Table 结合虚拟滚动优化性能
你的问题在于直接把整个cdk-table塞进cdk-virtual-scroll-viewport里,两者并不会自动联动——cdk-table会自行渲染所有行,完全不受虚拟滚动容器的控制。要实现两者结合,你需要调整结构,用*cdkVirtualFor替代*cdkRowDef来渲染行,让虚拟滚动容器直接管理行的渲染数量。
正确实现步骤及代码示例
- 保留表格基本结构,但移除
cdk-table的[dataSource]绑定,行的渲染将由虚拟滚动控制 - 在
cdk-virtual-scroll-viewport内部用*cdkVirtualFor遍历数据渲染行 - 确保
itemSize与实际行高一致,这是虚拟滚动计算可视区域的关键 - 配合
trackBy函数减少不必要的DOM重渲染
<!-- 虚拟滚动容器 --> <cdk-virtual-scroll-viewport appendOnly itemSize="50" class="example-viewport"> <table class="table-with-tree-wrapper"> <!-- 表头 --> <thead> <tr> <!-- 对应你的displayedColumns列定义 --> <th *ngFor="let col of displayedColumns">{{col}}</th> </tr> </thead> <tbody> <!-- 用*cdkVirtualFor渲染行,替代原来的*cdkRowDef --> <tr *cdkVirtualFor="let row of dataSource; trackBy: identifyRows" [class.table-row-hover]="hoverOnRow" [class.table-row-selected]="row?.element?.selected" > <!-- 根据列名渲染对应数据 --> <td *ngFor="let col of displayedColumns"> {{row[col]}} </td> </tr> </tbody> </table> </cdk-virtual-scroll-viewport>
额外注意事项
- 若需要表头固定,直接给
<thead>添加CSS样式即可:position: sticky; top: 0; background: #fff;,无需依赖cdk-header-row的sticky属性 appendOnly属性仅适合数据只会追加的场景(比如无限滚动加载),如果数据会频繁更新,建议移除该属性- 必须给虚拟滚动容器设置固定高度,否则无法计算可视区域:
.example-viewport { height: 500px; /* 根据需求调整高度 */ overflow: auto; }
保留CDK Table列定义的方案
如果你想复用cdk-table的列定义能力(比如cdkColumnDef),可以将虚拟滚动容器作为表格的行容器:
<table cdk-table> <!-- 列定义 --> <ng-container *ngFor="let col of displayedColumns" [cdkColumnDef]="col"> <th cdk-header-cell *cdkHeaderCellDef>{{col}}</th> <td cdk-cell *cdkCellDef="let row">{{row[col]}}</td> </ng-container> <!-- 固定表头 --> <tr cdk-header-row *cdkHeaderRowDef="displayedColumns; sticky: true"></tr> <!-- 虚拟滚动行容器 --> <cdk-virtual-scroll-viewport itemSize="50" class="example-viewport"> <tr cdk-row *cdkVirtualFor="let row of dataSource; trackBy: identifyRows" [class.table-row-hover]="hoverOnRow" [class.table-row-selected]="row?.element?.selected" [cdkRowDef]="displayedColumns" ></tr> </cdk-virtual-scroll-viewport> </table>
这种方案既保留了cdk-table的列定义逻辑,又让虚拟滚动控制行的渲染数量,适合需要复杂列配置的场景。
内容的提问来源于stack exchange,提问作者Dor Levi
相关产品推荐
相关产品推荐

