微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

ngOnChanges 只击中树的根,而不是所有的后代

如何解决ngOnChanges 只击中树的根,而不是所有的后代

我的父组件有一个非二叉树节点(树的根)作为子节点。 每个节点可以有 0 个或多个节点类型的子节点,子节点可以折叠或展开。 此外,在我的父组件中,有一个按钮可让您全部折叠展开所有树中所有节点的子级。

我有一个枚举来标记整个树是折叠(通过按钮),整个树是展开(通过按钮),还是手动控制树状态(这与此问题无关)。>

枚举看起来像这样:

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>

我只是不明白为什么,当我点击全部展开,从而将 treeStatus 更改为已展开时,ngOnChanged 正常工作并按预期运行,传播到三个节点中的每个节点,但是当点击 Collapse All 现在会触发相同的 ngOnChanges 回调方法,唯一检测到更改的节点似乎是根。

以下是日志的显示方式: 最初,当打开组件时,root id 的状态为 0(已折叠),而不是未定义:

2013777645:未定义 => 0

点击Expand All后,root Id的值从0(Collapsed)变为1(Expanded),其余节点从undefined变为1(Expanded)

2013777645:0 => 1

2118369458:未定义 => 1

368241412:未定义 => 1

1860836078:未定义 => 1

1979885541:未定义 => 1

1316570423:未定义 => 1

360484732:未定义 => 1

506271756:未定义 => 1

现在,在点击全部折叠后,日志中只出现根,将值从 1(展开)更改为 0(折叠)。

2013777645:1 => 0

最后,如果我们现在再次点击Expand All,会出现与之前完全相同的日志,即使其他节点不应该为 treeStatus 设置未定义的值,因为它之前已被赋值.

2013777645:0 => 1

2118369458:未定义 => 1

368241412:未定义 => 1

1860836078:未定义 => 1

1979885541:未定义 => 1

1316570423:未定义 => 1

360484732:未定义 => 1

506271756:未定义 => 1

你能帮我理解我遗漏了什么吗? 我真的希望你能从这个解释中理解这个问题。 提前致谢!

解决方法

看起来你用 ngIf 隐藏了子节点。当 ngIf 为 false 时,您的组件(或模板)不仅被隐藏,而且被销毁。您可以找到更多详情here

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。