Angular *ngIf 多次调用,使用异步管道和订阅

Angular *ngIf called multiple times, using async pipe and subscribe

我当前的 angular 设置遇到了问题,我无法弄清楚到底出了什么问题。 在解决问题之前,我先描述一些上下文。

我有一个 class - data-service.ts,里面有一个方法“getData”。这是正文:

getData(): Observable<Data[]> {
let params = new HttpParams();
params = params.append('user_id', this.userId);
return this.http.get<Data[]>('api/data', {
  observe: 'body',
  responseType: 'json',
  params
}).pipe(
    map((response: any[]) => {
      return response.map((s) => ({
        id: s.id,
        userId: s.user_id,
        type: s.type_id,
        ...
      }));
    })
);}

我的要求是每次用户在 ngModal 中输入目标选项卡时获取此数据并刷新视图。 当您单击该目标选项卡时,模态组件“modal-component.ts”会获取此数据。单击选项卡会触发一个事件,通过这段代码:

getData(evt) {
  this.data$ = this.dataSevice.getData();
}

我正在使用异步管道将这个“data$”可观察对象传递给子组件:

<modal-component>
...
    <app-data-manager [data]="data$ | async"></app-data-manager>
...
</modal-component>

在“数据管理器”内部,我在 [data] 上使用 *ngFor,并且我正在为每个数据渲染一些 html。在那个 HTML 中,我使用 *ngIf 来确定应该渲染哪个模板,第一个还是第二个。

<div *ngIf="isTrue(dataEntry); then first else second"></div>

问题是: 为每个数据条目调用 isTrue 方法,这很好,但它会为整个数据集调用多次。像百倍。我尝试使用 promises,使用 Take(1) 管道,在映射期间分配布尔值(ngIf 用来选择模板的那个),在订阅内部分配数据并传递普通集合而不是使用异步管道。我不知道这是造成这种情况的原因-我感谢您对此的所有帮助。谢谢!

附加信息 当我在 *ngIf 中使用 dataEntry.isTrue 而不是 isTrue(dataEntry) - 我仍然得到相同的结果。我还在带有控制台日志的子组件中添加了“OnChanges”——第一次点击它记录到控制台一次,第二次点击它记录到控制台两次。出现两条相同的消息。

问题是您在 angular 表达式中使用函数调用。不要这样做。

[T]he isTrue() function is executed every time Angular change detection runs. And that can be many times!

Because Angular cannot predict whether the return value of isTrue() has changed, it needs to execute the function every time change detection runs.

这意味着整个应用程序(包括 app-data-manager 组件外部)的任何更改检测都将导致 isTrue() 执行。

这篇文章讲的比较多:https://medium.com/showpad-engineering/why-you-should-never-use-function-calls-in-angular-template-expressions-e1a50f9c0496

一种解决方案是使用属性而不是函数。如果您想结束复杂的逻辑,请选择像这样制作自定义管道。

*ngIf="(dataEntry | isTruePipe); then first else second"></div>