angular4中ngModel双向绑定在限制输入情况下与value值不一致的问题及尝试的解决方法

近期公司的一个后台项目在使用angular4进行开发,随着项目的推进和迭代开发,需要对有的input框的value值进行限制输入,例如目前项目的一些input框只允许输入数字和'.' 这两种形式的内容。就在input标签的中添加了(keyup)属性,将相应的ts文件中编写的一个正则验证方法赋值给该属性,以便进行验证,如下所示:

<input type="text" #price [(ngModel)]="normal.price" (keyup)="numTest($event)">元/次 {{normal.price}} ||| {{price.value}}

numTest($event){
   $event.target.value = $event.target.value.replace(/[^\d]/g, '');
}
开始以为这样的正则是没有问题的,但是通过实践发现,该方法有一定局限性。在打开中输入法的时候,当键入汉字并使用Space键或者Enter键或者鼠标左键选择输入法罗列的汉字时,该正则对input的value值是有效果的,但是对双向绑定的“normal.price”是不起作用的。在页面显示的
normal.price -> 你好 ||| price.value -> ''(在页面是不显示price.value的值的,因为通过正则,已经将该值置为空了,这里用''表示)

初次遇到这个问题,感觉有些奇怪,印象里在angularjs的使用过程中并没有出现同样的问题,虽然angular2之后使用TypeScript重新编写了框架,但是双向绑定这个亮点还是保留的,不应该出现这样的不一致才对。随后查看了angular的文档,在核心知识->模板和数据绑定->模板语法中找到了相关的表述:

表述

从该表述中获知,双向绑定的实现是模仿input标签中的[value]、[input]两个属性来实现值的变化的。于是就暂时先弃用双向绑定的便利写法,回归原始:

input type="text" #price [value]="normal.price" (input)="normal.price=$event.target.value" (keyup)="numTest($event)">元/次 {{normal.price}} ||| {{price.value}}
 但结果跟使用双向绑定的效果一样,normal.price的值依然没有进行有效的正则过滤。对此更加疑惑不解,在网上好像也没能寻求到相同问题的解决办法。

这个问题搞了一下午还是没有什么起色,到了第二天,可能是换了换脑子的缘故,重新梳理了一下这个问题,决定将这个问题分两步,分别解决:1、怎么禁止中文输入法的使用,不能将键入选择的汉字输入到input框中;2、怎么同步[(ngModel)]的属性值与input的value值完全同步的问题。

有了这样的思路后,首先着手看怎么禁止中文输入法,这个网上有好多,相对能找到一些有价值的参考。找到了这篇文章:

input 事件与汉字输入法:使用compositionend事件解决发现了“compositionend“这个属性。查看了MDN中关于compositionend 属性的解释:

解释:
查看了翻译后的文本,当然解释不一定完全符合原意,有在网上查找了该属性的一些用法,一般是对input属性的补充。用于监听文本的输入,对中文输入法起作用。至此,对于第一个问题的解决就有了思路:
<input type="text" #price [(ngModel)]="normal.price" (compositionend)="$event.target.value= ''" (keyup)="numTest($event)">元/次 {{normal.price}} ||| {{price.value}}
这样,当中文输入法键入汉字时,input框的value值会强制置空,根据这样的思路,同时再强制双向绑定的值,也是可行的。
第一个问题解决之后,就着手开始第二个问题的处理,怎样使normal.price同input的value值保持一致,由于始终没有完全理清ngModel的实现原理,且还原成原始的value和input属性后效果相同,在不得已的情况下,又在input标签中添加了一个属性ngModelChage,将带有正则验证方法的返回值重新赋值给ngModel的属性值。这样问题二也能够间接的解决掉。并且配合前边的compositionend属性,使页面表现同数据的赋值相一致。
最终的结果是这样子的:
<input type="text" #price [(ngModel)]="normal.price" (ngModelChange)="normal.price=numTestValue($event)" (compositionend)="$event.target.value= ''" (keyup)="numTest($event)">元/次 {{normal.price}} ||| {{price.value}}
 clearNoNum11($event) {
    $event = $event.replace(/[^\d]/g, '');
    return $event;
  };
这样,算是解决了在有输入限制的情况下,input框的value值与双向绑定的值不一致的问题。当然,这里的解决方案并不是最终、最简便的,待以后对angular4有更深入的理解后,再进行方法的补充和提炼吧!

Ps: 这里还有一个疑惑,在angular技术文档中
<input [value]="currentHero.name" (input)="currentHero.name=$event.target.value" > 的对应anglar写法是
<input [ngModel]="currentHero.name" (ngModelChange)="currentHero.name=$event">
但是在ngModelChage的$event直接就是该input框的value,而不是通常认为的event事件对象。在这里注明一下,有待后续学习理解。






猜你喜欢

转载自blog.csdn.net/rushichunqiu/article/details/79161076