mos*_* cs 15 angular-material angular-material2 angular angular-cdk
我在我的项目中使用角度材质,我使用Mat-Table为每个表渲染1000个产品/行.当表格改为分页(我们使用后端分页)到1000行时,性能变得非常慢,我甚至无法在文本框中写入.
我试图调试问题,所以我把日志放在一个列模板上,这样我就可以看到渲染是如何工作的.
即使我将鼠标悬停在表格标题上,我也看到它会重新呈现所有行.是否有可能将变更检测控制为ChangeDetectionStrategy.OnPush
小智 27
不确定这是否会对您的情况有所帮助,因为没有代码但我们发现如果在设置数据源分页器之前设置了大型数据集,则MatTable加载速度非常慢.
例如 - 这需要几秒钟来渲染......
dataSource: MatTableDataSource<LocationItem> = new MatTableDataSource();
@ViewChild(MatSort) sort: MatSort;
@ViewChild(MatPaginator) paginator: MatPaginator;
ngOnInit() {
this.dataSource.data = [GetLargeDataSet];
}
ngAfterViewInit() {
this.dataSource.sort = this.sort;
this.dataSource.paginator = this.paginator;
}
Run Code Online (Sandbox Code Playgroud)
......但这很快
ngOnInit() {
// data loaded after view init
}
ngAfterViewInit() {
this.dataSource.sort = this.sort;
this.dataSource.paginator = this.paginator;
/* now it's okay to set large data source... */
this.dataSource.data = [GetLargeDataSet];
}
Run Code Online (Sandbox Code Playgroud)
顺便说一下,我们第二次访问组件时才发现这个问题,因为来自服务器的大型数据集正在被缓存,并且在第二次访问组件时立即可用.如果要将该代码保留在ngOnInit函数中,另一个选项是将.delay(100)添加到您的observable.
无论如何,这可能会或可能不会帮助您的情况.
KMJ*_*sen 10
经过一番努力,我能够将这篇文章中的许多不同答案结合起来,包括@turneye的上面和OP选择的正确答案,以及另一个类似的SO帖子的答案,这里和这里。
页面上的父组件以及多个子组件(包括分页MatTable组件)需要大约 1000 行。
数据加载时间小于 500 毫秒,但页面平均需要 15 秒才能渲染,因为最初我只是传递一个MatTableDataSource已分配数据的对象。
MatTableDataSource.data设置属性。MatPaginatorMatSortchangeDetection为。ChangeDetectionStrategy.OnPushComponentMatDataSource.data属性后,告诉 Angular 检测变化ChangeDetectorRef.detectChanges()现在,完整的 DOM 总共渲染时间约为 1 秒,考虑到需要立即呈现的数据量,这已经足够了。
这是一个精简的示例:
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
selector: 'app-dynamic-grid',
templateUrl: './dynamic-grid.component.html',
styleUrls: ['./dynamic-grid.component.scss'],
})
export class DynamicGridComponent implements OnInit, AfterViewInit {
@Input() public dataSource$: Observable<any[]>;
public matDataSource = new MatTableDataSource<any>();
@ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
@ViewChild(MatSort, { static: true }) sort: MatSort;
constructor(private changeDetectorRef: ChangeDetectorRef) {}
ngOnInit(): void {}
ngAfterViewInit() {
this.matDataSource.paginator = this.paginator;
this.matDataSource.sort = this.sort;
this.dataSource$.subscribe(x => {
this.matDataSource.data = x;
// The important part:
this.changeDetectorRef.detectChanges();
});
}
}
Run Code Online (Sandbox Code Playgroud)
扩展@Turneye 的回答。它发生的原因是因为在渲染所有行之后设置了分页器,因为这就是ngAfterViewInit钩子告诉你的。
所以它首先呈现来自数据源的所有行,然后它看到:“嘿,我得到了一个分页器,让我删除所有行(寻呼机计数除外)”。这在大型数据集和/或复杂的表格单元格模板上显然非常慢。
您可以使用此解决{static: true}你的选项@ViewChild。这将使分页器在ngOnInit生命周期钩子内可用,并且在任何行被渲染之前:
窃取他的代码,可以改成这样,还是有一个快表:
readonly dataSource: MatTableDataSource<LocationItem> = new MatTableDataSource();
@ViewChild(MatSort, { static: true }) sort: MatSort;
@ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
ngOnInit() {
this.dataSource.data = [ GetLargeDataSet ];
this.dataSource.sort = this.sort;
this.dataSource.paginator = this.paginator;
}
Run Code Online (Sandbox Code Playgroud)
请注意,如果您mat-paginator在结构指令中,这将不起作用*ngIf
另一个性能问题可能是您必须声明一个trackBy函数:
为了提高性能,可以向表提供一个 trackBy 函数,类似于 Angular 的 ngFor trackBy。这通知表如何唯一标识行以跟踪数据如何随每次更新而变化。
<table mat-table [dataSource]="dataSource" [trackBy]="myTrackById">
Run Code Online (Sandbox Code Playgroud)
我已经解决了这个问题,我通过将表格包装在自定义(网格)组件中并控制changeDetection组件的状态ChangeDetectionStrategy.OnPush以及何时渲染更新来提高性能ChangeDetectorRef.detectChanges()
| 归档时间: |
|
| 查看次数: |
8386 次 |
| 最近记录: |