【问题标题】:Event listeners and closures on HTML collection in for loopfor循环中HTML集合的事件监听器和闭包
【发布时间】:2016-02-19 10:25:31
【问题描述】:

代码是

//Logic which works when the desired element is clicked
function changeArtistPhotoAndBio(prop) {
    var artistPhoto = document.getElementsByClassName("artist-photo")[0];
    var artistBio = document.getElementsByClassName("artist-bio")[0];

    var i = prop.getAttribute("src").indexOf(".jpg");
    var photoName = prop.getAttribute("src").slice (0, i);

    artistPhoto.style.background="url(" + photoName + "-large.jpg";
    console.log("it happened");
};

//Setting listeners for the click event in the loop
var artists = document.getElementsByClassName("gallery")[0].getElementsByTagName("img");
for (var i = 0; i < artists.length; i++) {
    artists[i].addEventListener("click", changeArtistPhotoAndBio(artists[i]));
}

控制台输出是

7x it happened

并且点击功能的事件处理程序不起作用。我尝试在闭包中隔离处理程序,如下所示:

for (var i = 0; i < artists.length; i++) {(function(i) {
    artists[i].addEventListener("click", changeArtistPhotoAndBio(artists[i]));
}(i))
}

但输出仍然相同。所以有两个问题:

1) 如果我没有调用函数,只是将其设置为处理程序,为什么控制台输出包含七个处理程序调用的结果?

2) 如何在 HTML 集合的“for”循环中设置处理程序?

【问题讨论】:

  • 它应该是例如changeArtistPhotoAndBio.bind({}, artists[i]),而你在这里缺少右括号:"url(" + photoName + "-large.jpg";
  • 感谢您的回答和注意括号。但是我已经尝试绑定该函数但无济于事(即处理程序不起作用)。当然,我已经尝试过您的示例,但仍然无法正常工作。
  • 你的意思是处理程序没有被解雇?您应该提供复制您的问题的简约示例,例如在 jsFiddle
  • 好的,这里是小提琴:jsfiddle.net/snc8cL5y/2 我已经通过它进行了测试,无论出于何种原因,当我查找“img”元素时它不起作用,但在查找“ li" 元素。
  • 因为您使用artists[i].addEventListener("click", changeArtistPhotoAndBio(artists[i])); 作为返回函数changeArtistPhotoAndBio 的处理程序结果,在您的情况下为undefined(此函数不返回任何内容)。如果要将函数本身用作处理程序,则必须使用它的引用,或者可以将其包装在匿名函数中。基本上,使用anyFunction() 调用函数anyFunction

标签: javascript for-loop closures htmlcollection


【解决方案1】:

你必须使用闭包

var artists = document.getElementsByClassName("gallery")[0].getElementsByTagName("img");
for (var i = 0; i < artists.length; i++) {
    artists[i].addEventListener("click", function(index) {
        return function() {
            //You can use index for the current clicked item index
            // console.log(index);
            var artistPhoto = document.getElementsByClassName("artist-photo")[0];
            var artistBio = document.getElementsByClassName("artist-bio")[0];

            var i = this.getAttribute("src").indexOf(".jpg");
            var photoName = this.getAttribute("src").slice (0, i);

            artistPhoto.style.background="url(" + photoName + "-large.jpg";
            console.log("it happened");

        }
    }(i));
}

【讨论】:

    【解决方案2】:
    $('body *').on('mouseover',function(){console.log(this.tagName)});
    

    $('body *') 选择正文中的所有元素。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多