vue 表单输入格式化中文输入法异常问题


Posted in Javascript onMay 30, 2018

v-model 是 vue.js 提供的语法糖,根据不同的表单控件监听不同的事件,实现对表单控件的数据双向绑定。

当控件是 <input> 输入框时,v-model 监听其 input 事件。

如下所示,这两种写法有什么区别吗?

<input :value="name" @input="name = $event.target.value"><input v-model="name">

输入中文格式化问题

表单输入常见需求:对<input>控件输入的内容进行格式化,譬如:转成大写字母。如果输入的值包含中文,格式化就会引起输入法异常。

如下图所示,也可以在线尝试:

vue 表单输入格式化中文输入法异常问题

如果使用 v-model 指令实现数据双向绑定,就不会出现输入法异常,如下图所示,也可以在线尝试:

vue 表单输入格式化中文输入法异常问题

上面的问题,可以看出 v-model 不只是给变量赋值,那么,它还做了些什么呢?

v-model 源码分析

本文参考的 vue.js 源代码是 2.5.16

翻看 v-model 源码,可以看到 v-model 关注的仍然是 input 事件:

vue 表单输入格式化中文输入法异常问题

input 事件绑定的回调代码处理,如下:

vue 表单输入格式化中文输入法异常问题

这里可以看到,v-model 判断了 composing 属性,当输入法组合没有结束的时候,直接返回,并没有赋值。

composing 属性并不是标准 dom 元素属性,那它是怎么来的呢?

vue 表单输入格式化中文输入法异常问题

这里可以看出,composing 属性是 vue.js 添加到 dom 节点上的。

那么,是什么地方调用了这2个函数呢?可以看到,在插入dom节点时,vue.js 监听了 compositionstart / compositionend 事件:

vue 表单输入格式化中文输入法异常问题

compositionstart / compositionend 这2个 dom 事件,浏览器兼容性问题可以查阅 MDN 说明:

compositionstart 事件

compostionend 事件

源代码中还发现,在是否刷新 dom 属性值时,也用到了 composing 属性:

vue 表单输入格式化中文输入法异常问题

这里可以看出,在输入法组合过程中,vue.js 变量值的更新亦不会同步到 dom元素的 value 属性。

综上所述:

v-model 实际上是监听了 <input> 控件的 input、compositionstart、compositionend 三个事件,在输入法组合过程中就直接返回不赋值v-model 指令设置了变量 composing,此标识还用于判断是否更新 dom元素的 value 属性

v-model 输入中文触发的事件

从上面源代码分析可知,v-model 绑定 <input> 输入中文时,实际触发的事件如下:

vue 表单输入格式化中文输入法异常问题

vue 表单输入格式化中文输入法异常问题

compositionstart => 3个 input => compositionend 事件,这些都是 <input>控件触发的。最后一个 input 事件,是源代码里面看到的 onCompositionEnd 回调里面 vue.js 触发的。

1、compositionstart事件

修改dom对象的composing属性为 true

2、3个input事件

由于dom对象的composing属性为true,不会赋值,直接返回。

3、compositioinend事件

修改dom对象的composing属性为 false

4、vue.js触发的 input事件

由于dom对象的composing属性为false,赋值,修改相应变量的值。

格式化问题原因分析

再次看下文章开头的示例,如果使用 v-model 指令实现数据双向绑定,就不会出现输入法异常,如下图所示,也可以在线尝试:

vue 表单输入格式化中文输入法异常问题

由前面的分析可知:

v-model 指令设置了变量 composing,虽然代码在 format 函数里更改了 this.name 的值,但此时 composing 标识阻止了将 this.name 的值同步给 input 元素的 value 属性如果你感兴趣的话,可以修改 vue.js 的源代码,将 shouldUpdateValue 函数里对 composing 属性的判断去掉,可以看到输入法又跟之前一样异常了

格式化问题 bugfix

再次看下文章开头的示例,如果使用 :value, @input 实现数据双向绑定,有两个方案可以解决中文输入异常的问题。

方案一:监听 change 事件

等输入结束失去焦点以后,再调用格式化方法,如下所示,也可以在线尝试:

方案二:监听 input 事件,同时判断输入法组合过程

在输入法组合过程中,不进行格式化,如下所示,也可以在线尝试:

总结

以上所述是小编给大家介绍的vue 表单输入格式化中文输入法异常问题,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
JQuery实现点击div以外的位置隐藏该div窗口
Sep 13 Javascript
JavaScript判断变量是否为空的自定义函数分享
Jan 31 Javascript
jquery实现两个图片渐变切换效果的方法
Jun 25 Javascript
深入理解javascript作用域第二篇之词法作用域和动态作用域
Jul 24 Javascript
BootStrap Fileinput初始化时的一些参数
Dec 30 Javascript
jQuery+C#实现参数RSA加密传输功能【附jsencrypt.js下载】
Jun 26 jQuery
JS 60秒后重新发送验证码的实例讲解
Jul 26 Javascript
Swiper 4.x 使用方法(移动端网站的内容触摸滑动)
May 17 Javascript
vuex实现像调用模板方法一样调用Mutations方法
Nov 06 Javascript
js实现右键弹出自定义菜单
Sep 08 Javascript
JavaScript构造函数原理及实现流程解析
Nov 19 Javascript
JS常用跨域方法实现原理解析
Dec 09 Javascript
详解如何使用babel进行es6文件的编译
May 29 #Javascript
基于打包工具Webpack进行项目开发实例
May 29 #Javascript
JavaScript反射与依赖注入实例详解
May 29 #Javascript
使用webpack3.0配置webpack-dev-server教程
May 29 #Javascript
vuejs 切换导航条高亮(路由菜单高亮)的方法示例
May 29 #Javascript
微信小程序6位或多位验证码密码输入框功能的实现代码
May 29 #Javascript
Vue 全局loading组件实例详解
May 29 #Javascript
You might like
php计算十二星座的函数代码
2012/08/21 PHP
ECshop 迁移到 PHP7版本时遇到的兼容性问题
2016/02/15 PHP
php接口技术实例详解
2016/12/07 PHP
js querySelector和getElementById通过id获取元素的区别
2012/04/20 Javascript
用Jquery重写windows.alert方法实现思路
2013/04/03 Javascript
基于jquery实现的文字向上跑动类似跑马灯的效果
2014/06/17 Javascript
JavaScript中的apply和call函数详解
2014/07/20 Javascript
2016年最热门的15 款代码语法高亮工具,美化你的代码
2016/01/06 Javascript
手机端实现Bootstrap简单图片轮播效果
2016/10/13 Javascript
js中数组的常用方法小结
2016/12/30 Javascript
Angularjs实现搜索关键字高亮显示效果
2017/01/17 Javascript
浅谈js中的变量名和函数名重名
2017/02/13 Javascript
jQuery插件HighCharts实现的2D堆条状图效果示例【附demo源码下载】
2017/03/14 Javascript
微信小程序实现收藏与取消收藏切换图片功能
2018/08/03 Javascript
Vue.js 中 axios 跨域访问错误问题及解决方法
2018/11/21 Javascript
JavaScript实现随机点名小程序
2020/10/29 Javascript
vue+elementUI动态增加表单项并添加验证的代码详解
2020/12/17 Vue.js
用Python遍历C盘dll文件的方法
2015/05/06 Python
python实现手机通讯录搜索功能
2018/02/22 Python
Django重装mysql后启动报错:No module named ‘MySQLdb’的解决方法
2018/04/22 Python
python获取本机所有IP地址的方法
2018/12/26 Python
python使用threading.Condition交替打印两个字符
2019/05/07 Python
pyqt5 实现在别的窗口弹出进度条
2019/06/18 Python
python celery分布式任务队列的使用详解
2019/07/08 Python
python实现将视频按帧读取到自定义目录
2019/12/10 Python
社区版pycharm创建django项目的方法(pycharm的newproject左侧没有项目选项)
2020/09/23 Python
Python就将所有的英文单词首字母变成大写
2021/02/12 Python
美国电子产品折扣网站:Daily Steals
2017/05/20 全球购物
最新的大学生找工作自我评价
2013/09/29 职场文书
渔夫的故事教学反思
2014/02/14 职场文书
高中生第一学年自我鉴定
2014/09/12 职场文书
个人整改方案范文
2014/10/25 职场文书
2014年六五普法工作总结
2014/11/25 职场文书
学校党风廉政建设调研报告
2015/01/01 职场文书
一篇文章学会Vue中间件管道
2021/06/20 Vue.js
面试分析分布式架构Redis热点key大Value解决方案
2022/03/13 Redis