咱們在網頁中常常會遇到實時搜索的狀況,或者其餘相似須要input實時響應的問題,通常狀況下,咱們是利用input和propertychange事件來監聽input內容的變化來響應,可是有一個問題就是當輸入漢字的時候,可能咱們要輸入 ‘實時’ 的時候,咱們的input框中會出現 'shishi'直到咱們的空格纔會變成 '實時',這也就意味着咱們依次響應了 's','sh','shi','shis','shish','shishi','實時',前面的結果明顯不是咱們須要的 ,形成了咱們不少次無用的提交,若是是接口請求,那更要命,多發了好屢次請求。瀏覽器
最先以前有一個稍微能改善的解決方案就是配合一個定時器延時執行,這樣能減小請求次數,可是這個減小是不分狀況的減小 ,仍是治標不治本。app
今天偶然看到幾個事件,發現能夠完美解決這種問題。咱們來看一下這幾個事件優化
compositionstart ,
spacompositionupdate
,compositionend
compositionstart 官方解釋 : 觸發於一段文字的輸入以前(相似於 keydown
事件,可是該事件僅在若干可見字符的輸入以前,而這些可見字符的輸入可能須要一連串的鍵盤操做、語音識別或者點擊輸入法的備選詞),通俗點,假如咱們要輸入一段中文,當咱們按下第一個字母的時候觸發 。code
相應的compositionupdate在咱們中文開始輸入到結束完成的每一次keyup觸發。blog
而compositionend則在咱們完成當前中文的輸入觸發 。接口
正題來了,經過上面的事件咱們就能夠完美的解決中文輸入的響應問題了,從compositionstart觸發開始,意味着中文輸入的開始且還沒完成,因此此時咱們不須要作出響應,在compositionend觸發時,表示中文輸入完成,這時咱們能夠作相應事件的處理。事件
因此咱們能夠設置一個變量,或者給input定義一個屬性,在compositionstart到compositionend之間對input事件不作出響應。看如下代碼get
$('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,顯然不是最優方案。input
通過試驗,發現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