低版本AngularJs(1.2.12及以下)输入中文完成后不触发ng-model的问题
问题描述
当使用的AngularJs版本低于1.2.13
时,使用输入法输入中文无法触发ng-model
的双向绑定,此时必须再键入其它任意字符或者使输入框失去焦点,才能正确获取到ng-model
的绑定值。
这会对某些使用场景造成一些困扰,如搜索关键字自动补全,列表即时过滤等。
环境说明
- AngularJs版本:1.2.12及以下
- chrome浏览器版本:65.0.3325.181(正式版本) (64 位)
解决方案
1. 更换angualrJs版本到1.2.13
或以上
1.2.13
及以上版本已修复该BUG。
对一个庞大的项目或者老项目来说,贸然更换版本有一定的风险,可能会导致已完成开发功能点不可用,应确保有合格且全面的测试以发现问题并修复,保障线上运行时不会出错。
注意:在更换AngularJs版本时,要考虑到AngularJs相关插件的版本同步更新。
2. 修改源码
AngularJs会为添加了ng-model
指令的输入框绑定一系列监听,当input
输入框类型为text
时,绑定监听的方法为textInputType
在textInputType
方法中,绑定了compositionstart
、compositionend
、input
的事件监听,这就是对中文输入等非直接输入的监听事件(具体作用可自行搜索),代码如下所示:
1 | function textInputType(scope, element, attr, ctrl, $sniffer, $browser) { |
按代码逻辑来看,预想的是:在键入中文时,触发compositionstart
,将composing
值修改为true
,输入完成触发compositionend
,将composing
值修改为false
,然后触发input
,执行listener
,完成双向绑定。理想触发顺序为 compositionstart --> compositionend --> input --> 执行listener
但是在chrome浏览器中,由于浏览器机制问题,实际触发顺序为: compositionstart --> input --> 执行listener(实际并未执行)--> compositionend
因此,针对chrome浏览器,我们需要在触发compositionend
后,才执行listener
,所以,我们可以直接在compositionend
方法内部调用listener
:
1 | element.on('compositionend', function() { |
实际上,1.2.13
及以上版本就是这么做的。
3. 自定义指令
在某些特殊情况下,如果更换版本、修改源码均不可行,可以考虑自定义指令实现ng-model
相同的功能。
4. 更换浏览器
。。。
低版本AngularJs(1.2.12及以下)输入中文完成后不触发ng-model的问题