情况:我从 API 获取 JSON 数组。 “div”来 self 代码中前面的 getElementByID。
问题:addEventListener 仅附加到列表中的最后一个元素。
for(var i = 0; i < JSONarray.response.artists.length; i++){
var artistName = JSONarray.response.artists[i];
div.innerHTML += "<h4 id=\"artist" + i + "\" accessKey=\"" + artistName.id + "\">Artist Name: " + artistName.name + "</h4>";
document.getElementById("artist" + i).addEventListener("click", moreInfo, false);
}
奇怪的事情:如果我将 addEventListener 放在它自己的 for 循环中(具有完全相同的循环脚本),它会非常高兴,并且我的所有列表项都会获得它们的监听器。
问题:我无法将所有内容放入一个 for 循环中是否有原因,或者这是我的代码?
注意:我正在使用 Chrome 来运行它,如果它恰好是浏览器的问题的话。
感谢您的宝贵时间!
最佳答案
您正在每次迭代 for 循环时修改 div 的innerHTML,从而导致绑定(bind)到以该 div 作为父节点的某个节点的所有事件处理程序丢失,因为修改innerHTML 会导致从 HTML 重新创建所有子节点。
考虑一下 div.innerHTML += foo;
实际上是 div.innerHTML = div.innerHTML + foo;
的简写,它应该很明显我的意思。
编辑:我意识到我的答案已被接受(截至 2013 年 4 月 8 日),但我仍然觉得我可以措辞更好一点。
将 node.innerHTML = bar
视为“将节点子节点的所有内容替换为可以从给定字符串(在 bar
中)解释的任何 HTML”。它恰好作为给定字符串的一部分发生,您通过 node.innerHTML
给出了节点前子节点的 HTML 序列化。所以您可能失去的不仅仅是事件处理程序!
如您所见,这不是添加 html 的最佳方式。
作为旁注,假设您确实必须向节点添加一堆子节点,如果事件可以冒泡(请参阅 HTML DOM: Which events do not bubble? ,或更完整的列表 Wikipedia's article on DOM events ) ,您还可以向父节点添加事件处理程序,而不是向每个子节点添加处理程序,并且在现代浏览器(IE9+)中,可以按原样处理许多事件>冒泡。我最近还没有直接搞乱 DOM 中的事件冒泡,但许多第三方库很容易支持这种事件委托(delegate)。对于 jQuery,查看 jQuery.on
,绑定(bind)声明的工作方式类似于:
jQuery(parentnodeselector).on(eventname,childselector)
据我所知,自己处理事件冒泡并不是很难...您需要能够通过event.target
和event进行识别不过,如果事件通过正确的子级向上冒泡,则为 .target
的父级。
关于Javascript:addEventListener 无法在 for 循环中工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15871591/