Angular ngModel绑定输入框每输入一个字符就失焦如何解决
问题根因
*ngFor默认通过对象引用身份追踪列表项变更,你的contact.adress是字符串原始值数组,每次输入触发ngModel更新数组对应索引的字符串时,原始值的引用会发生改变,Angular会判定该列表项被整体替换,直接销毁旧DOM、重新渲染新节点,原本聚焦的输入框被销毁,自然就出现每输入一个字符就失焦的现象。
修复方法
方法一:添加trackBy追踪函数(改动最小,推荐)
通过trackBy指定按索引追踪列表项,只要索引不变就不重建对应DOM:- 在组件TS文件中添加trackBy方法:
trackByIndex(index: number): number { return index; } - 修改模板中*ngFor的配置,追加trackBy规则:
原有新增、删除地址的逻辑不需要调整即可正常使用。<div *ngFor="let phoneAddress of contact.adress; let i = index; trackBy: trackByIndex"> <label for="adress">Adress</label> {{phoneAddress}} <input type="text" [(ngModel)]="contact.adress[i]" [ngModelOptions]="{standalone: true}"> <button (click)="removeAddress(i)">-</button> <button (click)="addAddress()">+</button> </div>
- 在组件TS文件中添加trackBy方法:
方法二:调整数组存储结构
把原始字符串数组改为对象数组,由于对象的引用不会随着内部属性值变化而改变,*ngFor不会误判列表项被替换:- 调整数据结构,将
contact.adress的类型从string[]改为{content: string}[],新增地址时推入空对象:addAddress() { this.contact.adress.push({content: ""}); } removeAddress(ind: number): void { this.contact.adress.splice(ind, 1); } - 调整模板中的绑定目标为对象属性:
该方案不需要额外加trackBy,但需要调整上下游涉及地址数据的处理逻辑,适合还在开发初期、数据结构未定型的场景。<div *ngFor="let phoneAddress of contact.adress; let i = index"> <label for="adress">Adress</label> {{phoneAddress.content}} <input type="text" [(ngModel)]="contact.adress[i].content" [ngModelOptions]="{standalone: true}"> <button (click)="removeAddress(i)">-</button> <button (click)="addAddress()">+</button> </div>
- 调整数据结构,将
内容的提问来源于stack exchange,提问作者Bakhtovar Akhmedov
相关产品推荐
相关产品推荐

