You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular mat-tree数据源更新时自动折叠问题如何解决

问题原因

你自定义的expanded属性不会被mat-tree识别,组件的展开折叠状态统一由treeControl维护,和节点自身挂载的属性没有关系。另外你每次接口返回后直接全量替换this.dataSource.data,会导致Angular重新渲染所有树节点,之前保存的展开状态会被全部重置,默认回到折叠状态。

修复方案
  • 废弃自定义的节点expanded属性,所有展开/折叠状态判断、操作都通过treeControl提供的方法完成,不要自行维护节点展开状态。
  • 加载子节点数据时不要全量替换整个数据源,针对当前点击的父节点做局部数据更新,保留原有节点的对象引用,避免状态丢失。
  • 子节点数据渲染完成后,主动调用treeControl的展开方法标记当前节点为展开状态。

修复后的TS代码

// 确认treeControl初始化逻辑正确,扁平树初始化参考如下
treeControl = new FlatTreeControl<ZipFilesFlatNode>(
  node => node.level,
  node => node.hasChild
);

toggleNode(node:ZipFilesFlatNode){
  // 直接通过treeControl判断当前节点展开状态
  const isExpanded = this.treeControl.isExpanded(node);
  if (isExpanded) {
    this.treeControl.collapse(node);
    return;
  }

  node.isLoading = true;
  this.api.getRunFile(url).subscribe((res)=>{
    node.isLoading = false;
    // 扁平树场景:找到当前节点位置,将子节点插入到节点后方,不替换全量数据
    const nodeIndex = this.dataSource.data.indexOf(node);
    const updatedData = [...this.dataSource.data];
    updatedData.splice(nodeIndex + 1, 0, ...res.data);
    this.dataSource.data = updatedData;
    // 主动标记当前节点展开
    this.treeControl.expand(node);
  },err=>{
    node.isLoading = false;
  })
}

修复后的HTML代码

<mat-tree [dataSource]="dataSource" [treeControl]="treeControl">
  <mat-tree-node *matTreeNodeDef="let node" matTreeNodePadding>
    <button mat-icon-button disabled></button>
    {{node.name}}
  </mat-tree-node>
  <mat-tree-node *matTreeNodeDef="let node; when: hasChild" matTreeNodePadding>
    <button mat-icon-button
            [attr.aria-label]="'Toggle ' + node.name"  (click)="toggleNode(node)">
      <mat-icon class="mat-icon-rtl-mirror">
        <!-- 统一用treeControl判断展开状态 -->
        {{treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right'}}
      </mat-icon>
    </button>
    {{node.name}}
    <mat-progress-bar *ngIf="node.isLoading"
                      mode="indeterminate"
                      class="example-tree-progress-bar"></mat-progress-bar>
  </mat-tree-node>
</mat-tree>

如果使用嵌套树(NestedTreeControl)场景,不需要手动拼接扁平数据列表,直接把接口返回的子节点赋值给当前节点的children属性,再调用this.treeControl.expand(node)即可正常保留展开状态。

内容的提问来源于stack exchange,提问作者Vikash Mishra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 00:31:16