为啥使用 element.innerHTML 后事件监听器会停止工作?
Posted
技术标签:
【中文标题】为啥使用 element.innerHTML 后事件监听器会停止工作?【英文标题】:Why can event listeners stop working after using element.innerHTML?为什么使用 element.innerHTML 后事件监听器会停止工作? 【发布时间】:2016-09-23 17:39:40 【问题描述】:我是 javascript 的初学者。一本 JavaScript 书说element.innerhtml
的一个缺点是:
事件处理程序可能不再按预期工作。
我不明白这是什么意思。谁能举个例子?
【问题讨论】:
这是一个数组/JSON 类比:var obj = [Infinity]; var str = JSON.stringify(obj); str = str.slice(0, -1) + ', 42]'; obj = JSON.parse(str);
。这是向数组添加新元素的一种非常可怕的方式。结果是数组[null, 42]
,因为JSON 不能代表Infinity
。与 DOM 类似,任何绑定到元素的事件处理程序在转换为 HTML 时都会丢失,因为 HTML 本身无法存储绑定函数的表示。
【参考方案1】:
很可能,它指的是一些人用来在末尾插入 HTML 的技术:
element.innerHTML += "inserted HTML";
这将获取当前的 HTML,将其与插入的 HTML 连接起来,然后全部解析。
作为副作用,现有元素的所有内部状态(如事件侦听器、已检查状态等)都将丢失。
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>
【讨论】:
【参考方案2】:innerHTML
是元素的html内容的字符串表示。获取这些内容没有副作用,但重置它会强制浏览器生成 new 元素。
文档中的每个 HTML 标记都被浏览器解析为唯一的 DOM HTMLElement 对象。事件处理程序绑定到这些元素。通过重置innerHTML
属性,浏览器会移除旧元素,并使DOM 解析器根据新的html 字符串创建其他元素对象。当一个元素被移除时,它的事件处理程序也被移除。
假设您有一个元素通过处理程序响应它的点击事件,当元素被删除时,您无法单击它,因此您会觉得处理程序也被删除了。事件处理程序的垃圾收集方式取决于已编写的代码和 JavaScript 解释器的工作方式。
【讨论】:
【参考方案3】:因为当您使用 Javascript 和 element.innerHTML 函数动态创建元素时,新创建的元素可能无法按预期响应事件侦听器方法。
【讨论】:
以上是关于为啥使用 element.innerHTML 后事件监听器会停止工作?的主要内容,如果未能解决你的问题,请参考以下文章
AngularJS element.innerHTML 在指令内未定义
通过纯 JS 从 tablerow//<tr onClick(myFunction> 获取 element.innerHTML