为什么事件侦听器在使用 element.innerHTML 后会停止工作?

Why can event listeners stop working after using element.innerHTML?

我是 JavaScript 的初学者。 JavaScript 一本书说 element.innerHTML 的缺点之一是:

Event handlers may no longer work as intended.

我不明白这是什么意思。有人可以给我举个例子吗?

因为当您使用 element.innerHTML 函数动态创建带有 Javascript 的元素时,新创建的元素可能不会按预期响应事件侦听器方法。

innerHTML 元素 的 html 内容的 字符串表示形式 。获取这些内容没有副作用,但重置它会强制浏览器生成 new 元素。

文档中的每个 HTML 标签都被浏览器解析为唯一的 DOM HTMLElement 对象。事件处理程序绑定到这些元素。通过重置 innerHTML 属性,浏览器移除旧元素并使 DOM 解析器根据新的 html 字符串创建其他元素对象。当一个元素被移除时,它的事件处理程序也被移除。

假设您有一个元素通过处理程序响应它的点击事件,当元素被删除时您无法点击它,这让您感觉处理程序也被删除了。垃圾收集事件处理程序的方式取决于已编写的代码和 JavaScript 解释器的工作方式。

很可能是指某些人用来在最后插入HTML的技巧:

element.innerHTML += "inserted HTML";

这将获取当前的 HTML,将它与插入的连接起来,然后全部解析。

作为副作用,现有元素的所有内部状态(如事件侦听器、checkedness 等)都将丢失。

var btn = document.querySelector("button");
btn.addEventListener("click", function() {
  btn.textContent = "I won't work anymore";
  document.body.innerHTML += "<p>Inserted text</p>";
});
<button>Click me to insert HTML</button>

相反,如果你想在一个元素的末尾插入一些HTML,你可以使用

element.insertAdjacentHTML('beforeend', "inserted HTML");

这将保留现有元素。

var btn = document.querySelector("button");
btn.addEventListener("click", function() {
  btn.textContent = "I still work";
  document.body.insertAdjacentHTML("beforeend", "<p>Inserted text</p>");
});
<button>Click me to insert HTML</button>

另一种选择,如果您不介意将插入的内容包裹在元素中,则使用 appendChild:

var btn = document.querySelector("button");
btn.addEventListener("click", function() {
  btn.textContent = "I still work";
  var wrapper = document.createElement('div');
  wrapper.innerHTML = "<p>Inserted text</p>";
  document.body.appendChild(wrapper);
});
<button>Click me to insert HTML</button>