最近好久沒有更新博客了,不是沒有東西寫,而是沒有時間寫。公司項目上事情比較多,又在工會謀了份差事;家裏房子裝修,儘管有老爸盯着,但不少時候仍是要本身跑來跑去。因此有時候有了寫博客的想法,卻總是坐不下來細細寫。這些就算爲本身這段時間的荒廢找個小小的藉口吧。javascript
其實最主要的問題仍是在於本身對博客的定位。以前一直想每篇博客都儘可能找到一些比較好的主題,寫的比較詳細,這樣看起來比較專業。可是這樣要求的話,每一篇就要花狠多時間準備,不少時間編寫,無形中也給本身帶來了不少壓力。這也是久久沒有動筆的一個主要緣由。後來在看不少牛人的博客的時候,發現他們也常常放一些小的可是頗有用的東西在博客上。都是平時開發的時候遇到的小問題和解決的過程。這樣的記錄其實並不須要花太多的時間,並且可以鞏固本身對知識點的掌握,也便於之後再次查閱。因而我以爲這樣的方式挺好的,尤爲是比較忙的時候,這樣短小精煉的博客,一樣可以給本身帶來很多的長進,也能促進本身勤寫博客的習慣養成。html
閒話就講到這裏,接下來就進入今天的主題:使用中文輸入法時,對鍵盤事件的處理。前端
問題的起源是這樣的:組裏有個同事發現現有項目上的一個自動補全的輸入框不響應中文輸入。英文輸入的時候,超過兩個字就開始向後臺查詢複合條件的選項。但中文輸入的時候,在輸入法上無論輸入多少字,輸入框沒有任何反應,按了空格或者回車後,字進入了輸入框,依然沒有可以出發補全的功能。 因而這個問題就到了」前端專家「個人手裏。java
如何入手呢,一開始固然是看現象。 發現中文輸入的時候,打出來的字都是在輸入法的框裏,因而猜測鍵盤事件都被輸入法給截獲了。但讓我不解的是,爲何當字被輸入到輸入框裏,仍是沒有反映。我第一反映是到google看輸入框。因而分別打開chrome,firefox,ie看現象。web
首先是Chrome,表現是最完美的,在輸入框中輸入中文的時候,輸入的拼音在中文被輸入以前填寫在輸入框裏,匹配的內容應該是根據輸入框裏的英文字母進行匹配,因此使人很滿意。chrome
其次到了firefox,從下圖中咱們能夠看到。當打開中文輸入法打字的時候,並無任何文字被輸入到輸入框中,因此也就沒有任何匹配項出現。以後當按了回車或者空格,將文字輸入到輸入框中以後,纔會有響應的匹配項顯示。瀏覽器
再來看一下IE,結果和firefox同樣,輸入法打開的時候,也沒有內容被捕獲和匹配。前端工程師
看完這三個瀏覽器的現象,大概證明了本身的猜測,輸入框捕獲了一些鍵盤事件,從而致使瀏覽器沒法獲取用戶輸入進行匹配。但當內容被填入輸入框的時候,匹配被觸發。 接下來一個很天然的想法,是否是onchange事件出發了匹配函數。因而本身開始動手試驗:函數
寫了一個最簡單的例子,input box分別綁定onchange,onkeydown,onkeyup,onkeypress事件,查看事件被出發的狀況:測試
1 <html> 2 <head> 3 <script type="text/javascript"> 4 function onChange(e){ 5 console.log("onchange!"); 6 } 7 function onKeyDown(e){ 8 console.log("onkeydown"); 9 } 10 function onKeyUp(e){ 11 console.log("onkeyup"); 12 } 13 function onKeyPress(e){ 14 console.log("onkeypress"); 15 } 16 </script> 17 18 </head> 19 20 <body> 21 <input type="text" onchange="onChange()" onkeydown="onKeyDown()" onkeyup="onKeyUp()" onkeypress="onKeyPress()"/> 22 </body> 23 </html>
而後開始用各個瀏覽器進行測試:首先是英文輸入狀態下
普通按鍵 abc | alt.shift,ctrl | ESC | Backspace | Enter | ||
Chrome | onkeydown, onkeypress, onkeyup |
onkeydown, onkeyup |
onkeydown, onkeyup |
onkeydown, onkeyup |
onkeydown, |
|
Firefox | onkeydown, onkeypress, onkeyup |
onkeydown, onkeyup |
onkeydown, onkeypress, onkeyup |
onkeydown, onkeypress, onkeyup |
onkeydown, onkeypress,(當value發生變化的時候) onchange, onkeyup |
|
IE10 | onkeydown, onkeypress, onkeyup |
onkeydown, onkeyup |
onkeydown, onkeypress, onkeyup |
onkeydown, onkeyup |
onkeydown, onkeypress, onkeyup |
從上面的表格中能夠看出,不一樣的瀏覽器對不一樣的按鍵觸發的事件仍是有所差異的。尤爲是IE,按回車的時候不會出發onchange事件。
此外全部的瀏覽器,在onblur的時候,若是input的value發生了變化,都會觸發onchange事件。可是在輸入的過程當中,onchange事件並不回被觸發,因而否認了我本身的對於onchange事件觸發查詢的猜測。
接下來是在使用中文輸入法的時候觸發的事件列表
普通輸入abc | 空格,填入內容 | ||
Chrome | 每次按鍵 onkeydown, onkeyup |
onkeydown, onkeyup |
|
Firefox | 只在第一次按鍵時觸發 onkeydown |
onkeyup | |
IE10 | 每次按鍵 onkeydown, onkeyup |
onkeydown, onkeyup |
|
從上面的表中能夠看出,若是想在用戶輸入過程當中,經過onkeydown或者onkeyup事件來捕獲用戶的輸入,而且觸發匹配調用是不太可行的,尤爲是在firefox上,用戶的鍵盤事件根本沒有辦法馬上獲取。因此咱們也就能夠理解,爲何google的搜索框,在firefox中,也只能等待中文內容被天津輸入框以後才能進行匹配搜索。
可是對於IE,依然可以得到keydown和keyup事件,那就夠得到keycode,天然研究可以知道用戶按了什麼鍵,經過用戶按鍵進行匹配應該也是能夠作到的。爲何ie上對中文輸入的反映與firefox是同樣的呢。
繼續搜索才發現,原來在中文輸入框的狀況下,鍵盤事件並不能傳遞真實的用戶按鍵keycode。因而對代碼進行修改,加入了keycode和charcode的輸出:這裏還遇到了firefox和ie對event參數的兼容性問題,前臺開發真是不易啊。
1 <html> 2 <head> 3 <script type="text/javascript"> 4 function onChange(){ 5 console.log("onchange!"); 6 } 7 function onKeyDown(e){ 8 e = e || window.event; 9 console.log("onkeydown" + " keyCode:"+e.keyCode+" charCode:"+e.charCode); 10 } 11 function onKeyUp(e){ 12 e = e || window.vent; 13 console.log("onkeyup" + " keyCode:"+e.keyCode+" charCode:"+e.charCode); 14 } 15 function onKeyPress(e){ 16 e = e || window.event; 17 console.log("onkeypress" +" keyCode:"+e.keyCode+" charCode:"+e.charCode); 18 } 19 </script> 20 21 </head> 22 23 <body> 24 <input type="text" onchange="onChange()" onkeydown="onKeyDown(event)" onkeyup="onKeyUp(event)" onkeypress="onKeyPress(event)"/> 25 </body> 26 </html>
各個瀏覽器的測試結果以下:
a | ESC | 中文輸入法a | 中文輸入法接着按b | 空格,填入中文內容 | |||
Chrome | |||||||
Firefox |
onkeydown keyCode:65 charCode:0
onkeypress keyCode:0 charCode:97
onkeyup keyCode:65 charCode:0
|
onkeydown keyCode:27 charCode:0
onkeypress keyCode:27 charCode:0
onkeyup keyCode:27 charCode:0
|
onkeydown keyCode:0 charCode:0 | 沒有事件 | onkeyup keyCode:32 charCode:0 | ||
IE10 | onkeydown keyCode:65 charCode:0 onkeypress keyCode:97 charCode:97 onkeyup keyCode:65 charCode:0 |
onkeydown keyCode:27 charCode:0 |
onkeydown keyCode:229 charCode:0 |
onkeydown keyCode:229 charCode:0 |
onkeydown keyCode:229 charCode:0 |
這裏有人可能會對keyCode和charCode產生好奇。我也是寫這篇博客的時候才瞭解到這個知識點:keyCode表示按下鍵的數字代碼,也叫鍵碼,charcode表示按鍵的Unicode,也叫字符編碼。這裏有一篇文章介紹都比較詳細,你們能夠具體去看一下:http://blog.sina.com.cn/s/blog_65c2ec5e0101blj6.html
本文的重點是中文輸入,你們能夠看到,在chrome和ie中,使用中文輸入法輸入的時候,全部的keydown事件,keycode都是229,keyup事件的keycode表示正確。所以經過對keyup事件的捕獲,應該能獲取用戶的按鍵狀況。可是對於Firefox,只能等到用戶按空格或回車將輸入的內容填入框中,才能捕獲keyup事件。而後經過輸入的內容來進行匹配查詢。
因此這個中文輸入法自動匹配問題的最終解決方案也比較明顯了:捕獲keyup事件,而後經過輸入框裏的內容進行匹配查詢。
查看原有的code,果真只對keydown和keypress(針對opera)事件進行了捕獲,而沒有用到keyup,因此修改的內容就是將keydown事件改成keyup事件。
一個小小的中文輸入問題須要這麼多的搜索和調試才能完美解決,並且這裏只對chrome,firefox,ie作了支持,若是須要加上opera,safari,須要的工做可能更多。但相信這些問題碰到一個少一個,記錄下來也但願能爲別人帶來一些便利。同時也盼望着未來各瀏覽器廠商之間規範的統一和相互兼容,讓前端工程師能有更加順暢的開發過程。