[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

Angular 2 单选按钮验证与 ngModel

ngModel 自定义 ValuesAccessor

Angular 2:如何将 JavaScript 日期对象与 NgModel 两种方式绑定一起使用

Angular 2:如何将 JavaScript 日期对象与 NgModel 两种方式绑定一起使用