JavaScript onkeyup事件触发多次?求纯JavaScript解决方法
问题原因分析
你的问题核心出在事件重复绑定上:你把enterKeyCheck函数绑定在了onkeyup事件上,这意味着每输入一个字符(每次触发keyup),就会给这个可编辑单元格多绑定一个keypress事件监听器。当你最终按下回车键时,之前绑定的所有keypress监听器都会被触发,所以输出的次数正好等于你之前输入的字符数。
举个例子:如果你输入了3个字符,就会绑定3次keypress监听,按回车时自然会执行3次console.log。
纯JavaScript解决方案
这里给你几种简单有效的解决方式,按需选择:
方案1:一次性绑定事件(推荐)
直接在页面加载完成后,给目标单元格绑定一次keypress事件,从根源避免重复绑定。这样不管输入多少字符,监听器只会存在一个:
console.log('working'); // 页面DOM加载完成后执行绑定操作 document.addEventListener('DOMContentLoaded', function() { // 精准定位到可编辑的单元格 const editableCell = document.querySelector('#test1 td[contenteditable="true"]'); // 只绑定一次keypress事件监听器 editableCell.addEventListener('keypress', function(e) { if (e.which === 13) { e.preventDefault(); // 阻止默认的回车换行行为 console.log('Enter Pressed'); } }); });
对应的HTML部分可以去掉onkeyup属性:
<div id="test1"> <table> <tr> <td>CELL1</td> <td contenteditable="true">CELL2</td> </tr> </table> CHECKING </div>
方案2:在keyup中直接处理回车事件
如果你一定要保留onkeyup的写法,可以直接在enterKeyCheck函数里判断回车,不需要再嵌套绑定keypress事件,这样每次keyup只会执行一次判断逻辑:
console.log('working'); function enterKeyCheck() { // 直接在keyup事件中处理回车判断 if (event.which === 13) { event.preventDefault(); console.log('Enter Pressed'); } };
HTML保持你的原写法即可:
<div id="test1"> <table> <tr> <td>CELL1</td> <td contenteditable="true" onkeyup="enterKeyCheck()">CELL2</td> </tr> </table> CHECKING </div>
方案3:添加标记防止重复绑定(进阶)
如果因为某些场景限制,必须通过onkeyup来绑定keypress,可以给元素添加一个自定义标记,确保监听器只会被绑定一次:
console.log('working'); function enterKeyCheck(x) { // 检查元素是否已经绑定过事件 if (!x.dataset.hasBound) { x.addEventListener('keypress', function(e) { if (e.which === 13) { e.preventDefault(); console.log('Enter Pressed'); } }); // 标记该元素已完成事件绑定 x.dataset.hasBound = 'true'; } };
HTML依然使用你原来的写法,这种方法会给单元格自动添加一个data-has-bound属性,后续触发onkeyup时会跳过重复绑定逻辑。
内容的提问来源于stack exchange,提问作者Ashish Kushwaha
相关产品推荐
相关产品推荐

