咱们在网页中常常会遇到实时搜索的状况,或者其余相似须要input实时响应的问题,通常状况下,咱们是利用input和propertychange事件来监听input内容的变化来响应,可是有一个问题就是当输入汉字的时候,可能咱们要输入 ‘实时’ 的时候,咱们的input框中会出现 'shishi'直到咱们的空格才会变成 '实时',这也就意味着咱们依次响应了 's','sh','shi','shis','shish','shishi','实时',前面的结果明显不是咱们须要的 ,形成了咱们不少次无用的提交,若是是接口请求,那更要命,多发了好屡次请求。浏览器
最先以前有一个稍微能改善的解决方案就是配合一个定时器延时执行,这样能减小请求次数,可是这个减小是不分状况的减小 ,仍是治标不治本。app
今天偶然看到几个事件,发现能够完美解决这种问题。咱们来看一下这几个事件优化
compositionstart , compositionupdate ,compositionend code
compositionstart 官方解释 : 触发于一段文字的输入以前(相似于 keydown 事件,可是该事件仅在若干可见字符的输入以前,而这些可见字符的输入可能须要一连串的键盘操做、语音识别或者点击输入法的备选词),通俗点,假如咱们要输入一段中文,当咱们按下第一个字母的时候触发 。接口
相应的compositionupdate在咱们中文开始输入到结束完成的每一次keyup触发。事件
而compositionend则在咱们完成当前中文的输入触发 。get
正题来了,经过上面的事件咱们就能够完美的解决中文输入的响应问题了,从compositionstart触发开始,意味着中文输入的开始且还没完成,因此此时咱们不须要作出响应,在compositionend触发时,表示中文输入完成,这时咱们能够作相应事件的处理。input
因此咱们能够设置一个变量,或者给input定义一个属性,在compositionstart到compositionend之间对input事件不作出响应。看如下代码it
$('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,显然不是最优方案。io
通过试验,发现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>') }
最终效果实现:
在线预览: