Angular中如何在change事件触发后获取ngModel的旧值?
解决Angular 2下拉框绑定ngModel时获取旧值的问题
嘿,我碰到过好几个开发者遇到和你一样的问题——用Angular 2的ngModel绑定下拉框后,想在触发变更事件时拿到旧值,试了用data-*属性存储却拿到NaN,确实挺闹心的。下面给你几个实用的解决方案,都是实际项目里验证过的:
方案一:组件类手动维护旧值(模板驱动表单首选)
这是最直接的方式,完全在Angular逻辑里处理,不用碰DOM:
- 先在组件里定义两个变量,分别存当前值和旧值:
currentSelection: any; previousSelection: any;
- 初始化时把默认值(来自你的
question[]数组)赋值给这两个变量:
ngOnInit() { // 假设你的默认值是question数组的第一个元素的value this.currentSelection = this.question[0].value; this.previousSelection = this.currentSelection; }
- 模板里绑定
ngModel和ngModelChange事件(别用原生onchange,Angular推荐用这个):
<select [(ngModel)]="currentSelection" (ngModelChange)="onSelectionChange($event)"> <option *ngFor="let q of question" [value]="q.value">{{q.label}}</option> </select>
- 事件处理函数里就能拿到新旧值了:
onSelectionChange(newValue: any) { console.log('变更前的值:', this.previousSelection); console.log('新选中的值:', newValue); // 记得更新旧值,下次变更时用 this.previousSelection = newValue; }
方案二:修复data-*属性的使用方式
你之前拿到NaN,大概率是因为data-*的初始化或读取方式不对。试试这样:
- 给下拉框加个模板引用变量,方便获取DOM元素:
<select #myDropdown [(ngModel)]="selectedValue" (change)="onDropdownChange($event, myDropdown)"> <option *ngFor="let q of question" [value]="q.value">{{q.label}}</option> </select>
- 组件里用
ViewChild获取这个元素,初始化时设置data-*属性:
import { ViewChild, ElementRef } from '@angular/core'; @ViewChild('myDropdown') dropdownElement: ElementRef; selectedValue: any; ngOnInit() { this.selectedValue = this.question[0].value; // 初始化data-old-value为默认值 this.dropdownElement.nativeElement.dataset.oldValue = this.selectedValue; }
- 事件处理函数里正确读取和更新:
onDropdownChange(event: Event, dropdown: ElementRef) { const oldValue = dropdown.nativeElement.dataset.oldValue; const newValue = event.target['value']; // 注意:如果你的value是数字类型,要转一下,不然会是字符串 console.log('旧值:', Number(oldValue)); console.log('新值:', Number(newValue)); // 更新data-old-value为新值 dropdown.nativeElement.dataset.oldValue = newValue; }
这样就不会出现NaN了——之前的问题可能是你没在初始化时给data-*赋值,或者读取时没做类型转换(字符串转数字)。
方案三:用RxJS的pairwise(响应式表单首选)
如果你的项目用了响应式表单(FormControl),这个方式更优雅:
- 定义FormControl并初始化默认值:
import { FormControl } from '@angular/forms'; import { pairwise } from 'rxjs/operators'; selectControl = new FormControl(this.question[0].value);
- 在初始化时订阅valueChanges,用
pairwise操作符获取前后值:
ngOnInit() { this.selectControl.valueChanges.pipe( pairwise() // 会把当前值和前一个值组成数组返回 ).subscribe(([oldValue, newValue]) => { console.log('旧值:', oldValue); console.log('新值:', newValue); }); }
- 模板里绑定FormControl:
<select [formControl]="selectControl"> <option *ngFor="let q of question" [value]="q.value">{{q.label}}</option> </select>
这个方式不用手动维护旧值变量,RxJS会帮你处理,适合复杂的表单场景。
总结一下,模板驱动表单选方案一,响应式表单选方案三,一定要用data-*的话就用方案二——都是靠谱的解决办法,你可以根据自己的项目情况选。
内容的提问来源于stack exchange,提问作者K.Z
相关产品推荐
相关产品推荐

