Angular BehaviorSubject意外行为:不使用Next()进行更改

时间:2018-01-10 22:17:52

标签: angular rxjs behaviorsubject

我在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的工作原理但是如果有人能告诉我哪里出错了,我真的很感激:\谢谢你!

1 个答案:

答案 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;