angular material tree 动态加载子项有注释的ts

import { Component, OnInit,Injectable } from '@angular/core';
import {CollectionViewer, SelectionChange, DataSource} from '@angular/cdk/collections';//定义和操作数据源(DataSource)和视图容器(CollectionViewer)以及选择状态的变化(SelectionChange)
import {FlatTreeControl} from '@angular/cdk/tree';//管理扁平节点的展开和折叠状态
import {BehaviorSubject, merge, Observable} from 'rxjs';//创建可观察对象和处理异步数据流
import {map} from 'rxjs/operators';// 从 RxJS 库中导入 map 操作符,用于对可观察对象发出的值进行转换。
// 树组件
export class DynamicFlatNode {//定义了一个 DynamicFlatNode 类,表示一个扁平节点(Flat node),包含可展开状态和层级信息
  constructor(
    public item: string,
    public level = 1,
    public expandable = false,
    public isLoading = false,
  ) {}
}

@Injectable({providedIn: 'root'})//提供服务的装饰器语法。它的作用是将这个服务注册为根注入器的提供者。
export class DynamicDatabase {
  dataMap = new Map<string, string[]>([//定义了一个名为 dataMap 的 Map 对象,用于存储树形结构的数据
    ['Fruits', ['Apple', 'Orange', 'Banana']],
    ['Vegetables', ['Tomato', 'Potato', 'Onion']],
    ['Apple', ['Fuji', 'Macintosh']],
    ['Onion', ['Yellow', 'White', 'Purple']],
  ]);

  rootLevelNodes: string[] = ['Fruits', 'Vegetables'];//定义了一个名为 rootLevelNodes 的数组,其中包含了根节点的名称

  initialData(): DynamicFlatNode[] {//定义了一个名为 initialData 的方法,用于返回初始的树节点数据。在这个方法中,通过遍历 rootLevelNodes 数组创建了一个 DynamicFlatNode 对象的数组,并将其作为初始数据返回。
    return this.rootLevelNodes.map(name => new DynamicFlatNode(name, 0, true));
  }

  getChildren(node: string): string[] | undefined {//定义了一个名为 getChildren 的方法,用于获取指定节点的子节点数组。在这个方法中,通过调用 dataMap.get(node) 方法获取指定节点的子节点数组,并返回结果
    return this.dataMap.get(node);
  }

  isExpandable(node: string): boolean {//定义了一个名为 isExpandable 的方法,用于判断指定节点是否可展开(即是否有子节点)。在这个方法中,通过调用 dataMap.has(node) 方法判断指定节点是否存在于 dataMap 中,若存在则说明该节点有子节点,返回 true,否则返回 false。
    return this.dataMap.has(node);
  }
}
export class DynamicDataSource implements DataSource<DynamicFlatNode> {// 定义了一个名为 DynamicDataSource 的类,它实现了 DataSource 接口,这个接口的泛型参数指定为 DynamicFlatNode,表示这个数据源提供的是 DynamicFlatNode 类型的数据。
  dataChange = new BehaviorSubject<DynamicFlatNode[]>([]);//定义了一个名为 dataChange 的 BehaviorSubject 对象,用于在数据发生变化时向订阅者(subscribers)发送通
  get data(): DynamicFlatNode[] {//定义了一个名为 data 的 getter 方法,用于获取树形结构的数据。在这个方法中,通过访问 dataChange 的值来获取当前的树形结构数据。
    return this.dataChange.value;
  }
  set data(value: DynamicFlatNode[]) {//定义了一个名为 data 的 setter 方法,用于设置树形结构的数据。在这个方法中,首先将传入的新数据赋值给 _treeControl.dataNodes 属性,然后通过调用 dataChange.next() 方法发射新的数据,以通知所有订阅者更新数据。
    this._treeControl.dataNodes = value;
    this.dataChange.next(value);
  }
  constructor(// 定义了一个构造函数,接受两个参数 _treeControl 和 _database,分别表示 TreeControl 对象和数据源对象。在这个构造函数中,将接收到的 _treeControl 对象赋值给组件的 _treeControl 属性,将接收到的 _database 对象赋值给私有属性 _database。
    private _treeControl: FlatTreeControl<DynamicFlatNode>,
    private _database: DynamicDatabase,
  ) {}

  // 实现 DataSource 接口中的 connect() 和 disconnect() 方法
  connect(collectionViewer: CollectionViewer): Observable<DynamicFlatNode[]> {// DataSource 接口中的 connect() 方法,这个方法返回一个 Observable 对象,它用于向 TreeControl 提供数据。
    this._treeControl.expansionModel.changed.subscribe(change => {
      if (
        (change as SelectionChange<DynamicFlatNode>).added ||
        (change as SelectionChange<DynamicFlatNode>).removed
      ) {
        this.handleTreeControl(change as SelectionChange<DynamicFlatNode>);
      }
    });

    return merge(collectionViewer.viewChange, this.dataChange).pipe(map(() => this.data));
  }
  disconnect(collectionViewer: CollectionViewer): void {}// DataSource 接口中的 disconnect() 方法,这个方法在数据源不再需要使用时被调用,可以在这个方法中清理资源。

  handleTreeControl(change: SelectionChange<DynamicFlatNode>) {// Tree中的一个方法,用于处理树形结构的控制变化
    if (change.added) {
      change.added.forEach(node => this.toggleNode(node, true));
    }
    if (change.removed) {
      change.removed
        .slice()
        .reverse()
        .forEach(node => this.toggleNode(node, false));
    }
  }

  toggleNode(node: DynamicFlatNode, expand: boolean) {// Tree中的一个方法,用于展开或关闭树形结构中的一个节点
    const children = this._database.getChildren(node.item);
    const index = this.data.indexOf(node);
    if (!children || index < 0) {
      // If no children, or cannot find the node, no op
      return;
    }
    node.isLoading = true;

    setTimeout(() => {//使用 setTimeout() 方法模拟异步加载,等待 1 秒钟后执行回调函数。在回调函数中,根据需要展开还是关闭节点,进行不同的操作
      if (expand) {
        const nodes = children.map(
          name => new DynamicFlatNode(name, node.level + 1, this._database.isExpandable(name)),
        );
        this.data.splice(index + 1, 0, ...nodes);
      } else {
        let count = 0;
        for (
          let i = index + 1;
          i < this.data.length && this.data[i].level > node.level;
          i++, count++
        ) {}
        this.data.splice(index + 1, count);
      }

      // notify the change
      this.dataChange.next(this.data);
      node.isLoading = false;
    }, 1000);
  }
}


@Component({
  selector: 'app-dynamic-tree-demo',
  templateUrl: './dynamic-tree-demo.component.html',
  styleUrls: ['./dynamic-tree-demo.component.scss']
})//定义组件的装饰器要 紧挨着组件ts 要不要报错
export class DynamicTreeDemoComponent implements OnInit {
  constructor(database: DynamicDatabase) {
    this.treeControl = new FlatTreeControl<DynamicFlatNode>(this.getLevel, this.isExpandable);
    this.dataSource = new DynamicDataSource(this.treeControl, database);

    this.dataSource.data = database.initialData();
  }
  treeControl: FlatTreeControl<DynamicFlatNode>;//表示树形结构的控制器对象,用于管理树形结构的展开和闭合。

  dataSource: DynamicDataSource;//表示树形结构的数据源对象,用于管理树形结构的数据加载。

  getLevel = (node: DynamicFlatNode) => node.level;//一个箭头函数,用于获取节点的级别。

  isExpandable = (node: DynamicFlatNode) => node.expandable;//箭头函数,用于判断节点是否可展开。

  hasChild = (_: number, _nodeData: DynamicFlatNode) => _nodeData.expandable;//函数,用于判断节点是否有子节点。
  ngOnInit(): void {
  }

}

  • 10
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值