我们在网页中经常会遇到实时搜索的情况,或者其他类似需要input实时响应的问题,一般情况下,我们是利用input和propertychange事件来监听input内容的变化来响应,但是有一个问题就是当输入汉字的时候,可能我们要输入 ‘实时’ 的时候,我们的input框中会出现 'shishi'直到我们的空格才会变成 '实时',这也就意味着我们依次响应了 's','sh','shi','shis','shish','shishi','实时',前面的结果明显不是我们需要的 ,造成了我们很多次无用的提交,如果是接口请求,那更要命,多发了好多次请求。

  最早之前有一个稍微能改善的解决方案就是配合一个定时器延时执行,这样能减少请求次数,但是这个减少是不分情况的减少 ,还是治标不治本。

  今天偶然看到几个事件,发现可以完美解决这种问题。我们来看一下这几个事件

  compositionstart , compositionupdate ,compositionend  

   compositionstart 官方解释 : 触发于一段文字的输入之前(类似于 keydown 事件,但是该事件仅在若干可见字符的输入之前,而这些可见字符的输入可能需要一连串的键盘操作、语音识别或者点击输入法的备选词),通俗点,假如我们要输入一段中文,当我们按下第一个字母的时候触发 。

  相应的compositionupdate在我们中文开始输入到结束完成的每一次keyup触发。

  而compositionend则在我们完成当前中文的输入触发 。

  正题来了,通过上面的事件我们就可以完美的解决中文输入的响应问题了,从compositionstart触发开始,意味着中文输入的开始且还没完成,所以此时我们不需要做出响应,在compositionend触发时,表示中文输入完成,这时我们可以做相应事件的处理。

  所以我们可以设置一个变量,或者给input定义一个属性,在compositionstart到compositionend之间对input事件不做出响应。看以下代码

$('input').on({
input : function(e){
var flag = e.target.isNeedPrevent;
if(flag) return;
response()
},
compositionstart : function(e){
e.target.isNeedPrevent = true ;
},
compositionend : function(e){
e.target.isNeedPrevent = false;
}
})
function response(){
$('div').append('<p>事 件触发</p>')
}

  我们通过compositionstart,compositionend事件来设置flag,判断是否正在进行输入中文以控制input事件的响应,看上去没有问题,但实际执行时会发现在谷歌浏览器中input执行顺序要先于compositionend,火狐执行顺序正常,但compositionend会响应两次。这就导致谷歌浏览器中输入汉字不会响应input事件。当然也可以在compositionend事件中再执行一次response事件,这样的问题是在火狐浏览器中会多执行一次response,显然不是最优方案。

  经过试验,发现keyup和compositionend事件执行顺序在各大浏览器都保持一致,于是我们改成如下代码:

$('input').on({
keyup : function(e){
var flag = e.target.isNeedPrevent;
if(flag) return;
response()
},
compositionstart : function(e){
e.target.isNeedPrevent = true ;
},
compositionend : function(e){
e.target.isNeedPrevent = false; }
})
function response(){
$('div').append('<p>事 件触发</p>')
}

  这样在各个浏览器基本保持一致了(兼容compositionstart的浏览器)。但是keyup有一个问题,比如通过鼠标复制粘贴的时候并不相应keyup事件,所以上面的事情我们还需要再优化下,keyup相应按键事件,input响应除了keyup之外的变化事件。代码如下

$('input').on({
keyup : function(e){
var flag = e.target.isNeedPrevent;
if(flag) return;
response() ;
e.target.keyEvent = false ; },
keydown : function(e){
e.target.keyEvent = true ;
},
input : function(e){
if(!e.target.keyEvent){
response()
}
},
compositionstart : function(e){
e.target.isNeedPrevent = true ;
},
compositionend : function(e){
e.target.isNeedPrevent = false; }
})
function response(){
$('div').append('<p>事 件触发</p>')
}

  从目前需求可以完全实现了。

在线预览:

参考文章:

https://developer.mozilla.org/zh-CN/docs/Web/Events/compositionstart

  

input事件中文触发多次问题研究的更多相关文章

  1. input输入中文时,拼音在输入框内会触发input事件的问题。

    问题描述: 监听文本输入框的input事件,在拼写汉字(输入法)但汉字并未实际填充到文本框中(选词)时会触发input事件,如图: 需要完成的需求就是在输入阶段不触发input中的事件,选词之后文字落 ...

  2. input、textarea等输入框输入中文时,拼音在输入框内会触发input事件的问题

    监听文本输入框的input事件,在拼写汉字(输入法)但汉字并未实际填充到文本框中(选词)时会触发input事件,如图: 但是在很多情况下,只需要输入到输入框的中文字符. 解决办法: 通过查阅资料得知在 ...

  3. input事件以及中文输入法的处理

    在项目的开发过程中,相信大家都处理过监听用户输入的事情,一般我们会用到onkeyup.onkeydown.onkeypress.onchange.oninput事件,虽然都很熟悉了,但是还是有必要巩固 ...

  4. compositionEnd 和 input 事件(中文输入法问题)

    网上用 compositionstart + compositionend + input 解决中文输入法问题的办法 node.addEventListener('compositionstart', ...

  5. label标签内含有input元素,点击事件会触发两次

    **label标签内含有input元素,点击事件会触发两次** 如果你的结构是label内写input实现点击文字时候input也有相应.并且,把事件设置在了label上,那么就会执行两次了. //h ...

  6. vant 使用field组件加载页面就触发input事件的坑,已解决

    使用vant的时候,遇到一个坑,加载组件就自动触发input事件,input事件里写了验证,导致已加载就验证错误 原因:v-model绑定的时候写的是null, filed组件接收的时候把他转换成空字 ...

  7. input 事件与汉字输入法:使用compositionend事件解决

    input 事件与汉字输入法:使用compositionend事件解决 在使用<input type="text">的input事件的时候 会遇到中文输入法的" ...

  8. input事件与change事件

    输入框的change事件: 必须等到输入框失去焦点的时候才会触发,鼠标在空白的地方点一下: 输入框的input事件: 在输入内容变化的同时,实时的触发,不需要等到失去焦点.

  9. HTML5 input事件检测输入框变化

    之前一直用change事件来监听输入框内容是否发生变化,只有当输入框失去焦点时才会触发,没想到html5还有个input事件,只要输入框内容发生变化就会立即触发,既然有这么好的东西我们干嘛放着不用呢, ...

随机推荐

  1. Jmeter3.2版本中Generating Report Dashboard功能浅析

    自从投入到Jmeter怀抱,一直想找到一个比较不错的测试结果报告模板用于展示,类似于Loadrunner中导出html那种,但是苦苦的寻找始终没有一款让我看上眼的,包括Jmeter自带的xsl,虽然展 ...

  2. Spark源码剖析(七):Job触发流程原理与源码剖析

    引言 我们知道在application中每存在一个action操作就会触发一个job,那么spark底层是怎样触发job的呢?接下来我们用一个wordcount程序来剖析一下job的触发机制. 解析w ...

  3. 深入C#.NET数据类型

    深入C#数据类型 --不同类型的参数传递使用值传递,在方法中对参数的更改在调用后不能保留.使用ref方式传递,可以保留对参数值的更改. ---值方式参数传递和引用方式传递使用值方式(不用ref修饰)传 ...

  4. HTML5新特性: 自定义属性前缀data-以及dataset的使用

    HTML5规定可以为元素添加非标准的属性,但要添加前缀 data- ,目的是为元素提供与渲染无关的信息,或者提供语义信息.这些属性可以任意添加.随便命名,只要以 data- 开头即可 添加了自定义属性 ...

  5. [Spark SQL] SparkSession、DataFrame 和 DataSet 练习

    本課主題 DataSet 实战 DataSet 实战 SparkSession 是 SparkSQL 的入口,然后可以基于 sparkSession 来获取或者是读取源数据来生存 DataFrameR ...

  6. docker with flannel

    ** 原创文章,请勿转载 ** docker的单host,多container环境下,是使用host的docker0网桥进行通信的.如果跨host, container之间要通信怎么办呢?答案是fla ...

  7. BaseServer的介绍

    服务器类型 5种类型:BaseServer,TCPServer,UnixStreamServer,UDPServer,UnixDatagramServer.注意:BaseServer不直接对外服务. ...

  8. 使用筛选器特性标记方法解决webapi 跨域问题

    在我的之前随笔 解决api.WebService跨域问题 中有人问到可以用特性来解决跨域问题吗,答案是肯定的,可以的:操作如下: 首先建一个类CrossSiteAttribute:从抽象 Action ...

  9. div外观例子

    title: div外观例子 date: 2018-1-15 14:00:00 tags: 前端 div css categories: 前端框架 --- 标题 我的标题 内容 Font Awesom ...

  10. gradle学习记录

    一.Gradle简介 Gradle是Android现在主流的编译工具,虽然在Gradle出现之前和之后都有对应更快的编译工具出现,但是Gradle的有时就在于它是亲儿子,Gradle确实比较慢,这和它 ...