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

为何仅最后一个输入框触发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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 15:15:37