如何使用可观察对象检查 ngFor 循环中的 属性

How to check a property in an ngFor loop using an observable

存在从 API 返回的卡片对象列表。

其中一张卡应设置为非活动状态。在通过 observable 完成的卡片组件中:

@Component({
  selector: "app-card",
  template: `
    <article [ngClass]="{ inactive: inactive$ | async }">
      <h1>{{ title }}</h1>
    </article>`,
  styleUrls: ["./card.component.css"]
})
export class CardComponent {
  @Input() title: string;

  @Input() inactive$: Observable<boolean>;
}

现在在渲染卡片的组件中需要有一个函数来有条件地检查卡片是否处于活动状态。

./app/app.component.ts

@Component({
  selector: "app-root",
  template: `<app-card
    *ngFor="let card of cards$ | async"
    [title]="card.title"
    [inactive$]="checkIfInactive$(card.inactive)"
  ></app-card>`,
  styleUrls: ["./app.component.css"]
})
export class AppComponent implements OnInit, OnDestroy {
  cards$ = new BehaviorSubject([]);

  ngOnInit() {
    this.cards$.next([
      { title: "Card title 1" },
      { title: "Card title 2", inactive: true }
    ]);
  }

  ngOnDestroy() {
    this.cards$.complete();
  }

  // Each time this function is run, a new behaviorsubject is created? :(
  checkIfInactive$(inactiveCard: boolean) {
    if (inactiveCard) {
      return new BehaviorSubject(true).asObservable();
    } else {
      return new BehaviorSubject(false).asObservable();
    }
  }
}

现在 rxjs 的第一条规则似乎总是 unsubscribe/complete 一个可观察的。函数 checkIfInactive$() returns 每次调用该函数时都会产生一个新的可观察对象。好像不太对。

解决这个问题的正确方法是什么?


工作代码和框:https://codesandbox.io/s/ancient-resonance-6xgv55?file=/src/app/app.component.ts:0-887

您可以将常规输入传递给 app-card 的非活动 属性 而不是 Observable。

  import { Component, Input } from '@angular/core';

  @Component({
    selector: 'app-card',
    templateUrl: './card.component.html',
    styleUrls: ['./card.component.css']
  })
  export class CardComponent {
    @Input() title: string;

    @Input() inactive: boolean;

  }

还有.html

<article [ngClass]="{ inactive: inactive }">
  <h1>{{ title }}</h1>
</article>

通过此更改,您将能够解决您的工作场景。

此外,如果除了在模板中显示值之外,您还需要对 Inputs 的更新做出反应并在组件中执行其他操作,您可以使用 OnChanges 生命周期挂钩并观察 inactive 的值。

  @Component({
    selector: 'app-card',
    templateUrl: './card.component.html',
    styleUrls: ['./card.component.css']
  })
  export class CardComponent implements OnChanges {
    @Input() title: string;

    @Input() inactive: boolean;

    ngOnChanges(changes: SimpleChanges): void {
      if (changes.inactive?.currentValue) {
        // Do your thing
      } else {
        // Do something else
      }
    }
  }

小心将 Observable 作为输入传递。 在这种情况下,您必须注意一些事项。

从我的角度来看,最重要的是,为了从 Observable 中获取值,您可以使用 | async 订阅或反映模板上的值。如果你只想在模板上反映值,你可以使用 | async,但如果是这种情况,你可以简单地将值作为输入传递,而不是首先使用 Observable。 另一方面,如果您需要对 Observable 发出的值做其他事情,您必须订阅它,为此您还需要使用 OnChanges 生命周期钩子,以确保您正在处理如果您的输入发生变化。

旁注:对象和数组等可观察对象通过引用传递,因此您必须确保在输入中提供新引用以检测更改。