在最近開發(fā)的IM中,QA測出了一個BUG,使用中文輸入法輸入@時,不會彈出待選列表,但是英文輸入法就可以,很奇怪,打開調(diào)試工具一看才知道原來在jquery的keydown事件中,獲取到的keyCode的值為229,并非所期待的值。
PS: IM使用Electron框架開發(fā),在輸入框中輸入@時,會彈出可以@的人的列表
代碼是這樣的:
// 監(jiān)聽輸入框的鍵盤事件
$('#chat-input-area').keydown(function (e) {
if (e.key == '@') {
// 邏輯處理...
}
});
網(wǎng)上搜索了好多方案,結(jié)果都不行,這個問題貌似無解啊,原因呢,好像是因為中文輸入法還在處理,會給調(diào)用者先返回一個值,但是js中接收了值就不會再處理了,所以中文輸入法下拿到的keyCode全部都是229,既然網(wǎng)上沒有好的方案,那只能采用最笨的方法了。
每次輸入記錄下輸入框中的值,再次輸入時拿當(dāng)前的值和上次記錄的值做diff,然后拿到差異,也就是最后輸入的數(shù)據(jù)了,但是這個diff算法的效率成了關(guān)鍵了,一個字符一個字符的比對,那效率肯定不高了,拿到當(dāng)前焦點的索引,然后減1,就可以得到最后的輸入字符,但是獲取當(dāng)前的索引還是比較復(fù)雜的,尤其是輸入框里可能會有表情等特殊字符,所以一向比較懶的我選擇了diff方案:
用到了這個開源庫,diff速度很快:
https://github.com/jhchen/fast-diff
下面是部分代碼:
const diff = require('fast-diff');
let inputContent = '';
// 監(jiān)聽輸入框的鍵盤事件
$('#chat-input-area').on('input', function (e) {
let innerText = $('#chat-input-area')[0].innerText;
let d = diff(inputContent, innerText);
// console.log('diff result = ', d);
inputContent = innerText;
let isAt = false;
if (!empty(d)) {
for (let i = 0; i < d.length; i++) {
if (d[i][0] == diff.INSERT && d[i][1].trimLeft(' ') == '@') {
isAt = true;
break;
}
}
}
if (!isAt) {
return;
}
// 處理@
// ...
});
經(jīng)測試,3k+的一篇文章copy進去,然后按下Shift + 2,@彈窗基本上是秒開,根本感覺不到慢,效率還可以。