点击按钮结合小键盘数字触发对应函数的异常问题排查
解决方案
问题根源
你遇到的所有异常都来自alert的线程阻塞特性:点击按钮触发alert弹窗时,JS主线程会被挂起,此时松开小键盘按键的keyup事件无法正常触发执行,导致全局存储的按键状态一直被标记为true,后续就会出现按键状态不更新、无按键点击也触发逻辑的问题。
修复后完整代码
<!DOCTYPE html> <html> <head> <title>Page Title</title> </head> <body> <button type="button" id="b41" onclick="test_ks(event)">Shape Anchor Point</button> <script> const pressedButtons = {}; // 监听按键按下事件,仅记录小键盘1-9的状态 window.addEventListener('keydown', e => { if(e.code.startsWith('Numpad') && /\d$/.test(e.code)) { pressedButtons[e.code] = true; } }) // 监听按键松开事件,更新对应按键状态 window.addEventListener('keyup', e => { if(e.code.startsWith('Numpad') && /\d$/.test(e.code)) { pressedButtons[e.code] = false; } }) // 页面失焦时重置所有按键状态,避免切换页面等场景导致状态残留 window.addEventListener('blur', () => { Object.keys(pressedButtons).forEach(key => pressedButtons[key] = false) }) function test_ks(event) { if (pressedButtons.Numpad1) { // 阻塞类操作放入setTimeout异步执行,避免阻塞键盘事件回调 setTimeout(() => alert('numpad 1'), 0) // 此处替换为你的1号自定义函数 } else if (pressedButtons.Numpad2) { setTimeout(() => alert('numpad 2'), 0) // 此处替换为你的2号自定义函数 } // 以此类推补充Numpad3到Numpad9的逻辑即可 } </script> </body> </html>
核心优化说明
- 改用标准
addEventListener绑定事件,避免覆盖全局的按键回调逻辑 - 用
e.code识别小键盘按键,无需记忆硬编码键值,适配不同键盘布局,可读性更高 - 新增页面失焦状态重置逻辑,避免切页、最小化等场景导致的按键状态残留
- 阻塞类操作(如alert、confirm等)放入异步队列执行,不会阻止键盘事件回调的正常触发,按键状态可以正常更新
- 仅监听记录小键盘1-9的按键状态,减少无关判断逻辑
如果你的实际业务中调用的是普通自定义函数,没有阻塞主线程的操作,不需要加setTimeout也可以正常运行。
内容的提问来源于stack exchange,提问作者manjunath karanth
相关产品推荐
相关产品推荐

