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

为何ES6中addEventListener仅生效一次?

为什么你的addEventListener只生效一次?

嘿,我懂你碰到的问题——点一次按钮能正常计数,再点就没反应了对吧?咱们来拆解下问题到底出在哪。

先贴出你的代码方便分析:

JavaScript代码:

let input = document.querySelector(".send"); 
let i = 0; 
input.addEventListener('click',(e)=>{ 
  e.preventDefault(); 
  i+=1; 
  document.body.innerHTML += i; 
});

HTML代码:

<input type="submit" class="send">

问题根源:DOM元素被销毁了!

罪魁祸首就是这句 document.body.innerHTML += i。当你用这种方式修改innerHTML时,浏览器会做两件关键的事:

  1. 把当前<body>里的所有内容(包括你绑定了事件的那个.send按钮)全部移除并销毁
  2. 把原来的内容加上新的i值,重新渲染成一套全新的DOM元素

简单说:你第一次点击后,原来的按钮已经被删掉了,新生成的按钮虽然看起来一模一样,但它是个完全没绑定事件的新元素,所以后续点击自然没反应。

几种靠谱的解决方案

方案1:不要修改整个body的innerHTML,单独更新计数元素

这是最推荐的方式,避免动到按钮所在的DOM结构:

let input = document.querySelector(".send"); 
let i = 0;
// 先创建一个专门用来显示计数的元素
let counter = document.createElement('span');
document.body.appendChild(counter);

input.addEventListener('click',(e)=>{ 
  e.preventDefault(); 
  i+=1; 
  // 只更新计数元素的内容,不碰其他DOM
  counter.textContent = i;
});

方案2:用事件委托(Event Delegation)

如果一定要修改innerHTML,可以把事件绑定在不会被销毁的父元素(比如<body>)上,利用事件冒泡来处理:

let i = 0; 
// 把事件绑定在body上,监听所有点击
document.body.addEventListener('click',(e)=>{ 
  // 判断点击的是不是目标按钮
  if(e.target.classList.contains('send')){
    e.preventDefault(); 
    i+=1; 
    document.body.innerHTML += i; 
  }
});

不管按钮被重新渲染多少次,只要它带.send类,点击事件都会被<body>捕获并处理。

方案3:每次修改后重新绑定事件(不推荐,但可用)

这个方法有点冗余,但也算一种思路——每次更新innerHTML后,重新找到新按钮并绑定事件:

let i = 0; 

function bindClickEvent(){
  let input = document.querySelector(".send"); 
  input.addEventListener('click',(e)=>{ 
    e.preventDefault(); 
    i+=1; 
    document.body.innerHTML += i; 
    // 重新给新生成的按钮绑定事件
    bindClickEvent();
  });
}

// 初始绑定一次
bindClickEvent();

内容的提问来源于stack exchange,提问作者Rso Invisible

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:12:07