【问题标题】:Angular render FormArray with 10k+ rows (15 columns per row) data in one pageAngular 渲染 FormArray,在一页中包含 10k+ 行(每行 15 列)数据
【发布时间】:2019-11-26 11:19:35
【问题描述】:

我需要在我的 Angular 8 Web 应用程序的一个页面中呈现一个包含 10k+ 行数据(每行 15+ FormControls)的 FormArray 的表单。由于这些大量数据,存在很大的渲染问题,有人可以帮助我提高渲染性能吗?谢谢

我曾尝试将 virtualScroll 与 @angular/cdk 一起使用,但效果仍然不佳

<table [formGroup]="validateForm">
    <thead>
      <tr>
        <th *ngFor="let column of columns">{{column.name}}</th>
      </tr>
    </thead>
    <ng-container formArrayName="rows"
                  *ngIf="inputDataValid(rowDatas, columns)">
      <tbody *cdkVirtualFor="let row of rowDatas; let rowIndex = index; "
             [formGroupName]="rowIndex"
             class="example-item"
             >
        <tr>
          <td *ngFor="let column of columns;">
            <input type="text"
                   [formControlName]="column.prop"
                   *ngIf="column.controlType === controlTypes.TEXT">
            <select name=""
                    id=""
                    [formControlName]="column.prop"
                    *ngIf="column.controlType === controlTypes.SELECT">
<!-- options -->
</select>
          </td>
        </tr>
      </tbody>
   </ng-container>
</table>

【问题讨论】:

  • 为什么不分页呢?使用无限滚动或只是加载更多按钮。
  • 当然,同时所有 10k 行不是必需的?是学校项目吗?如果是现实世界,分页就是答案。
  • 我会使用虚拟滚动进行分页
  • 很遗憾,不允许分页,这是用户的具体要求,在一页中显示和修改这些数据

标签: angular typescript angular-reactive-forms large-data formarray


【解决方案1】:

ng-container 中,您有一个 ngIf 正在调用一个函数来验证数据。您可能知道,每次 Angular 检测到更改(或事件)时,都会重新评估 ngIf。每次检测到 UI 事件时验证超过 10K+ 行将严重影响您的性能。我认为您应该在收到数据并显示一些消息(即“处理中...”)时运行该验证,表明您正在等待某事完成,然后(在验证完成后)显示您的数据。

您可以通过在验证完成后设置一个布尔属性来实现此目的,该属性设置为 true

它可能看起来像这样:

<table [formGroup]="validateForm">
    <thead>
      <tr>
        <th *ngFor="let column of columns">{{column.name}}</th>
      </tr>
    </thead>
    <tbody *ngIf="!canDisplay">
       <tr><td>Processing...</td></tr>
    </tbody>
    <ng-container formArrayName="rows"
                  *ngIf="canDisplay">
      <tbody *cdkVirtualFor="let row of rowDatas; let rowIndex = index; "
             [formGroupName]="rowIndex"
             class="example-item"
             >
        <tr>
          <td *ngFor="let column of columns;">
            <input type="text"
                   [formControlName]="column.prop"
                   *ngIf="column.controlType === controlTypes.TEXT">
            <select name=""
                    id=""
                    [formControlName]="column.prop"
                    *ngIf="column.controlType === controlTypes.SELECT">
                <!-- options -->
            </select>
          </td>
        </tr>
      </tbody>
   </ng-container>
</table>

这里 canDisplay 是一个布尔属性,当数据准备好显示时(即验证完成后)设置为 true。

【讨论】:

    【解决方案2】:

    我放弃使用FormArray来修改数据,改用TreeTable with TreeTableCellEditor in the library of Primeng,当然还有虚拟滚动

    【讨论】:

      【解决方案3】:

      我正在尝试解决类似的问题。使用 Chrome 分析器,我发现很多时间都花在重复运行验证上。创建没有验证的表单会有所帮助,但还是有点太慢了。

      禁用表单数组:

      validateForms.rows.disable({emitEvent: false});

      在创建每个 FormGroup 行时,禁用每个控件:

      FormBuilder.group({
          col1: [{value: 'value1', disabled: true }, validators... ],
          col2: [{value: 'value2', disabled: true }, validators... ],
      });
      

      然后将所有组添加到数组后,启用数组:

      validateForm.rows.enable({onlySelf: false, emitEvent: false});

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-14
        • 2017-07-20
        • 1970-01-01
        • 1970-01-01
        • 2019-07-01
        • 1970-01-01
        相关资源
        最近更新 更多