div按回车调用focus()聚焦按钮为何触发按钮click事件?
问题原因与解决方案
这是个典型的浏览器事件流程导致的小坑,我来帮你理清楚前因后果:
为什么会触发按钮的click?
当你在设置了tabindex="0"的div上按下回车键时,整个事件流程是这样的:
- div捕获到
keydown事件,执行你的btnKeyDown函数,里面调用了按钮的focus()方法,此时焦点立刻转移到按钮上。 - 但同一个回车键的事件还没处理完——浏览器会继续派发
keyup事件,而此时焦点已经在按钮上了,按钮的默认行为就是:当它获得焦点时,按下并释放回车键(keyup)会自动触发click事件。 - 说白了,你相当于在按钮聚焦的瞬间,让它“接收到”了同一个回车键的释放动作,浏览器就把这个动作转换成了按钮的点击事件。
怎么解决?
这里有两个靠谱的方案,你可以根据需求选:
方案1:阻止div上keydown的默认行为
直接中断浏览器对这个回车键的后续处理,这样就不会有后续的keyup触发按钮的click了。修改代码如下:
首先修改HTML的事件绑定,传入event参数:
<div id='btn' onkeydown="btnKeyDown(event)" tabindex='0'>Click1</div> <button id='btn1' onclick="btnclick()">Click Me!2</button>
然后修改JS函数:
function btnclick() { console.log('button click triggered'); } function btnKeyDown(event) { console.log('key down triggered'); document.getElementById('btn1').focus(); event.preventDefault(); // 阻止浏览器继续处理这个按键的默认行为 }
方案2:延迟执行focus操作
让焦点转移的动作等当前的事件循环结束后再执行,这样按键的后续事件会在div上处理完,不会影响到按钮。修改JS函数即可:
function btnclick() { console.log('button click triggered'); } function btnKeyDown() { console.log('key down triggered'); // 用setTimeout把focus放到下一个事件循环 setTimeout(() => { document.getElementById('btn1').focus(); }, 0); }
这两种方法都能避免触发按钮的click事件,你可以根据自己的场景选择~
内容的提问来源于stack exchange,提问作者Madhan
相关产品推荐
相关产品推荐

