每次在FormControl对象上调用valueChanges
函数时,FormControl对象上存在的setValue(value)
Observable都会发出值。
使用RxJS运算符distinctUntilChanged
,我们可以过滤掉不是新的值。但是,如果FormControl具有初始值,则这不起作用。
const formGroup1 = new FormGroup({page: new FormControl(1)});
const formControl1 = formGroup1.get('page');
formControl1.valueChanges.pipe(distinctUntilChanged())
.subscribe(v => console.log(`new formControl1 value: ${v}`));
formControl1.setValue(1);
formControl1.setValue(2);
这是要记录的
> new form1Control value: 1
> new form1Control value: 2
1是valueChanges
Observable发出的第一个值,因为在创建valueChanges
Observable之前设置了formControl1值。
distinctUntilChanged
从未过滤掉第一个发射值
以下是此问题的一种解决方案:
const formGroup2 = new FormGroup({page: new FormControl(1)});
const formControl2 = formGroup2.get('page');
formControl2.valueChanges.pipe(
startWith(1),
distinctUntilChanged(),
skip(1)
).subscribe(v => console.log(`new formControl2 value: ${v}`));
formControl2.setValue(1);
formControl2.setValue(2);
这里我通过发出FormControl初始值修改valueChanges
Observable,然后跳过它。所以distinctUntilChanged
第一次被调用,这是行:
formControl2.setValue(1)
它将已经有previousValue(1)来比较新值,因此subscribe中的函数将不会被执行。
但我真的不喜欢这个解决方案。是否有内置或推荐的方法来处理Angular7和RxJS6中的FormControl值更改?
stackblitz:https://stackblitz.com/edit/angular-arevmw?file=app%2Ficon-overview-example.ts
如果我正确理解了这个问题,你希望你的observable只触发除初始值之外的任何值变化吗?
您是否尝试在创建表单控件时设置该值
new FormControl({ value: 1 });
或者您可以指定在设置值时不想发出事件
const formControl1 =new FormControl(1);
formControl1.setValue(1, { emitEvent: false });
根据文档,您可以在设置值时指定选项,包括:
emitEvent:当为true或未提供(默认值)时,statusChanges和valueChanges observables在更新控件值时会发出具有最新状态和值的事件。如果为false,则不会发出任何事件。
我希望这有帮助!
distinctUntilChanged初始状态始终为空。但是当第一个值被发出时,distinctuntilchanged存储了第一个值。然后发出第二个值,它比较新值和存储值。所以你的解决方案是正确的,或者你可以使用skipWhile进行第一次比较。