Angular 6中如何获取值发生变化的输入字段名称?
嘿,完全懂你这种要逐个写if判断的痛苦——字段多起来不仅代码冗余,还容易漏写!我之前也遇到过类似的场景,给你分享几个更优雅的解决方案:
方案1:利用深对比+差异字段提取
这个方案适合你需要批量判断变化,或者想知道具体哪些字段被修改的场景。我们可以用深对比工具(比如lodash的isEqual)来替代逐个字段的判断,再配合RxJS的distinctUntilChanged避免不必要的订阅触发:
首先确保项目里有lodash-es(如果没有的话,执行npm i lodash-es安装),然后可以这么写:
import { isEqual } from 'lodash-es'; import { distinctUntilChanged } from 'rxjs/operators'; // ... 其他代码 this.localstorageService.getPlaceDetail().subscribe(data => { this.initPlaceDetail = data; // 先把初始数据转换成和表单value结构完全一致的对象(关键!避免结构不一致导致对比错误) const initialFormState = { ja_name: this.initPlaceDetail.languages.ja.name.text, ja_romaji: this.initPlaceDetail.languages.ja.name.romaji, // 其他表单字段对应的初始值,一一对应 }; this.editPlaceForm.valueChanges.pipe( // 只有当表单值真的发生变化时才触发订阅,排除重复的相同值 distinctUntilChanged((prev, curr) => isEqual(prev, curr)) ).subscribe(changedVal => { // 自定义函数获取所有变化的字段名 const changedFields = this.getModifiedFields(initialFormState, changedVal); // 比如判断是否有日语相关字段变化 this.changedJA = changedFields.some(field => ['ja_name', 'ja_romaji'].includes(field)); // 其他语言或字段的标记逻辑同理 }); }); // 提取变化字段的辅助函数 private getModifiedFields(initial: Record<string, any>, current: Record<string, any>): string[] { return Object.keys(current).filter(key => !isEqual(initial[key], current[key])); }
方案2:单独监听每个表单控件的变化
如果你的需求是对单个字段的变化做精细化处理(比如某个字段变化要触发特定逻辑),可以直接循环表单的控件,给每个控件单独订阅valueChanges:
import { distinctUntilChanged } from 'rxjs/operators'; // ... 其他代码 this.localstorageService.getPlaceDetail().subscribe(data => { this.initPlaceDetail = data; // 遍历所有表单控件 Object.keys(this.editPlaceForm.controls).forEach(controlName => { const control = this.editPlaceForm.get(controlName); if (!control) return; control.valueChanges.pipe( distinctUntilChanged() ).subscribe(newVal => { // 根据控件名匹配对应的初始值 let initialVal: any; switch(controlName) { case 'ja_name': initialVal = this.initPlaceDetail.languages.ja.name.text; break; case 'ja_romaji': initialVal = this.initPlaceDetail.languages.ja.name.romaji; break; // 其他控件的初始值映射 } // 判断值是否变化,更新对应状态 if (!isEqual(newVal, initialVal)) { if (['ja_name', 'ja_romaji'].includes(controlName)) { this.changedJA = true; } // 其他字段的专属逻辑可以写在这里 } }); }); });
额外提示
- 注意拼写!你代码里的
chengedVal是拼写错误,应该是changedVal,避免后续出现奇怪的bug; - 如果只是需要判断表单是否有任何变化,不需要具体字段的话,直接用
isEqual(initialFormState, changedVal)就能快速得到结果; - 记得在组件销毁时取消所有订阅,避免内存泄漏(可以用
takeUntil操作符配合ngOnDestroy里的销毁信号)。
内容的提问来源于stack exchange,提问作者通りすがりのおっさん
相关产品推荐
相关产品推荐

