我在Angular中的BehaviorSubject有一些意想不到的“行为”。当我的应用加载时,我得到一堆对象(状态)并将它们设置为可观察的:
public statuses$ = new BehaviorSubject<any>(null)
public getStatuses(): Promise<any> {
return this.http.get<any>(this.url, { headers: this.headers })
.toPromise()
.then(res => {
this.statuses$.next(res);
return res;
});
}
在我的组件中,我在ngOnInit期间订阅并将其分配给变量,以便我可以在我的模板中使用它:
ngOnInit() {
this.appointmentStatusesService.statuses$.subscribe(statuses => {
this.statuses = statuses;
});
}
足够简单。我正在做的简短版本:我在我的HTML模板w / ngFor中循环遍历这些状态。用户单击状态,并通过表单显示状态。 (这是用户点击状态时使用的功能):
public viewStatus(seqNo: number) {
const statuses = this.appointmentStatusesService.statuses$.getValue();
for (let x = 0; x < statuses.length; x++) {
if (statuses[x].seqno === seqNo) {
this.currentStatus = statuses[x];
break;
}
}
}
现在,我遇到的问题是对表单所做的任何更改,也会更改状态$ observable,即使我没有调用.next()。这就是我的表单:
<input type="text" class="form-control" [(ngModel)]="currentStatus.name">
不知何故,当更改currentStatus的名称(在用户单击“VIEW STATUS”时分配)时,它也会更改状态$ observable。换句话说,对currentStatus对象所做的任何更改也会对状态进行更改$ observable。好像存在某种双向绑定。我的印象是,为了将更改推送到BehaviorSubject,你必须调用.next()方法。我可能误解了BehaviorSubject的工作原理但是如果有人能告诉我哪里出错了,我真的很感激:\谢谢你!
答案 0 :(得分:1)
我认为问题在于:
this.currentStatus = statuses[x];
因此,您只复制状态的引用,因此如果您编辑currentStatus,则还要编辑列表中的状态。你可以尝试的第一件事是创建一个像这样的新对象
this.currentStatus = { ...statuses[x] };
我的一般建议是重写一点,以避免订阅和太多的本地状态。我已经使用虚拟数据完成了它并且工作正常并且非常简单:
// template
<p *ngFor="let s of statusses$ | async" (click)="statusClicked(s)">{{ s }}</p>
<input type="text" class="form-control" [(ngModel)]="currentStatus">
// script
statusses$ = new BehaviorSubject(['status1', 'status2', 'status3']);
currentStatus: string;
statusClicked = (s: string) => this.currentStatus = s;