onkeyup事件中如何处理USB条码扫描器的Shift前置按键识别问题
问题根因
- 你当前使用
keyup事件监听输入,而条码扫描器模拟上档字符(如大写字母、:这类需要按Shift才能输出的符号)的逻辑是:先按下Shift → 按下对应字符键 → 松开Shift → 松开字符键。你在keyup阶段直接过滤了Shift事件,此时拿到的字符键的event.key已经丢失了Shift激活状态,只能拿到原始下档字符(比如;而不是:) event.key受当前系统的键盘布局影响,Win7设备如果是多语言键盘布局,就会出现你测试结果里的ò、ç这类错误字符- 不同型号扫描器的键事件触发时序存在差异,Win7的键盘事件响应逻辑也和新系统不同,才会出现换设备就失效的问题
修复方案
1. 替换监听事件为keydown,使用event.code做物理键位映射
keydown触发时event.shiftKey的状态是准确的,event.code是物理键位标识,不受系统键盘布局影响,我们可以固定映射英文标准键盘的字符,避免布局干扰。
2. 新增英文键盘上档字符映射表
提前定义好Shift激活时对应物理键的输出字符,直接覆盖event.key的取值。
3. 可选:加输入超时判断区分扫描输入和手动输入
扫描器输入每个字符的间隔通常小于10ms,加超时可以避免手动误触键盘产生脏数据。
修改后的参考代码:
// 英文标准键盘上档字符映射表,按需补充你需要的符号 const shiftKeyMap = { 'Semicolon': ':', 'Digit1': '!', 'Digit2': '@', 'Digit3': '#', 'Digit4': '$', 'Digit5': '%', 'Digit6': '^', 'Digit7': '&', 'Digit8': '*', 'Digit9': '(', 'Digit0': ')', 'Minus': '_', 'Equal': '+', 'BracketLeft': '{', 'BracketRight': '}', 'Backslash': '|', 'Quote': '"', 'Comma': '<', 'Period': '>', 'Slash': '?', 'Backquote': '~' }; let barcode = ''; let scanTimer = null; // 扫描输入超时时间,超过50ms没有新输入就认为本次扫描结束,可按需调整 const SCAN_TIMEOUT = 50; document.addEventListener("keydown", (event) => { // 过滤修饰键本身的事件,保留修饰键状态给后续字符键使用 if (event.isComposing || ['Shift', 'Control', 'Meta', 'Alt'].includes(event.key)) { return; } if (containerLoading.classList.contains("d-none")) { showLoading(); } if (!containerLoading.classList.contains("d-none")) { // 清掉上一次的超时计时器 clearTimeout(scanTimer); if (event.key === "Enter" || event.key === "Tab") { if (barcode !== "") { websocket.send(`<ART>${barcode}</ART>`); barcode = ""; } } else { let currentChar = event.key; // Shift激活时,优先用映射表取上档字符,字母直接转大写 if (event.shiftKey) { if (shiftKeyMap[event.code]) { currentChar = shiftKeyMap[event.code]; } else if (currentChar.length === 1 && /[a-z]/.test(currentChar)) { currentChar = currentChar.toUpperCase(); } } barcode += currentChar; } // 超时重置条码,避免和手动输入混淆 scanTimer = setTimeout(() => { barcode = ''; }, SCAN_TIMEOUT); } });
注意事项
如果还有其他符号映射错误,你可以打印event.code和event.shiftKey的取值,补充到shiftKeyMap映射表里即可覆盖所有错误情况。
内容的提问来源于stack exchange,提问作者NiceToMytyuk
相关产品推荐
相关产品推荐

