阅读How to use RxJs distinctUntilChanged?和this,似乎distinctUntilChanged
会改变输出流,只提供不同的连续值。
我认为这意味着如果相同的值立即连续到达,那么您实际上是过滤流并且只获得该重复值的一次出现。
所以,如果我写这个:
this.myFormControl.valueChanges
.debounceTime(1000)
.distinctUntilChanged()
.subscribe(newValue => {
console.log('debounced: ', newValue);
});
我认为输出与此没有区别:
this.myFormControl.valueChanges
.debounceTime(1000)
.subscribe(newValue => {
console.log('debounced: ', newValue);
});
我看到有几个地方建议在表单输入上订阅distinctUntilChanged
时使用valueChanges
- 但实际上并不明白为什么。
这是一个输入,所以如果用户输入它总是在变化,对吧?这些值将始终是不同的,因此您只需添加额外的操作来无缘无故地过滤输入。
或者我在这里遗漏了什么?
修改
根据我的第一个代码示例使用distinctUntilChanged
,我创建了一个值为Mr Trump
的表单输入,并确保将其保存在模型中。
然后我在控件内部单击并粘贴Mr Trump
。由于值是相同的,我原本不希望看到任何记录 - 控件具有与之前相同的值,所以distinctUntilChanged
肯定应该忽略它?
编辑2
在进一步查看我的测试之后,这种行为似乎是因为我使用了AbstractControls
的数组:
this.itemsControl = <FormArray>this.form.controls['items'];
...
this.itemsControl.controls[index].valueChanges...
所以虽然有点奇怪,当输入值相同时它仍然会触发,我猜我需要连接到这个数组项(表单组)中实际输入的valueChanges
,并且不是数组项本身。
编辑3
因此,在将EDIT 2中的代码更改为以下内容后,将已存在的相同值粘贴到输入控件中不会触发valueChanges
(如预期的那样)。在编辑2中valueChanges
被挂钩到整个formGroup
,而不是单个输入控件(在本例中称为content
):
let fg = this.itemsControl.controls[index]; // get the formGroup
fg['controls'].content.valueChanges
.debounceTime(1000)
.distinctUntilChanged()
.subscribe(newValue => {...});
答案 0 :(得分:7)
distinctUntilChanged
应用于表示完整表单的valueChanges
可观察对象根本没有用!
它仅适用于单个值(如您所说)。
要跟踪整个表单的更改,您需要编写一个自定义比较器,最简单的方法是使用JSON.stringify
输出可以比较的值。除非您提供比较器功能,否则valueChanges
的Observable会发出一个对象,并且distinctUntilChanges
不够聪明,无法执行reference compare之外的任何事情。
this.form.valueChanges.pipe(distinctUntilChanged((a, b) => JSON.stringify(a) ===
JSON.stringify(b)))
.subscribe(changes => { console.log('The form changed!'); });
distinctUntilChanged
可以很好地用于具有原始类型的单个值,因为===
足以检测更改。
如果您试图将distinctUntilChanges
塞入管道(针对整个表单)以避免无限循环,则实际上可能需要这样做:
this.form.patchValue(address || {}, { emitEvent: false });
答案 1 :(得分:5)
使用debounceTime(1000)
表示我们只在用户停止输入1秒钟时发送请求,在此期间用户可以写入3个字符然后擦除它们,因此输入值自上次请求后没有改变但是你发送相同的请求,以避免您使用.distinctUntilChanged()
this.myFormControl.valueChanges
.debounceTime(1000)
.distinctUntilChanged()
.subscribe(newValue => {
console.log('debounced: ', newValue)
});