用于显示分层数据的嵌套 *ngFor 循环的性能问题

Posted

技术标签:

【中文标题】用于显示分层数据的嵌套 *ngFor 循环的性能问题【英文标题】:Performance problem with nested *ngFor loops used to display hierarchical data 【发布时间】:2020-01-28 20:51:53 【问题描述】:

我是 Angular 框架的新手,我遇到了。

    *ngFor - 每个项目的 10 个项目(级别 1)扩展面板 *ngFor 10 Items (Level 2) 网格列表显示内容 *ngFor 5 Items (Level 3) 5 个按钮切换和 2 个选择控件

为避免加载所有数据,我将根据当前打开的第 1 级面板设置第二个 *ngFor 的集合。

当我展开面板或尝试按下按钮切换时,整个页面非常慢。 注意:我不会使用这些操作更改集合。

为了调试,我在每个 ngFor 中放了一个函数来返回集合。我看到每次按下按钮切换时,angular 都会多次重做所有 *ngFor 指令中的所有迭代。

我不明白为什么每次更改控件时都需要进行所有迭代。在这种情况下如何提高性能?

重现stackblitz上的问题的代码示例!

【问题讨论】:

使用trackby功能,请查看:angular.io/api/common/NgForOf#description 感谢@Chellappan,但是当我更改控件时,angular 仍在执行所有 *ngFor 迭代。如果我理解正确,当您添加/删除集合中的项目时会使用 trackBy。 【参考方案1】:

您可以使用变量“index”提高性能,并且仅当该值是选定的accordeaon 时才使“content”可见

<!--I put the *ngFor in the own mat-expansion-panel-->
<mat-expansion-panel 
          *ngFor="let itemLevel1 of this.rootItem.children;let i=index"
          [expanded]="false" 
           <!--see that pass, itemLevel1 and "i"-->
          (opened)="onOpenLevel1Panel(itemLevel1,i)">
    <mat-expansion-panel-header>
      ...
    </mat-expansion-panel-header>   
    <ng-container *ngIf="i==index" >  
         <div *ngFor="let itemLevel2 of this.selectedItemChildren;">
            ....
         </div>
    </ng-container>
<mat-expansion-panel>

在 OpenLevel1Panel 中,我们使用变量 index

  index:number=-1;

  onOpenLevel1Panel(selectedItem: Item,index:number): void 
    this.selectedItemChildren = selectedItem.children;
    this.index=index;
  

此外,我认为“选项”是应用程序变慢的真正原因

【讨论】:

感谢@Eliseo,实际上带有 *ngIf 条件的 ng-container 有了显着的改进。在面板上导​​航时查看 html,我看到当索引更改时内容被删除。我现在意识到关闭面板只是隐藏了内容。但是,对我来说,为什么 Angular 在我更改控件时重做迭代仍然是个谜,应该只在我更改对象或整个集合时。 切换按钮时的性能问题与嵌套的 *ngFor 指令无关。经过几次测试后,我意识到如果我切换到 mat-radio-group,我不会有任何延迟。这是 mat-button-toggle 材质组件的性能问题。 github.com/angular/components/issues/17252【参考方案2】:

您指出了一个真正的问题,嵌套数据。 *ngFor 为简单的平面迭代而构建。 从这里你可以尝试结合一些技巧和技巧:

    使用“trackby”优化渲染。会有所帮助,但无法解决。 尝试使用“智能哑”组件方法来扁平化数据,请参阅this example 懒惰分别处理每一关,你甚至可以处理任何递归的深层次(点击打开新关卡) 使用virtual scroll优化渲染,这不会渲染不可见的数据,适合长列表。

【讨论】:

以上是关于用于显示分层数据的嵌套 *ngFor 循环的性能问题的主要内容,如果未能解决你的问题,请参考以下文章

如何使用angular4在ngFor循环中显示嵌套的@component?

如何在 ngFor 循环 [Angular] 中制作可扩展的表格行?

Angular2中嵌套ngFor循环的计数器

Angular *ngFor嵌套循环[重复]

在嵌套 *ngFor 循环中访问索引

ngFor用于角度嵌套对象[关闭]