用于显示分层数据的嵌套 *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?