Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript:addEventListener在for循环中不工作_Javascript_Arrays_For Loop_Addeventlistener - Fatal编程技术网

Javascript:addEventListener在for循环中不工作

Javascript:addEventListener在for循环中不工作,javascript,arrays,for-loop,addeventlistener,Javascript,Arrays,For Loop,Addeventlistener,情境:我从一个API获得一个JSON数组。“div”来自代码前面的getElementByID 问题:addEventListener仅附加到列表中的最后一个元素 for(var i = 0; i < JSONarray.response.artists.length; i++){ var artistName = JSONarray.response.artists[i]; div.innerHTML += "<h4 id=\"artist" + i

情境:我从一个API获得一个JSON数组。“div”来自代码前面的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);
    }
for(var i=0;i
奇怪的事情:如果我把addEventListener放在它自己的for循环中(使用完全相同的循环脚本),它会非常高兴,我的所有列表项都会得到它们的侦听器

问题:我不能将所有内容都放在一个for循环中,这是有原因的吗?还是我的代码

注意:我正在使用Chrome来运行它,如果它碰巧是浏览器的东西


谢谢你的时间

看起来像是dom更新问题

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 + '" onclick="moreInfo(this)">Artist Name: ' +  artistName.name + '</h4>';
}
for(var i=0;i

演示:

您在每次迭代for循环时都修改div的innerHTML,从而导致绑定到某个以该div为父节点的节点的所有事件处理程序丢失,因为修改innerHTML会导致从HTML重新创建所有子节点

考虑
div.innerHTML+=foo
实际上是
div.innerHTML=div.innerHTML+foo的缩写我的意思应该很清楚

编辑:我意识到我的答案已经被接受了(截至2013年4月8日),但我仍然觉得我可以用更好的措辞

可以将
node.innerHTML=bar
想象为“用可以从给定字符串(在
bar
中)解释的HTML替换节点的所有子节点”。它恰好是给定字符串的一部分,您通过
node.innerHTML
对节点以前的子节点进行HTML序列化。。因此,您可能失去的不仅仅是事件处理程序

如您所见,这不是添加html的最佳方式

作为补充说明,假设您必须向一个节点添加一组子节点,如果事件可以冒泡(请参阅,或更完整的列表),那么您也可以向父节点添加一个事件处理程序,而不是向每个子节点添加一个事件处理程序,在现代浏览器(IE9+)中,许多事件可以在冒泡时进行处理。到目前为止,我还没有直接处理DOM中的事件冒泡,但是许多第三方库很容易支持这种事件委托。使用jQuery,查看
jQuery.on
,绑定声明的工作方式如下:

 jQuery(parentnodeselector).on(eventname,childselector)
if (newH4.addEventListener) {
    newH4.addEventListener("click", moreInfo, false);
} else if (newH4.attachEvent) {
    newH4.attachEvent("onclick", moreInfo);
} else {
    newH4.onclick = moreInfo;
}

顺便说一句,你自己处理冒泡事件并不难。。。但是,如果事件是通过正确的子级冒泡出现的,则需要能够通过
event.target
event.target
识别事件的父级。

内联事件处理程序,尤其是当使用
innerHTML
动态创建时,不应鼓励这样做。我甚至记得读到过关于IE在这种情况下所发生的不好的事情。尝试使用类似这样的方法,它使用更合适的方法向DOM添加元素:

for (var i = 0; i < JSONarray.response.artists.length; i++) {
    var artistName = JSONarray.response.artists[i];
    var newH4 = document.createElement("h4");
    newH4.id = "artist" + i;
    newH4.accessKey = artistName.id;    // You might have to use newH4.setAttribute("accessKey", artistName.id) instead
    newH4.innerHTML = "Artist Name: " +  artistName.name;
    newH4.addEventListener("click", moreInfo, false);
    div.appendChild(newH4);
}

此外,不应在循环中的同一元素上使用
innerHTML
。更有效的方法是创建一个大字符串并附加到for循环内的字符串,然后在循环后的元素上设置
innerHTML
。随着
JSONarray.response.artists
数组大小的增加,这一点变得更加重要。

您确定在引用
moreInfo
的地方没有内嵌匿名函数吗?如果您不需要对单击事件进行任何特殊处理,只需使用document.getElementById(…).onclick=moreInfo;或者只是内联,因为您的
moreInfo
是如何定义的?哦,刚刚接受了关于innerHTML的多重替换的教育。从未在innerHTML上使用过事件处理程序,因此从未遇到此问题。自从发现jQuery之后,我就再也不用自己的Jason处理了。您是否考虑过jQuery,它将极大地简化您对语法问题的处理;转义
moreInfo()
中的引号。我很想知道为什么原始代码不起作用。我只是厌倦了它,它成功地创建了DOM元素,使用了正确的ID和
文档。getElementByID
在循环中成功地找到了它们,但只有最后一个元素附加了处理程序。@akonsu True True,我想我的观点是,如果你以“正确”的方式做事,就不应该有这样的问题。不管怎样,奇怪的原因很有趣。你有小提琴要测试吗?这是我根据@ArunPJohny的一把小提琴创作的一把:@akonsu如果你看看JayC的答案,这应该可以解释为什么:)这是我从未听过的有趣信息。我不知道使用innerHTML会抛弃EventHandler。他们不知道的小事情。@AsdAsd如果你不使用
innerHTML
:)@AsdAsd:是的。。。尽管我知道你接受了我的回答,我还是添加了一些信息,只是为了澄清,还有另一个你可能不知道的事件绑定选项。