在 Angular 中将数据从子级传递给具有 n 个子级的父级,而不会沿途在每个组件中发出

Passing data from children to parent with n children in Angular without emiting in each component along the way

如果我在 Angular 中有这个组件层次结构:

组件 F 中发生了一些 B 应该知道的事情。 我可以做到的一种方法是在 F 中使用 emit() 并将其传递到 A,但这将需要我在 each 组件 E、D 和C,即使他们不关心也不应该关心正在发出的数据 - 所以在 F 中我会写

export class F .... {
  ...

  @Output() emitterName: EventEmitter<any> = new EventEmitter<any>();

  doSomething(data) {
   ...
   this.emitterName.emit(data);
  }
  ...
}

那么,class E 应该像 <app-f-selector (emitterName)="setData($event)"><app-f-selector/>

那样调用 F

并且在 E 中,我应该创建一个新函数 setData(),它只将事件发送到 D:

export class E .... {
  ...

  @Output() emitterName: EventEmitter<any> = new EventEmitter<any>();

  setData(data) {
   ...
   this.emitterName.emit(data);
  }
  ...
}

现在我应该对 D 和 C 做同样的事情。 这看起来真的很糟糕,在没有代码重复的情况下,Angular 中是否有一些优雅的方法可以将数据从子组件向上传递到父组件? 类似于 React context?

类似这样的东西(未检查,但作为指南):

export class MySharedService {

  private data$ = new Subject<any>();
  public setData(data: any) {
      this.data$.next(data);
  }
  public getData(): Observable<any> {
      return this.data$.asObservable();
  }
}

然后在任何需要此数据的组件中,通过构造函数注入并订阅更改:

this.mySharedService.getData().subscribe(data => ...do something here);

如果您确定您可能只有一个 parent 类型为“A”,您可以在 children 中注入并直接调用它。

export class F {
  constructor(
    private parentA: AComponent
  ){}

  setData(data) {
   this.parentA.doSomething(data);
  }
}

但我不推荐这样的结构,因为这会使组件 F 与组件 A 紧密耦合。在我们的项目中,我们仅使用这种方法来实现动态生成的自定义 UI 组件。

您可以使用共享服务来做到这一点。

// shared.service.ts
export class SharedService  {
  private updateComp = new Subject<any>();
  public updateComp$ = this.updateComp.asObservable();
    
    public updateComponent(data: any) {
    this.updateComp.next(data);
  }
}

// C OR D Component .ts enject sharedService in constructor
ngOnInit() {
    this.sharedService.updateComp$.subscribe((res: any) => {
    //you code...
    });
}

// F Component .ts call share service method i.e.
this.sharedService.updateComponent({ you data});