将 BehaviorSubject 值作为参数传递

Pass BehaviorSubject value as parameter

我有一个 Angular 组件,其 BehaviourSubject 初始化为当前月份:

textLabel: string;

private monthIndex$: BehaviorSubject<number>;

private MONTHS = [
"Gennaio",
"Febbraio",
"Marzo",
"Aprile",
"Maggio",
"Giugno",
"Luglio",
"Agosto",
"Settembre",
"Ottobre",
"Novembre",
"Dicembre"
];

constructor(private listService: ShoppingListService) {}

ngOnInit() {
  this.monthIndex$ = new BehaviorSubject<number>(new Date().getMonth());

  // Like this it does not display the label
  this.setMonthLabel(this.monthIndex$.value); 

  this.model$ = this.monthIndex$.pipe(
    switchMap((monthValue: number) => {
      //    this.setMonthLabel(monthValue);  // This way it works!
      return this.listService.getHistoryChartModel(monthValue);
    }),
    takeUntil(this.destroy$)
  );
}

private setMonthLabel(monthIndex: number) {
  this.textLabel = this.MONTHS[monthIndex];
}

setMonth(direction: number) {
  let monthIndex = this.monthIndex$.getValue();
  monthIndex += direction;
  monthIndex =
  monthIndex < 0 ? 0 : monthIndex > 11 ? 11 : monthIndex;

  this.monthIndex$.next(monthIndex);
  this.setMonthLabel(monthIndex);
}

和模板:

<div class="view-sel-container">
  <button
   color="primary" mat-icon-button
   (click)="setMonth(-1)"
   [disabled]="monthIndex === 0">
  <i class="material-icons">
    keyboard_arrow_left
  </i>
 </button>

 <span class="label-text" *ngIf="textLabel">{{ textLabel }}</span>

 <button
  color="primary" mat-icon-button
  (click)="setMonth(1)"
  [disabled]="monthIndex === 11">
  <i class="material-icons">
    keyboard_arrow_right
  </i>
 </button>

将BehavourSubject值传递给方法this.setMonthLabel(this.monthIndex$.value),标签没有显示在模板中,是否是时间原因?

更新

Deborah Kurata 使用 get/set 而不是 BehaviourSubject 提供的解决方案是最好的方法。我让原来的 question/code 保持打开状态,因为我仍然不明白为什么代码现在可以通过将 behaviorSubject 值作为参数传递来工作。

this.monthIndex$ = new BehaviorSubject<number>(new Date().getMonth());

  // Like this it does not display the label
  this.setMonthLabel(this.monthIndex$.value); 

  this.model$ = this.monthIndex$.pipe(
    tap(monthValue => {
      this.setMonthLabel(monthValue);
      return this.listService.getHistoryChartModel(monthValue);
    }),
    takeUntil(this.destroy$)
  );
  1. 你应该使用 tap 来处理任何有副作用的事情。
  2. 我不知道为什么你需要使用 this.setMonthLabel(this.monthIndex$.value),当你的管道中已经有了值?
  3. this.setMonthLabel 是做什么的?

考虑使用这样不需要 SubjectBehaviorSubject 的东西:

组件

import { Component } from '@angular/core';
import { Observable } from 'rxjs';

@Component({
  templateUrl: './history-chart.component.html'
})
export class HistorChartComponent {
  textLabel: string;
  model$: Observable<any>;

  private _monthIndex: number;
  get monthIndex(): number {
    return this._monthIndex;
  }
  set monthIndex(value: number) {
    console.log("setter called with: " + value);
    // Set the label
    this.setMonthLabel(value);
    // Get the data
    this.getMonthData(value);
    this._monthIndex = value;
  }

  private MONTHS = [
    "Gennaio",
    "Febbraio",
    "Marzo"
  ];

  constructor() { }

  ngOnInit() {
    // This calls the setter
    this.monthIndex = new Date().getMonth();
  }

  // Increment or decrement the month index
  // This calls the setter
  setMonth(value: number) {
    this.monthIndex += value;
  }

  private setMonthLabel(monthIndex: number) {
    this.textLabel = this.MONTHS[monthIndex];
  }

  private getMonthData(monthIndex: number): void {
    // Commented out because I don't have the service code
    //this.model$ = this.listService.getHistoryChartModel(monthIndex);

    // Faking out the call to the service
    this.model$ = of(
      { id: 1, value: "some data for month : " +  this.MONTHS[monthIndex] },
    );
  }
}

每次用户更改值或在代码中更改值时,都会自动调用setter。所以 setter 是执行任何需要响应更改的代码的好地方。

使用上面的代码,当用户每次单击任一按钮时,都会在 ngOnInt 上检索该月的数据。如果您在提供的 stackblitz 中没有看到这种行为,请告诉我。

模板

<div class="view-sel-container">
    <button
   color="primary" mat-icon-button
   (click)="setMonth(-1)"
   [disabled]="monthIndex === 0">
  <i class="material-icons">
    keyboard_arrow_left
  </i>
 </button>

 <span class="label-text" *ngIf="textLabel">{{ textLabel }}</span>

 <button
  color="primary" mat-icon-button
  (click)="setMonth(1)"
  [disabled]="monthIndex === 11">
  <i class="material-icons">
    keyboard_arrow_right
  </i>
 </button>

<div>
<span class="label-text" *ngIf="textLabel">
 {{textLabel}}
</span>
</div>
<div *ngIf="(model$ | async) as model">
  <div>
  {{ model.value }}
  </div>
</div>

这是相关的 stackblitz:https://stackblitz.com/edit/angular-bpusk2