为什么在更改支持 mat-tree 的数据后,我的 angular 应用程序变得非常慢? [英] Why is my angular app becoming very slow after changing the data backing a mat-tree?
问题描述
我正在实现角度/材质树组件,但遇到了一些问题.保存对树的更改后,我正在重置支持树的数据(有效),但是应用程序变得异常缓慢,扩展节点可能需要大约 8 秒.
更奇怪的是,实际操作数据源的代码在其他地方运行,例如向树添加一个新子项——我们希望 UI 更新,而这不会导致问题.只有在保存时应用才会变慢.
save(): void {const 树 = this.flattenedTree.filter(node => this.isRootNode(node));this.serviceThatHasNoSideEffects.save(trees).then(结果 => {this.tree = 结果;this.flattenedTree = this.getFlattenedTree();this.refreshTree();});}私人刷新树(){const 数据:any[] = this.flattenedTree.filter(x => this.isRootNode(x)).filter(x => x.children.length > 0 || x.id === this.focusId);this.nestedDataSource.data = null;this.nestedDataSource.data = 数据;const focusNode = this.getNode(this.focusId);this.nestedTreeControl.expand(focusNode);}私有 addChild(parentNode: any, childNode: any) {如果 (!this.getNode(parentNode)) {this.flattenedTree.push(parentNode);}如果 (!this.getNode(childNode)) {this.flattenedTree.push(childNode);}parentNode.children.push(childNode);this.refreshTree();this.nestedTreeControl.expand(parentNode);}
更改刷新树以创建全新的数据源解决了缓慢的问题(内存泄漏?),但不添加未在 UI 中显示的子项.虽然孩子在扁平的树上,所以应该显示出来.
私有 refreshTree() {const 数据:any[] = this.flattenedTree.filter(x => this.isRootNode(x)).filter(x => x.children.length > 0 || x.id === this.focusId);this.nestedDataSource = new MatTreeNestedDataSource();this.nestedDataSource.data = 数据;const focusNode = this.getNode(this.focusId);this.nestedTreeControl.expand(focusNode);}
这是支持它的 html.很标准.
<li class="mat-tree-node"><按钮垫图标按钮禁用></button>{{node.uniqueName}}</mat-tree-node><!--当有嵌套子项时--><mat-nested-tree-node *matTreeNodeDef="let node; when: hasNestedChild"><li><div class="mat-tree-node">
<ul [class.invisible]="!nestedTreeControl.isExpanded(node)"><ng-container matTreeNodeOutlet></ng-container></mat-nested-tree-node></mat-tree>
我花了几个小时才让它工作,但这是我所做的更改:
//mat 树所基于的 cdk 树存在一个错误,导致在未先将数据设置为 null 的情况下,子项无法在 UI 中呈现this.nestedDataSource.data = null;//mat-tree 在不实例化新的 MatTreeNestedDataSource 时存在某种内存泄漏问题,这会导致应用程序变得非常缓慢this.nestedDataSource = new MatTreeNestedDataSource();this.nestedDataSource.data = 数据;
我在这里找到的显示儿童问题:https://github.com/angular/material2/问题/11381
I am implementing the angular/material tree component and having some problems. After saving changes to the tree I am resetting the data backing the tree (which works) however the app then becomes incredibly slow, expanding nodes can take about 8 seconds.
What makes this even weirder is that the code that actually manipulates the data source is run in other places, such as adding a new child to the tree - we want the UI to update, and this does not cause a problem. It is only when saving that the app becomes slow.
save(): void {
const trees = this.flattenedTree.filter(node => this.isRootNode(node));
this.serviceThatHasNoSideEffects.save(trees)
.then(result => {
this.tree = result;
this.flattenedTree = this.getFlattenedTree();
this.refreshTree();
});
}
private refreshTree() {
const data: any[] = this.flattenedTree
.filter(x => this.isRootNode(x))
.filter(x => x.children.length > 0 || x.id === this.focusId);
this.nestedDataSource.data = null;
this.nestedDataSource.data = data;
const focusNode = this.getNode(this.focusId);
this.nestedTreeControl.expand(focusNode);
}
private addChild(parentNode: any, childNode: any) {
if (!this.getNode(parentNode)) {
this.flattenedTree.push(parentNode);
}
if (!this.getNode(childNode)) {
this.flattenedTree.push(childNode);
}
parentNode.children.push(childNode);
this.refreshTree();
this.nestedTreeControl.expand(parentNode);
}
EDIT:
changing refresh tree to create a completely new data source solves the slow issue (memory leak?) but not adding a child isnt displaying in the UI. Although the child is there on the flattened tree so should be displayed.
private refreshTree() {
const data: any[] = this.flattenedTree
.filter(x => this.isRootNode(x))
.filter(x => x.children.length > 0 || x.id === this.focusId);
this.nestedDataSource = new MatTreeNestedDataSource<theTreeType>();
this.nestedDataSource.data = data;
const focusNode = this.getNode(this.focusId);
this.nestedTreeControl.expand(focusNode);
}
EDIT: here is the html backing it. pretty standard.
<mat-tree-node *matTreeNodeDef="let node" matTreeNodeToggle>
<li class="mat-tree-node">
<button mat-icon-button disabled></button>
{{node.uniqueName}}
</li>
</mat-tree-node>
<!--when has nested child-->
<mat-nested-tree-node *matTreeNodeDef="let node; when: hasNestedChild">
<li>
<div class="mat-tree-node">
<button mat-icon-button matTreeNodeToggle>
<mat-icon>
{{nestedTreeControl.isExpanded(node) ? 'expand_more' : 'chevron_right'}}
</mat-icon>
</button>
{{node.uniqueName}}
</div>
<ul [class.invisible]="!nestedTreeControl.isExpanded(node)">
<ng-container matTreeNodeOutlet></ng-container>
</ul>
</li>
</mat-nested-tree-node>
</mat-tree>
it took me a few hours to get it working but here is the change I made:
// cdk tree that mat tree is based on has a bug causing children to not be rendered in the UI without first setting the data to null
this.nestedDataSource.data = null;
// mat-tree has some sort of memory leak issue when not instantiating a new MatTreeNestedDataSource which causes the app to become very slow
this.nestedDataSource = new MatTreeNestedDataSource<LocationHierarchyNodeDataModel>();
this.nestedDataSource.data = data;
The displaying children issue I found here: https://github.com/angular/material2/issues/11381
这篇关于为什么在更改支持 mat-tree 的数据后,我的 angular 应用程序变得非常慢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!