You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

按下按钮的Enter键并聚焦到下一个文本框后,为何下一个文本框会触发keyup事件?

按下按钮的Enter键并聚焦到下一个文本框后,为何下一个文本框会触发keyup事件?

这个问题我之前也碰到过,其实是键盘事件的传播时机在搞鬼!

问题原因拆解:

当你在按钮上按下Enter键时,会按以下顺序触发事件:

  1. 按钮先接收到keydown事件(此时Enter键处于按下状态)
  2. 浏览器的默认行为:按钮的Enter按键会自动触发它的click事件,你的click处理函数执行,立刻把焦点转移到了下一个输入框(item-2)
  3. 当你松开Enter键时,此时焦点已经在输入框item-2上了,所以这个输入框会捕获到keyup事件;刚好你的输入框绑定了keyup的Enter监听逻辑,于是又触发了跳转,导致连续跳过了两个元素。

几种靠谱的解决方案:

方案1:改用keydown事件处理输入框跳转

keydown是在按键按下瞬间触发的,此时焦点还停留在当前元素上,不会出现焦点转移后捕获同个按键事件的问题:

const selects = document.querySelectorAll('.item');
selects.forEach(el => el.addEventListener('keydown', e => { 
    if (e.key === 'Enter' || e.keyCode === 13) {
        e.preventDefault(); // 阻止默认行为,避免额外的浏览器动作
        let idx = parseInt(e.currentTarget.getAttribute("index"));
        focusToTheNextControl(idx);
    }
}));

方案2:直接处理按钮的keyup事件,阻止默认click触发

按钮的Enter按键默认会触发click事件,我们可以直接接管按钮的键盘事件,避免后续的意外触发:

// 替换原来的按钮click监听
document.querySelector('.btn-item').addEventListener('keyup', e => { 
    if (e.key === 'Enter' || e.keyCode === 13) {
        e.preventDefault(); // 阻止默认的click事件触发
        let idx = parseInt(e.currentTarget.getAttribute("index"));
        focusToTheNextControl(idx);
    }
});

这样按钮的Enter按键事件完全由我们处理,焦点转移后,松开Enter的事件已经被按钮处理完毕,输入框不会再接收到这个keyup。

方案3:在输入框的keyup事件中增加焦点校验

确保只有当输入框本身是当前焦点元素时,才执行跳转逻辑:

const selects = document.querySelectorAll('.item');
selects.forEach(el => el.addEventListener('keyup', e => { 
    if ((e.key === 'Enter' || e.keyCode === 13) && document.activeElement === el) {
        let idx = parseInt(e.currentTarget.getAttribute("index"));
        focusToTheNextControl(idx);
    }
}));

关于你用setTimeout有效的原因:

延迟1秒后,Enter键的keyup事件已经完全处理完成了,此时再聚焦输入框,自然不会触发它的keyup监听。但这只是临时的 workaround,上面的方案更稳定可靠。

备注:内容来源于stack exchange,提问作者Qudu Ta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.15 10:33:08