点击按钮后空格键keypress事件监听器失效问题
问题表现
点击.button-div内任意升级按钮后,按下空格键会自动触发上一次点击按钮的绑定逻辑,原本注册在document上的空格键keypress事件不会执行,需要保证空格键按下时正常触发自定义的player.shoot()逻辑,不被按钮拦截。
相关代码
HTML
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Pew Pew</title> </head> <body> <canvas id="gameCanvas" height="800px" width="1000px"></canvas> <div class="button-div"> <button id="atkUp" onclick="player.attackSpeedUp()">1 Atk Speed - 1c</button> <button id="dmgUp" onclick="player.damageUp()">1 Damage - 1c</button> <button id="multishotUp" onClick="player.multishotUp()">1 Multi-Shot - 1c</button> <button id="moveSpeedUp" onClick="player.moveSpeedUp()">1 Move Speed - 1c</button> <button id="armorUp" onclick="player.armorUp()">1 Armor - 1c</button> <p>UPGRADES</p> </div> </body> </html>
JavaScript
document.addEventListener("keypress", (event) =>{ if(event.keyCode == 32){ player.shoot(); } }, false);
原因说明
这是浏览器原生的默认交互规则:点击按钮后按钮会自动获取焦点,焦点停留在按钮上时,按下空格键会直接触发该按钮的click事件,事件不会冒泡到document层级,因此绑定的全局空格监听无法触发。
解决方案
以下三种方案任选其一即可生效:
- 方案1:点击按钮后主动移除焦点
最简单的实现方式是点击按钮后调用blur()让按钮失焦,不需要逐个修改原有内联事件,直接批量绑定监听即可:
如果偏好直接改内联属性,在原有onclick逻辑末尾加document.querySelectorAll('.button-div button').forEach(btn => { btn.addEventListener('click', function() { this.blur() }) })this.blur()即可,示例:<button id="atkUp" onclick="player.attackSpeedUp();this.blur()">1 Atk Speed - 1c</button> - 方案2:拦截按钮上的空格键默认行为
给所有升级按钮绑定键盘事件,阻止空格键触发按钮点击的默认逻辑:document.querySelectorAll('.button-div button').forEach(btn => { btn.addEventListener('keydown', e => { if(e.keyCode === 32) e.preventDefault() }) }) - 方案3:调整全局键盘监听的触发阶段
把全局监听从keypress换成更早触发的keydown,注册在捕获阶段,同时阻止空格的默认行为:
注意:该方案不需要修改原有按钮逻辑,但要确保监听注册在捕获阶段,否则事件还是会先被焦点按钮拦截。// 第三个参数设为true,在捕获阶段就触发事件,比按钮的默认处理更早执行 document.addEventListener("keydown", (event) =>{ if(event.keyCode == 32){ event.preventDefault() player.shoot() } }, true);
内容的提问来源于stack exchange,提问作者Nate Baker
相关产品推荐
相关产品推荐

