ngOnChanges 只击中树的根,而不是所有的后代
ngOnChanges only hitting root of tree, not all offsprings
我的 parent 组件有一个非二叉树节点(树的根)作为 child。
每个节点可以有0个或多个children类型的节点,children可以折叠或展开。
此外,在我的 parent 组件中,有一个按钮可以让您 Collapse All 或 Expand All children of树中的所有节点。
我有一个枚举标记整棵树是折叠的(通过按钮),整棵树是展开的(通过按钮),还是树的状态是手动控制的(这与这个问题无关)。
枚举如下所示:
export enum TreeStatus{
Collapsed,
Expanded,
Manual
}
parent.component.ts:
export class ParentComponent implements OnInit {
root: Node;
public treeStatus= TreeStatus.Collapsed; //in the beginning, every node in the tree has children collapsed
public isAnyNodeChildrenCollapsed = true; //checks if any node has children collapsed(mainly used for manual toggle)
onExpandAll() {
this.treeStatus= TreeStatus.Expanded;
this.isAnyNodeChildrenCollapsed = false;
}
onCollapseAll(){
this.treeStatus= TreeStatus.Collapsed;
this.isAnyNodeChildrenCollapsed = true;
}
...
}
parent.component.html:
<div>
<button *ngIf="!isAnyNodeChildrenCollapsed " (click)="onCollapseAll()"> //if all nodes have children expanded, we will see the button that allows us to collapse all
Collapse All
</button>
<button *ngIf="isAnyNodeChildrenCollapsed " (click)="onExpandAll()"> //if at least one node has children collapsed, we will see the button that allows us to expand all
Expand All
</button>
</div>
<div>
<tree-item [node]="root" [treeStatus]="treeStatus"></tree-item> //the root of my tree
</div>
tree-item.component.ts:
export class TreeItemComponent implements OnInit, OnChanges{
@Input() node: Node;
@Input() treeStatus: TreeStatus;
public isChildrenCollapsed = true; //initially, all nodes have children collapsed
ngOnChanges(changes: SimpleChanges) {
console.log(this.node.id + ": " + changes.treeStatus.previousValue + " => " + changes.TreeStatus.currentValue);
//this log above best displays the issue. When I click on Expand All, all nodes in my tree appear in the logs, but when I click Collapse All, even though this is the same callback method, only the root appears to detect the change.(even so, the toggle somehow happens regardless)
if (changes.treeStatus && changes.treeStatus.currentValue!=NavigatorTreeStatus.Manual) {
this.isChildrenCollapsed = !(changes.treeStatus.currentValue == NavigatorTreeStatus.Expanded);
}
}
}
}
tree-item.component.html(基本DFS树解析):
<div>
//display node here
</div>
<div *ngIf="node.children.length > 0 && !isChildrenCollapsed">
<tree-item *ngFor="let child of node.children"
[node]="child"
[treeStatus]="treeStatus"
>
</div>
我根本不明白为什么,当我点击 Expand All,从而将 treeStatus 更改为 Expanded 时,ngOnChanged 正常工作并按预期传播到三个节点中的每个节点,但是当点击 Collapse All 现在触发相同的 ngOnChanges 回调方法时,唯一检测到变化的节点似乎是根节点。
日志显示如下:
最初,当打开组件时,root id 获得状态 0(Collapsed),而不是 undefined:
2013777645: undefined => 0
点击全部展开后,root Id 的值从 0(Collapsed) 变为 1(Expanded),其余节点从 undefined 变为 1(Expanded) )
2013777645: 0 => 1
2118369458: undefined => 1
368241412: undefined => 1
1860836078: undefined => 1
1979885541: undefined => 1
1316570423: undefined => 1
360484732: undefined => 1
506271756: undefined => 1
现在,点击 全部折叠 后,只有根出现在日志中,值从 1(展开)更改为 0(折叠)。
2013777645: 1 => 0
最后,如果我们现在再次点击 Expand All,将出现与之前完全相同的日志,即使其他节点不应该具有未定义的 treeStatus 值,因为它已经之前被赋值了。
2013777645: 0 => 1
2118369458: undefined => 1
368241412: undefined => 1
1860836078: undefined => 1
1979885541: undefined => 1
1316570423: undefined => 1
360484732: undefined => 1
506271756: undefined => 1
你能帮我理解我错过了什么吗?
我真的希望你能从这个解释中理解这个问题。
提前致谢!
您似乎使用 ngIf
隐藏了子节点。当 ngIf
为 false 时,您的组件(或模板)不仅被隐藏,而且被销毁。您可以找到更多详细信息 here.
我的 parent 组件有一个非二叉树节点(树的根)作为 child。 每个节点可以有0个或多个children类型的节点,children可以折叠或展开。 此外,在我的 parent 组件中,有一个按钮可以让您 Collapse All 或 Expand All children of树中的所有节点。
我有一个枚举标记整棵树是折叠的(通过按钮),整棵树是展开的(通过按钮),还是树的状态是手动控制的(这与这个问题无关)。
枚举如下所示:
export enum TreeStatus{
Collapsed,
Expanded,
Manual
}
parent.component.ts:
export class ParentComponent implements OnInit {
root: Node;
public treeStatus= TreeStatus.Collapsed; //in the beginning, every node in the tree has children collapsed
public isAnyNodeChildrenCollapsed = true; //checks if any node has children collapsed(mainly used for manual toggle)
onExpandAll() {
this.treeStatus= TreeStatus.Expanded;
this.isAnyNodeChildrenCollapsed = false;
}
onCollapseAll(){
this.treeStatus= TreeStatus.Collapsed;
this.isAnyNodeChildrenCollapsed = true;
}
...
}
parent.component.html:
<div>
<button *ngIf="!isAnyNodeChildrenCollapsed " (click)="onCollapseAll()"> //if all nodes have children expanded, we will see the button that allows us to collapse all
Collapse All
</button>
<button *ngIf="isAnyNodeChildrenCollapsed " (click)="onExpandAll()"> //if at least one node has children collapsed, we will see the button that allows us to expand all
Expand All
</button>
</div>
<div>
<tree-item [node]="root" [treeStatus]="treeStatus"></tree-item> //the root of my tree
</div>
tree-item.component.ts:
export class TreeItemComponent implements OnInit, OnChanges{
@Input() node: Node;
@Input() treeStatus: TreeStatus;
public isChildrenCollapsed = true; //initially, all nodes have children collapsed
ngOnChanges(changes: SimpleChanges) {
console.log(this.node.id + ": " + changes.treeStatus.previousValue + " => " + changes.TreeStatus.currentValue);
//this log above best displays the issue. When I click on Expand All, all nodes in my tree appear in the logs, but when I click Collapse All, even though this is the same callback method, only the root appears to detect the change.(even so, the toggle somehow happens regardless)
if (changes.treeStatus && changes.treeStatus.currentValue!=NavigatorTreeStatus.Manual) {
this.isChildrenCollapsed = !(changes.treeStatus.currentValue == NavigatorTreeStatus.Expanded);
}
}
}
}
tree-item.component.html(基本DFS树解析):
<div>
//display node here
</div>
<div *ngIf="node.children.length > 0 && !isChildrenCollapsed">
<tree-item *ngFor="let child of node.children"
[node]="child"
[treeStatus]="treeStatus"
>
</div>
我根本不明白为什么,当我点击 Expand All,从而将 treeStatus 更改为 Expanded 时,ngOnChanged 正常工作并按预期传播到三个节点中的每个节点,但是当点击 Collapse All 现在触发相同的 ngOnChanges 回调方法时,唯一检测到变化的节点似乎是根节点。
日志显示如下: 最初,当打开组件时,root id 获得状态 0(Collapsed),而不是 undefined:
2013777645: undefined => 0
点击全部展开后,root Id 的值从 0(Collapsed) 变为 1(Expanded),其余节点从 undefined 变为 1(Expanded) )
2013777645: 0 => 1
2118369458: undefined => 1
368241412: undefined => 1
1860836078: undefined => 1
1979885541: undefined => 1
1316570423: undefined => 1
360484732: undefined => 1
506271756: undefined => 1
现在,点击 全部折叠 后,只有根出现在日志中,值从 1(展开)更改为 0(折叠)。
2013777645: 1 => 0
最后,如果我们现在再次点击 Expand All,将出现与之前完全相同的日志,即使其他节点不应该具有未定义的 treeStatus 值,因为它已经之前被赋值了。
2013777645: 0 => 1
2118369458: undefined => 1
368241412: undefined => 1
1860836078: undefined => 1
1979885541: undefined => 1
1316570423: undefined => 1
360484732: undefined => 1
506271756: undefined => 1
你能帮我理解我错过了什么吗? 我真的希望你能从这个解释中理解这个问题。 提前致谢!
您似乎使用 ngIf
隐藏了子节点。当 ngIf
为 false 时,您的组件(或模板)不仅被隐藏,而且被销毁。您可以找到更多详细信息 here.