Angular:输入框原内容为默认值全选删除后未同步显示重置值
问题原因
该问题由Angular ngModel 双向绑定的变更检测优化逻辑导致:
- 全选删除输入框内容时,原生输入框会先把自身DOM值更新为空字符串,随后触发
ngModel的模型同步逻辑,把空字符串传入你的set方法。 - set方法检测到空值后,直接把内部存储的变量重置回
'DEFAULT'。此时Angular会对比ngModel绑定属性的新旧值:更新前的旧值为'DEFAULT',重置后的新值还是'DEFAULT',Angular判定值未发生变化,就不会触发把模型值回写到输入框DOM的操作。 - 插值绑定的span元素没有
ngModel的这层优化,每次变更检测周期都会读取最新的属性值渲染,因此能正确显示'DEFAULT'。
解决方案
下面提供3种可直接落地的修复方案:
方案1:最低改造成本方案
在set方法重置值时加一层微任务延迟,让Angular先完成当前的空值变更检测流程,再更新为'DEFAULT',就能触发正常的视图同步:
private _value = 'DEFAULT'; get value() { return this._value; } set value(v: string) { if (v === '') { // 0延迟的setTimeout会把赋值操作推到下一个微任务队列执行 setTimeout(() => { this._value = 'DEFAULT'; }, 0); return; } this._value = v; }
方案2:强制ngModel同步视图
通过ViewChild拿到输入框的ngModel实例,重置值后手动调用控件的setValue方法强制更新视图:
组件代码:
import { ViewChild, NgModel } from '@angular/core'; export class AppComponent { @ViewChild('inputRef') inputNgModel: NgModel; private _value = 'DEFAULT'; get value() { return this._value; } set value(v: string) { if (v === '') { this._value = 'DEFAULT'; // 强制更新输入框视图 setTimeout(() => { this.inputNgModel.control.setValue(this._value); }); return; } this._value = v; } }
模板代码给输入框添加模板引用:
<input #inputRef [(ngModel)]="value" /> <span>{{value}}</span>
方案3:使用Angular表单原生逻辑实现
改用响应式表单的校验和值变更监听逻辑实现需求,天然适配表单的更新机制,避免自定义set方法的时序问题:
组件代码:
import { FormControl } from '@angular/forms'; export class AppComponent { valueControl = new FormControl('DEFAULT'); ngOnInit() { this.valueControl.valueChanges.subscribe(v => { // emitEvent设为false避免触发循环监听 if (v === '') { this.valueControl.setValue('DEFAULT', { emitEvent: false }); } }); } }
模板代码:
<input [formControl]="valueControl" /> <span>{{valueControl.value}}</span>
内容的提问来源于stack exchange,提问作者Leviathan3
相关产品推荐
相关产品推荐

