正如@jonrsharpe 指出的那样,就目前的情况而言,您的 observable 只会发出一个值。听起来您想要的是一种在currentSheetNumber 更改时通知订阅者的方法。这是一种可能性,分两步。首先,按照@jonrsharpe 的建议,让我们从您的服务中公开Subject(这是一种特殊的可观察对象):
public currentSheetNumber$ = new Subject();
那么,在 B 类:
ngAfterViewInit() {
this.sheetNumberObserver = this.measurementDataService.currentSheetNumber$.subscribe((sheets) => {
this.sheetNumber = sheets;
});
}
此时,每当一个值“下一个”到 currentSheetNumber$ 主题上时,this.sheetNumber(在 B 类中)都会相应地更新。
但是,目前,currentSheetNumber$ 主题与您的currentSheetNumber 变量(在您的服务中)没有任何关联。也就是说,当您更改currentSheetNumber 时,currentSheetNumber$ 没有任何反应。我们需要将这两者“绑定”在一起,以便currentSheetNumber 的更新由currentSheetNumber$ 发出。
一种方法是添加一个特殊的方法来分配currentSheetNumber,并且仅使用该方法修改这个变量。在这个方法中,我们可以更新currentSheetNumber 和 将新值发送给我们主题的订阅者:
setCurrentSheetNumber(value: number) {
// Update the value of `currentSheetNumber`...
this.currentSheetNumber = value;
// ...and send the new value to subscribers of `currentSheetNumber$`
this.currentSheetNumber$.emit(value);
}
这需要您将任何对currentSheetNumber 的分配替换为对setCurrentSheetNumber 的调用。
这应该可行,但它涉及遵循我们无法强制执行的规则(不是对变量进行“直接”分配)。这是难以诊断的错误的潜在来源。
幸运的是,有一种方法可以稍微调整当前设置,以提供更简单的体验。我们可以用一对“getter/setter”方法替换currentSheetNumber变量。这将允许我们在分配给currentSheetNumber 时添加额外的“下一个”逻辑,而不必担心调用单独的方法:
get currentSheetNumber(): value {
// What goes here?
}
set currentSheetNumber(value: number) {
this.currentSheetNumber$.next(value);
}
现在,每当进行像 this.currentSheetNumber = 42 这样的赋值时,新值(在本例中为 42)将发送给 currentSheetNumber$ 的所有订阅者。我们快到了。
我们需要解决的最后一个问题是:既然我们已经用 getter/setter 对替换了 currentSheetNumber,那么我们实际上在哪里存储这个值?我们有几个选择。一种是添加另一个变量,比如_currentSheetNumber,我们用它来维护当前值,但我们从不直接与之交互。看起来像这样:
_currentSheetNumber = 0;
get currentSheetNumber(): number {
return this._currentSheetNumber;
}
set currentSheetNumber(value: number) {
this._currentSheetNumber = value;
this.currentSheetNumber$.next(value);
}
这不仅增加了我们现在需要考虑的额外变量,而且我们又回到了必须遵守与以前类似的分配规则:我们需要永远分配给_currentSheetNumber直接地。必须有更好的方法。
有。我们需要做的就是使用BehaviorSubject 而不是仅仅使用Subject。 BehaviorSubject 就像一个主题,但它“记住”它的当前值,可以通过它的 getValue 方法访问。看起来是这样的:
public currentSheetNumber$ = new BehaviorSubject(0);
get currentSheetNumber(): number {
return this.currentSheetNumber$.getValue();
}
set currentSheetNumber(value: number) {
this.currentSheetNumber$.emit(value);
}
应该这样做,但有一个重要的警告可能会导致错误和挫败感。 BehaviorSubject 在订阅时会发出其当前值。在许多情况下,这可能不是您想要的,并且可能会迫使您添加一些杂项(例如跳过订阅中的第一个发射值等)。在这种情况下,您最好使用_currentSheetNumber 策略,尽管它有缺陷。
(或者,您可以直接与 currentSheetNumber$ 行为主体交互并避免这种情况,或编写一个保持其当前状态的自定义主体,但不会将其发送给新订阅者)