我遇到的实际问题就像下面的测试代码一样
我需要在一个函数中包含一堆事件加法器,并多次调用它
它生成相同的结果,即不适用于每个元素的事件
window.onload = function() {
var body = document.body;
var elText = '<input id="randId" type="text"/>';
var elTmp;
var ids = [];
var times = 3;
var randId = function(){
return Math.random().toString(36).substr(2,9);
};
var setEvent = function(el, text) {
el.addEventListener('click', function(e) {
el.value = text;
});
};
for (var i = 0; i < times; i++) {
ids.push(randId());
body.innerHTML += elText.replace('randId', ids[ids.length - 1]);
elTmp = document.getElementById(ids[ids.length - 1]);
setEvent(elTmp, 'this is ' + (i+1));
}
};
甚至将这些代码包装在一个闭包中,该事件仅适用于最后创建的元素,前两个不是
请参阅此topic
for (var i = 0; i < times; i++) {
ids.push(randId());
body.innerHTML += elText.replace('randId', ids[ids.length - 1]);
elTmp = document.getElementById(ids[ids.length - 1]);
(function(_i) {
setEvent(elTmp, 'this is ' + (_i+1));
})(i);
}
答案 0 :(得分:1)
问题在于每次迭代都会改变所有内部HTML。发生这种情况时,将删除所有先前的事件侦听器(因为元素已从DOM中删除)。我刚刚回答了similar question。
根据MDN:
.innerHTML
- 删除所有元素的子节点,解析内容字符串并将结果节点指定为元素的子节点。
要解决此问题,您可以使用.insertAdjacentHTML()
method来插入元素。在这样做时,没有触及/删除其他HTML,因为这只是插入 HTML。
for (var i = 0; i < times; i++) {
ids.push(randId());
body.insertAdjacentHTML('beforeend', elText.replace('randId', ids[ids.length - 1]));
elTmp = document.getElementById(ids[ids.length - 1]);
setEvent(elTmp, 'this is ' + (i+1));
}
当然,您也可以使用.appendChild()
method。
答案 1 :(得分:0)
当您再次呼叫innerHTML
时,正文内容已被强制,Event Listener
会一次又一次被删除。
我认为您应该使用$('').append()
中的Jquery
方法添加Element
。
答案 2 :(得分:0)
对于解决方案,Josh Crozier answer已经存在。我只想解释一下为什么JS正在使用+=
附加html时保留之前的html时删除以前的事件处理程序。仔细看看这个:
body.innerHTML += elText.replace('randId', ids[ids.length - 1]);
它实际上是以下的捷径:
body.innerHTML = body.innerHTML + elText.replace('randId', ids[ids.length - 1]);
所以,首先你得到的body.innerHTML
只是一个文本字符串,没有绑定到它的事件处理程序,你用它附加新文本,之后你将其设置为{{1 }}。在那段时间,它以Josh Crozier突出显示:
body.innerHTML
- 删除所有元素的子节点,解析内容字符串并将结果节点指定为元素的子节点。