首页 > 解决方案 > 在这种特殊情况下使用 async-pipe 而不是 subscribe() 真的更好吗?

问题描述

在我的组件中,我得到一个 Observable 作为@Input()。

如果 Observable 的值发生变化,我必须展开/折叠 ng-bootstrap 手风琴。所以我真的不需要模板中的 Observable 值。

这是代码,我已经有了:

零件:

@Input() urlParam$!: Observable<string>;

@ViewChild('acc') accordion!: NgbAccordion;

urlParamChange$!: Observable<string>;

ngAfterViewInit(): void {
  this.urlParamChange$ = this.urlParam$.pipe(
    tap(urlParam => this.synchronizeAccordion(urlParam))
  );
}

synchronizeAccordion(urlParam: string): void {
// do something with this.accordion
}

在模板中,我通过异步管道订阅了新创建的 urlParamChange$:

<ng-container *ngIf="(urlParamChange$ | async)"></ng-container>

<ngb-accordion #acc="ngbAccordion">
 ....
</ngb-accordion>

由于我真的不需要 urlParamChange$ 的值,所以我把它放在一个自己的 ng-container 中,这样完全独立,但仍然会调用同步手风琴的方法。

我认为,上述实现并不是那么好。您将操作拆分为两个不同的文件(需要组件中的点击 + 模板中的异步管道)。

下面的方式不是更好吗?我不会在异步管道的帮助下订阅,而是直接在 ngAfterViewInit() 中订阅()。这样,我可以删除附加变量 urlParamChange$ 并且实现全部在 ngAfterViewInit() 方法中。

零件:

@Input() urlParam$!: Observable<string>;

@ViewChild('acc') accordion!: NgbAccordion;

ngAfterViewInit(): void {
  this.urlParam$.subscribe(urlParam => this.synchronizeAccordion(urlParam));
}

synchronizeAccordion(urlParam: string): void {
// do something with this.accordion
}

在模板中,额外的 ng-container 被移除:

<ngb-accordion #acc="ngbAccordion">
 ....
</ngb-accordion>

在我看来,这两种实现都应该以完全相同的方式工作。根据最佳实践,我认为应该首选第一个解决方案。但第二个是更清洁的 IMO。

那么实现这种用例的最佳方法是什么?

标签: angulartypescriptrxjs

解决方案


我建议您采用方法 2。通过您自己的录取,它似乎更清晰,更容易遵循。

想象一下将来有人出现,他们看到一个ng-container带有async绑定但没有内容的随机数。假设不再使用它,他们很可能决定将其删除,在这种情况下,您的整个tap操作将不再运行,并且不会抛出任何错误来提醒您这一点。

而通读方法 2 的人可以很容易地看到正在发生的事情,并且修改订阅的结果是显而易见的。

手动取消订阅并没有错,您只需要确保您这样做!


推荐阅读