为何仅最后一个输入框触发addEventListener?JS事件绑定异常
为何仅最后一个输入框触发时才打印日志?
这一定是我不了解的JS特殊机制,为何以下代码仅在最后一个输入框(Id 3)改变时才打印日志?我已为所有输入框添加addEventListener,本应所有输入框触发时都输出日志。
代码示例
JavaScript代码
function constructInputs(ctx, id) { console.log(id); ctx.innerHTML += `<input type="text" id="${id}_textInput"></br>`; let textInput = document.getElementById(`${id}_textInput`); textInput.addEventListener("input", function (e) { console.log(id); }); } const ctx = document.getElementById("centerdiv"); constructInputs(ctx, '1'); constructInputs(ctx, '2'); constructInputs(ctx, '3');
HTML代码
<body> <div style="text-align: center;" id="centerdiv"> </div> <script src="./main.js"></script> </body>
问题原因
问题出在ctx.innerHTML += ...这个操作上。当你使用innerHTML +=时,浏览器会重新解析整个容器内的HTML并重建所有DOM元素,这意味着之前添加的输入框以及绑定的事件监听器都会被销毁,然后重新创建。
具体流程:
- 第一次调用
constructInputs(ctx, '1'):添加id为1的输入框并绑定事件,此时正常工作。 - 第二次调用
constructInputs(ctx, '2'):执行innerHTML +=后,浏览器把原有内容(id1的输入框)和新内容拼接,重新渲染整个容器。原来的id1输入框被销毁,新创建的id1输入框没有绑定事件,只有刚添加的id2输入框有事件。 - 第三次调用
constructInputs(ctx, '3'):重复上述逻辑,前两个输入框都被重建且丢失事件绑定,只有最后一个id3的输入框保留了事件。
因此最终只有最后一个输入框的事件能触发打印。
解决方法
方法1:使用appendChild创建并追加DOM元素
直接创建单个DOM元素并追加到容器,避免重建整个DOM结构:
function constructInputs(ctx, id) { console.log(id); // 创建输入框元素 const input = document.createElement('input'); input.type = 'text'; input.id = `${id}_textInput`; // 创建换行元素 const br = document.createElement('br'); // 绑定事件 input.addEventListener("input", function (e) { console.log(id); }); // 追加到容器 ctx.appendChild(input); ctx.appendChild(br); } const ctx = document.getElementById("centerdiv"); constructInputs(ctx, '1'); constructInputs(ctx, '2'); constructInputs(ctx, '3');
方法2:一次性拼接HTML再设置innerHTML
先把所有需要的HTML内容拼接完成,一次性赋值给innerHTML,之后再批量为输入框绑定事件:
// 生成单个输入框的HTML字符串 function getInputHtml(id) { return `<input type="text" id="${id}_textInput"></br>`; } const ctx = document.getElementById("centerdiv"); // 一次性设置所有HTML ctx.innerHTML = getInputHtml('1') + getInputHtml('2') + getInputHtml('3'); // 逐个绑定事件 ['1', '2', '3'].forEach(id => { const textInput = document.getElementById(`${id}_textInput`); textInput.addEventListener("input", () => { console.log(id); }); });
内容的提问来源于stack exchange,提问作者pqzpkaot
相关产品推荐
相关产品推荐

