Angular: 我怎样才能像往常一样从几个可观察数组中收集数据?

Angular: How can I collect data from a few observable as usual array?

我需要做下一个 - 从后端获取数据并将其转发到 child 组件:

...

@Component({
  selector: 'my-component',
  template: `<my-child-component [data]="data"></my-child-component>` 
})

public data = [];

ngOnInit() {
  this.service.getParentData().subscribe(res =>  {
    res.map(r => this.service.getChildDatas(r.id)
      .subscribe(child => this.data.push(child)));
  });
}

但是在 child 组件中,当我尝试在 ngOnChanges 中打印数据时,我只看到奇怪的数组,我可以看到元素,但长度等于 0:

它是如何工作的以及如何实现我的 objective(将数据传递给 child 并像处理数组一样处理数据)?

您似乎有 2 个要通过管道传输的可观察对象,一个接一个。 您需要使用 rxJS operators 来实现。

实现它的方法是使用运算符 switchMap 或 mergeMap,具体取决于您是否希望将第一个更改为 re-trigger 第二个。

然后使用 forkJoin 运算符,以列表形式订阅可观察和威胁结果列表

假设您首先收到一个数组,并且需要每个数组值通过您将拥有的另一个服务获取子项

ngOnInit() {
  this.service.getParentData()
          .pipe(switchMap((parentData: {id: string}[]) => {
                 return forkJoin(parentData.map(r => 
                     this.service.getChildDatas(r.id))
                 })
      .subscribe((childData: any[]) => {this.data = childData});
}

ngOnChange - 当指令的任何 data-bound 属性 更改时调用的生命周期挂钩。

在这里你绑定了一个数组,它被视为 object.That 意味着当你发送新对象时 ngOnChange 将被触发,在我们的例子中是一个新数组(意味着新引用id).

Angular 使用相等检查运算符 === 来检测指令的输入何时更改。 === 运算符检查它正在检查的对象中的引用更改。

在这里您更改的是对象的内容,而不是对象引用。

ngOnChange 将被触发,对于任何类型的对象,当有引用更改时意味着新对象。

所以第一个解决方案是

ngOnInit(){
this.service.getParentData().subscribe(res =>  {
    res.map(r => this.service.getChildDatas(r.id)
      .subscribe(child => {
        this.data.push(child);
        this.data = [...this.data]; // It will re assign new instance 
          data(Array) on every push
      }));
  });
} 

但我会建议您在这里稍微优化一下代码,例如

ngOnInit(){
  this.service.getParentData().pipe(
    concatMap((res) => this.service.getChildDatas(res.id))
  ).subscribe({
     next: (res) => {
       this.data.push(res);
       this.data = [...this.data];
     },
  });
} 

第二个解决方案 通过将自定义对象与 angular trackBy 绑定。 angular 将通过 trackBy 索引而不是对象引用来比较对象的相等性,这也会提高性能。

<my-child-component [data]="{trackBy:data.length,data:data}"></my-child-component>
ngOnChanges(changes: SimpleChanges): void {
   console.log(changes.data.currentValue.data);
}

更新:
您使用了 .push,所以我假设您正在接收单个数据,但是如果您正在接收一个数组,那么您可以将 res 数组分配给 this.data,通过这样做,您每次都在更改引用

ngOnInit(){
      this.service.getParentData().pipe(
        concatMap((res) => this.service.getChildDatas(res.id))
      ).subscribe({
         next: (res) => {
           this.data = res;
         },
      });
    } 

再来一个Update

当您可能要处理同时更改的多个属性,或者希望对多个属性执行某些操作时,请使用 ngOnChanges

但是如果你想处理特定的 属性 变化,那么更好的选择是使用 setter 和 @Input

@Input() set data(data:any[]){
    console.log(data);
  };

我觉得这个博客很有帮助Detecting @​Input changes in Angular with ngOnChanges and Setters