我的情况很简单。有两个字段的html表单:
我希望
lastName
在用户更改firstName
时有所改变。我通过Angular(8)中可观察到的valueChanges实现了它。此外,我有两个订阅来监听和记录更改:
lastName
这是它的实现方式:
ngOnInit(){
this.form = new FormGroup({
firstName: new FormControl('', {updateOn: 'blur'}),
lastName: new FormControl('', {updateOn: 'blur'}),
});
this.form.get('lastName').valueChanges.subscribe(value => console.log('lastName', value));
this.form.valueChanges.subscribe(value => console.log('Value', value));
this.form.get('firstName').valueChanges
.subscribe(firstName => {
this.form.get('lastName').setValue(`firstName ${firstName} ${new Date().getMilliseconds()}`);
});
}
通常,从用户的角度来看,这的行为符合预期。用户更改
firstName
,然后lastName
自行更改。但是,当我查看控制台日志时,这是我得到的:
lastName firstName test 850
Value > {firstName: "test", lastName: "firstName test 850"}
Value > {firstName: "test", lastName: "firstName test 850"}
我希望从整体上得到两个日志,但是一个名字更改了,第二个姓氏更改了。
像这样:
Value > {firstName: "test", lastName: ""}
lastName firstName test 850
Value > {firstName: "test", lastName: "firstName test 850"}
这是stackblitz的完整示例。
好的,所以当我改变一种方式时,从这里更新
lastName
:this.form.get('lastName').setValue(`firstName ${firstName} ${new Date().getMilliseconds()}`);
对此:
setTimeout(() => this.form.get('lastName').setValue(`firstName ${firstName} ${new Date().getMilliseconds()}`));
然后按照我期望的顺序进行日志:
Value > {firstName: "test", lastName: ""}
lastName firstName test 850
Value > {firstName: "test", lastName: "firstName test 850"}
但是,
setTimeout
在这里似乎很棘手。这是stackblitz的完整代码。
问题是:
这里发生了什么?为什么FormGroups以这种方式工作?
是否有一种模式可以在Angular中处理此类事件(当一种形式影响另一种形式时)?
最佳答案
这就是事件循环的工作方式
两种情况都发生了什么:
没有setTimeout
firstName.valueChanges
已添加到EventLoop
队列EventLoop
运行并调用操作firstName.valueChanges
lastName.setValue
称为lastName.setValue
将lastName.valueChanges
和form.valueChanges
添加到eventLoop队列lastName.valueChanges
将form.valueChanges
添加到eventLoop队列lastName.valueChanges
已出列form.valueChanges
(来自lastName.valueChanges
)已出队form.valueChanges
(来自firstName.valueChanges
)已出队使用setTimeout
firstName.valueChanges
已添加到EventLoop
队列EventLoop
运行并调用操作firstName.valueChanges
setTimeout(lastName.setValue)
未调用,但已添加到事件循环队列firstName.valueChanges
将form.valueChanges
添加到事件循环队列setTimeout
出队,他设置lastName
值并将lastName.valueChanges
添加到tevent循环队列form.valueChanges
(来自firstName.valueChanges
)已出队lastName.valueChanges
出队,并将form.valueChanges
添加到事件循环队列form.valueChanges
(来自lastName.valueChanges
)已出队