首页 > 解决方案 > Angular Material Datatable 加载缓慢

问题描述

我的角度材料应用程序遇到了一些麻烦。我正在使用带有分页器的数据表。数据不必排序。

在加载数据时,我正在展示一个垫子旋转器

<div *ngIf="schools !== undefined">
        <mat-spinner *ngIf="showSpinner" style="margin:0 auto;"></mat-spinner>
        <div *ngIf="!showSpinner">
            Keine Daten gefunden.
        </div>
</div>
<div *ngIf="schools !== undefined">
   <mat-table [dataSource]="dataSource"> 
      ...
   </mat-table>
   <mat-paginator [pageSizeOptions]="[10, 20, 50, 100]" [pageSize]="20" showFirstLastButtons></mat-paginator>
</div>

在正常情况下,我正在加载数据,并且在加载数据时微调器停止旋转,然后显示数据。这工作得很好。

但是对于一个大约有 400 行的表,我遇到了这个问题:

成功加载数据后,微调器会变得非常缓慢大约一秒钟,并且数据表会显示所有内容。(由分页器分隔)

从 api 加载数据大约需要 400 毫秒,解析它大约需要 3 毫秒,所以这不应该是问题。

我正在加载这样的数据:

ngOnInit() {
    setTimeout(() => {
      this.showSpinner = false;
    }, 5000);

    this.userID = this.authService.getCurrentUser.uid;
    this.loadData();
}

loadData() {
    this.apiService.getSchools().subscribe((schoolsData: any) => {
      this.schools = this.refParser.parse(schoolsData);
      this.dataSource = new MatTableDataSource(this.schools);

      this.cdr.detectChanges();
      this.dataSource.paginator = this.paginator;
    });
}

我已经在 stackoverflow 上找到了一篇应该对我有帮助的帖子(Angular 6 MatTable Performance in 1000 rows.)。但这对我没有帮助:(

我是这样尝试的:

ngOnInit() {
    setTimeout(() => {
      this.showSpinner = false;
    }, 5000);

    this.userID = this.authService.getCurrentUser.uid;
    //this.loadData();
    this.dataSource = new MatTableDataSource();

    this.dataSource.paginator = this.paginator;
}

ngAfterViewInit(){
    setTimeout(() => {
      this.apiService.getSchools().subscribe((schoolsData: any) => {
        this.schools = this.refParser.parse(schoolsData);
        this.dataSource.data = this.schools;
        this.cdr.detectChanges();
      })
    })
}

它没有给我任何性能提升。唯一发生的事情是,分页器不再工作了。

有谁知道什么可以帮助我提高我的应用程序的性能?

谢谢您的回答:)

标签: angularperformancedatatableangular-material

解决方案


我过去也遇到过同样的问题,Mat-Table 自己处理变更检测,所以它不是 mat 表的问题,它是数据源设置错误。

如果您一次性传递所有数据,它将仅在第一次加载时呈现整个数据并显示滞后。

由于您使用的是分页器,因此您应该将数据源分解为 pageSize,以便在加载时仅呈现 20 个元素。

创建一个新的分页器实例:actualPaginator: MatPaginator;

@ViewChild(MatPaginator, {static: false})
  set paginator(value: MatPaginator) {
    this.actualPaginator = value;
  }

this.actualPaginator.pageIndex = Math.ceil(this.schools.length/this.actualPaginator.pageSize) - 1;

 let nextPageData: any[] = [];
 nextPageData = this.schools.slice((this.actualPaginator.pageSize * this.actualPaginator.pageIndex),(this.actualPaginator.pageSize * (this.actualPaginator.pageIndex + 1)));
 this.dataSource.data = nextPageData;

因此,分发您的this.schools数据并按页面大小计数加载它,this.schools在单击下一个按钮时使用下一个数据槽更改数据源将解决您的问题。

您必须通过创建作为关键解决方案的新 MatPaginator 实例来单独操作 mat-paginator。


推荐阅读