[Angular]关于ngModel与ngModelChange
Posted 俞旭龙
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Angular]关于ngModel与ngModelChange相关的知识,希望对你有一定的参考价值。
最近开始参与公司内的Angular4+Ionic3混合开发App项目,算是正式接触Angular2+版本(之前只在CMDT做Benz项目时用过Angular1.x...惭愧)
初步看下来门槛的确比Vue高了不少,包括TypeScript和RxJS,不过好像TS里的强类型也可以用any类型全部糊弄过去?(烦躁了我就全部写any)
总的来说感觉Angular2+类似Java的MVC风格,有Model有Service,当然也可能是我的错觉...说错了请轻喷...
这个项目中有一个需求是:
输入框只能输入数字或小数点,小数点最多只能有一个,并且小数最多只能有8位
看起来挺简单的是吧?我一开始也是这么想的...第一反应是用类似Vue的watch来监听ngModel的值,当小数点数量大于1个时,替换为oldValue,同样小数点后面的长度大于8位时也做相同处理,事实证明我还是太天真了...
Angular的确有类似watch的事件,名叫(ngModelChange),但是它的限制很多,比如:
1.只能和ngModel配合使用(不能监听其他类型的值,也不能做类似计算属性的设置)
2.仅提供一个入参newVal,不像Vue有oldVal可以做参考
3.不能在ngModelChange事件里对当前ngModel的值进行赋值!!!!!
4.不能在ngModelChange事件里对当前ngModel的值进行赋值!!!!!
5.不能在ngModelChange事件里对当前ngModel的值进行赋值!!!!!
↑重要的事情说三遍!!上面这个什么意思呢,比如你写了:
html:
<input [(ngModel)]="price" (ngModelChange)="onModelChange(this.value)" />
ts:
onModelChange(newVal){
if(newVal不符合业务要求){
this.price = 'xxx';//这里等于xxx只是举例,实际应该是要恢复成输入前的oldValue值
}
}
如果是在Vue的Watch中,那么可以很轻松的将this.price的值变为xxx或修改回oldValue,而且用户体验很好,用户几乎无感知;但是在angular中,你会发现它只会在第一次生效,之后就无效了
在折腾了好几次以后,猜测Angular认为你在onModelChange事件中修改ngModel的值会导致ngModelChange再次触发,从而造成无限递归甚至死循环(但其实这个需求的业务逻辑并不会造成死循环),于是Angular直接禁止你修改ngModel的值...
emmm...这也太简单粗暴了点...我记得Vue是会判断是否会造成死循环的...
然后这玩意怎么破解呢...其实也很简单...加一个大杀器setTimeout timeout=0就行了...虽然这么写很丑陋...
ts:
onModelChange(newVal){
if(newVal不符合业务要求){
setTimeout(()={
//在这里欢快地修改price的值吧~
},0)
}
}
最终这个需求分了两步来执行,(keyDown)判断按下的值是否符合0-9/Backspace/.的需求,(ngModelChange)处理小数点数量和小数位数逻辑...代码我就不贴了...
PS:
1.我不是Vue吹,但是从易用性和设计上来说,Vue更好用
2.input type="number"也是个坑,会把"0."默认直接转成"0",如果用type="tel"又不能输小数点了,一开始是为了让手机默认弹出数字键盘才用的number,最后还是改成了text,但是在blur时将type改为number,click或focus时再改为text
3.魅族的系统浏览器内核依然是坑王之王,keyDown事件时根据event.key判断当前按下的键时直接失效,真机调试了下发现居然没有key这个属性...再查了下发现魅族的系统浏览器内核居然是Chrome40,而大部分功能都是在Chrome49才开始引入的...PC版的Chrome都65了...魅族你可以的...
以上是关于[Angular]关于ngModel与ngModelChange的主要内容,如果未能解决你的问题,请参考以下文章
Angular2 NgModel 在 Jasmine 测试中没有获得价值
[Angular]关于ngModel与ngModelChange