首页 > 解决方案 > 角度的动态组件订阅

问题描述

我正在通过ngFor循环渲染一些动态组件,我希望这些组件能够相互通信。我这样做的第一个想法是从辅助状态服务(myComunicationService )订阅一些主题更改:

HTML

<div *ngFor="let entry of dataList">
    <custom-component [entry]="entry"/>
</div>

自定义组件 ts

export class CustomComponent implements OnInit {
  @Input() entry: Entry;

  private subscriptions: Subscription = new Subscription();

  constructor(private myComunicationService: MyComunicationService) {}

  public ngOnDestroy(): void {
    this.subscriptions.unsubsribe();
  }

  public ngOnInit(): void {
    this.subscriptions.add(
      this.myComunicationService.dataChanged$.subscribe(
        (dataChanged) => {
          if (isForThisComponentInstance(dataChanged)) {
            // do stuff for this component instance only
          }
        }
      );
    );
  }

  // private isForThisComponentInstance = (dataChanged) => boolean
  // this method checks some unique property that matches with the instance component

}

所以基本上我所有的组件都在监听同一个事件,它们都在捕捉那个事件,并且if { }语句是某种过滤器,它实际上允许组件改变/做事情。(对这种方法不太满意)

如何改进这一点而不依赖于 if 语句?

标签: angularrxjs

解决方案


而不是使用

this.myComunicationService.dataChanged$直接在您的组件中,您可以要求服务为您做一些额外的工作。

this.myComunicationService.getChangesFor(this)

然后为您服务

getChangesFor(compy: CustomComponent): Observable<any>{
  return this.dataChanged$.pipe(
    filter(data => data.id === compy.id)
  );
}

这实际上是同一件事,但是从可能不属于它的组件中删除了逻辑。这样如果 10 个不同的组件都调用这个服务,它们就不会都单独实现这个逻辑。它还使您可以自由更改通信服务处理问题的方式。

例如:

  1. 您可以为每个组件创建一个新的主题/重播主题(例如,将它们推入一个数组)。然后,不要过滤,只针对您知​​道(或可能)需要数据的组件。
  2. 您可以定义与组件无关的命名法和/或接口,它决定哪些类型的数据适合过滤。

然而,在某些时候,哪些数据去哪里的逻辑取决于你。


推荐阅读