Angular ngModelChange中的大坑

本人后端程序员, Angular小菜鸡一枚, 文章内容可能有误, 还请务必指出. 

先说结论

Angular中ngModelChange与ngModel属性, 在标签中出现的位置顺序决定ngModelChanges事件触发与Model的改变顺序.

如果ngModelChange出现在ngModel前面, 那么ngModelChange被触发的时候, model中变量的值还是没有change过的变量, 也就是视图层View之前的值.

如果ngModelChange出现在ngModel后面, 那么ngModelChange被触发的时候, model中变量的值就是当前视图层View中的值.

根据上面这个结论, 可以应该可以说在绝大多数场景下, ngModelChange都应该在ngModel的后面, 要是一不小心写反了, 程序就会有意想不到的结果.

我的经历

我尝试着通过angular编写一个计算器程序, 界面如下:

 

没有任何按钮, 只通过监听上面的输入和选择的更改, 执行计算操作.

代码如下:

<div nz-row [nzGutter]="[32,16]">
    <div nz-col id="col1">
        <div nz-col>
            <input nz-input (ngModelChange)="calculate()"  [(ngModel)]="this.num1" id="num1 " name="num1 " placeholder="操作数1 ">
        </div>

        <div nz-col>
            <nz-select  (ngModelChange)="this.calculate()" [(ngModel)]="this.cur_operator" [nzOptions]="this.operators ">

            </nz-select>

        </div>
    </div>
    <div nz-col id="col2 ">
        <div nz-col>
            <input nz-input  (ngModelChange)="calculate()" [(ngModel)]="this.num2" id="num2 " name="num2 " placeholder="操作数2 ">
        </div>
        <div nz-col>
            <input nz-input [(ngModel)]="this.num3" id="num3 " name="num3 " placeholder="答案 ">
        </div>
    </div>
</div>

按理来说, 只要监测到Model Change, 然后去执行计算操作, 就可以满足我的需求了.

然而, 我大意了. 这样的做法的结果就是:

 

虽然输入操作触发了ModelChange事件, 然而在ModelChange被触发的时候, 绑定的值并没有改变. 正如上图所示, 只有在左侧文本框已经变成12了, 这时结果文本框居然计算的是1+2的值(应该计算12+2).

这就很令人头痛了...

后来在百度和Google上搜了, 找到了问题所在: ngModelChange一定要跟在ngModel后面(也就是开篇我所描述的). 于是, 我将ngModelChange放到了ngModel后面, 问题迎刃而解.

我顺便尝试了下, 如果ngModel前后都有一个ngModelChange, 那么是否会在model改变前和改变后调用触发两次change事件呢?

答案是: 确实如我所想.


<div nz-col>
   <nz-select (ngModelChange)="this.before()" [(ngModel)]="this.cur_operator" 
							(ngModelChange)="this.calculate()" [nzOptions]="this.operators ">
</nz-select>

如上代码, 在ngModel前后设定了change事件, 分别调用before和calculate方法, 它们都会在控制台中输出操作符绑定的变量operator_cur, 下面是option从+变成/时, 控制台的输出结果.

 

可见, 确实我的选择操作触发了两次change事件. 而且也确实是一先一后.

input事件

上面说了关于ModelChange事件的执行先后的问题, 下面介绍一个input事件, 绑定这个事件可以无视ngModel所在的位置. 只要用户发生了输入操作, 就会调用该方法, 并且一定是在model发生了改变后调用. 对于input这种文本框, 可以考虑使用这个事件, 因为这样就不需要上述不小心写反的问题.

美中不足是, 根据我目前的测试, 该事件仅能在一些需要键盘输入的控件上上被触发. 像刚刚那个selector是不能触发input事件的.

这是我得知这个事件的地方:

https://stackoverflow.com/questions/35359358/angular-2-change-event-on-every-keypress

I just used the event input and it worked fine as follows:

# in .html file :
<input type="text" class="form-control" (input)="onSearchChange($event.target.value)">

# in .ts file :
onSearchChange(searchValue: string): void {  
  console.log(searchValue);
}

感谢阅读!  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值