在带有 @angular/cdk-experimental 的 Angular Material 2 表中使用虚拟滚动

Posted

技术标签:

【中文标题】在带有 @angular/cdk-experimental 的 Angular Material 2 表中使用虚拟滚动【英文标题】:Using Virtual Scroll in Angular Material 2 Table with @angular/cdk-experimental 【发布时间】:2018-11-14 10:05:41 【问题描述】:

我有一个表格显示这么多行,我想优化它的性能。我通过使用虚拟滚动技术找到了解决方案。这是Angular Material CDK Vritual Scroll Viewport Component 的示例,我发现了一个简单的div

<cdk-virtual-scroll-viewport class="list-container lg" [itemSize]="52.5">
  <div *cdkVirtualFor="let state of statesObservable | async;" class="list-group-item">
     <div class="state">state.name</div>
     <div class="capital">state.capital</div>
  </div>
</cdk-virtual-scroll-viewport>

但是,我想将它与Angular Material Table 集成,如下所示

<table mat-table [dataSource]="dataSource">
    <ng-container  *ngFor="let c of displayedColumns" [matColumnDef]="c">
      <th mat-header-cell *matHeaderCellDef>getTitle(c)</th>
      <td mat-cell style="white-space: pre-wrap;" *matCellDef="let element"> element[c]</td>
    </ng-container>
    <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
    <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
 </table>

我想知道如何将 cdk-virtual-scroll-viewport 包装成 mat-table。我的表格最多显示 1000 行和 20 多列,并且在加载和滚动时性能很慢。

PS:我知道使用Paginator可以解决,但我不想这样做。

版本

    "@angular/material": "^6.2.0" @angular/cdk": "^6.2.0" @angular/cdk-experimental": "^6.2.1" "@angular/core": "6.0.3" "@angular/cli": "6.0.7"

【问题讨论】:

为此+1,我面临同样的问题,否则我将不得不更改整个项目以使用简单的div *cdkVirtualFor进行操作 但我更喜欢 Angular 材质表 这还支持吗? @IgnacioBustos 查看此示例代码:stackblitz.com/edit/nahgrin-virtual-scroll-table 【参考方案1】:

这不是目前开箱即用的东西。 CdkTable(或MatTable)组件不支持虚拟滚动YET

@angular/cdk 中的虚拟滚动支持仍处于试验阶段 - 这将在版本 7 中更改。

但是,当此功能落地时,下一步将是在桌子上实施它。我会解释原因。

cdk-virtual-scroll-viewport*cdkVirtualFor 指令的容器,如果我们查看这个指令 (CdkVirtualForOf) 我们可以看到

    实现 CollectionViewer (code)

    它接受(使用)DataSource 实例 (code)

考虑到这一点,让我们看看CdkTable

    实现 CollectionViewer (code)

    它接受(使用)DataSource 实例 (code)

相似度并非偶然,cdk-virtual-scroll-viewport 可以使用该表(经过一些调整),就像使用 cdkVirtualFor 一样。

我不确定最终的实现是什么,开发人员是否能够从外部包装表格或表格将在内部设置它,但这就是它的方向。

如果我不得不猜测,我会说开发人员会选择是否要用虚拟卷轴包裹桌子。这是因为cdk-virtual-scroll-viewport 不查询cdkVirtualFor(通过ViewChild),它是被动的并等待附加它的东西。这表明这是事先考虑好的。

您现在可以通过扩展CdkTable 并自己进行调整来完成,这需要了解表的内部结构并且可能需要一些时间。建议稍等。

【讨论】:

【参考方案2】:

目前还不支持。但是有些人试图做一些POC。这是一个https://github.com/angular/material2/issues/10122#issuecomment-440442656。

同样在issue 中讨论了虚拟滚动以及上述 POC 的工作原理。

【讨论】:

【参考方案3】:

I made a custom directive,有什么办法可以解决这个问题:

1) 安装一个包:$ npm install -save ng-table-virtual-scroll 并将其添加到导入中:

import  TableVirtualScrollModule  from 'ng-table-virtual-scroll';

@NgModule(
  imports: [
    // ...
    TableVirtualScrollModule
  ]
)
export class AppModule  

2) 使用包中的自定义DataSource

import  TableVirtualScrollDataSource  from 'ng-table-virtual-scroll';

@Component(...)
export class MyComponent 

  dataSource = new TableVirtualScrollDataSource();


3) 在视口容器上使用指令:

<cdk-virtual-scroll-viewport tvsItemSize style="height: 400px;">
    <table mat-table [dataSource]="dataSource">
    ...
    </table>
</cdk-virtual-scroll-viewport>

该指令允许您使用mat-table 的所有功能,例如排序、分页、粘性标题/列等

【讨论】:

如何重新填充 mat-table?这不是更新表... this.dataSource= new TableVirtualScrollDataSource(this.tasksNotPlanned); 我试过了,数据源用dataSource = new TableVirtualScrollDataSource('someData');但这不会在 UI 中呈现行

以上是关于在带有 @angular/cdk-experimental 的 Angular Material 2 表中使用虚拟滚动的主要内容,如果未能解决你的问题,请参考以下文章

带有 LiveCharts 的 WPF 在运行时添加带有 DataBinding 的系列

如何在带有 React 的 Typescript/JSX 中使用带有箭头函数的泛型?

带有自定义层的 CoreML 在带有 Apple 神经引擎的设备上存在错误

如何在本地主机上设置带有和不带有 www 前缀的子域/域

带有核心数据的 NSPredicate,在字符串属性中搜索带有边界的单词

是否应该在带有或不带有 :hover 伪类的规则中设置游标属性?