如何在for循环中添加事件侦听器

How to add event listener inside a for loop?

本文关键字:添加 事件 侦听器 循环 for      更新时间:2023-09-26

由于某些原因,我需要循环浏览各种元素,并在单击它们时更改它们的样式。这是代码(https://jsfiddle.net/wd4z1kvs/1/)我正在尝试:

var myscroll = {};
myscroll.list = document.getElementsByClassName("navbar-right")[0].getElementsByTagName("li");
for( var j=0; j < 5; j++) {
	myscroll.list[j].anchor = document.getElementsByClassName("navbar-right")[0].getElementsByTagName("li")[j].getElementsByTagName("a")[0];
	myscroll.list[j].anchor.addEventListener("click", function() {
		alert(j);
		myscroll.list[1].anchor.innerHTML = "hello" + j;
                myscroll.list[j].anchor.innerHTML = "yellow" + j;  
	});
}
 <div id="navbar" class="navbar-collapse collapse">
            <ul class="nav navbar-nav navbar-right">
              <li class="active"><a href="#">Home</a></li>
              <li><a href="#artists">Artists</a></li>
              <li><a href="#songs">Songs</a></li>
              <li><a href="#beats">Beats</a></li>
              <li><a href="#contact">Contact</a></li>
            </ul>
          </div>

问题似乎是该事件使用j的当前值。当代码实际运行时,它不接受参数的值。

最简单的解决方案是使用forEach或其他循环回调函数:

myscroll.list.forEach(function(item, j) {
    item.anchor = document.getElementsByClassName("navbar-right")[0]
                          .getElementsByTagName("li")[j]
                          .getElementsByTagName("a")[0];
    item.anchor.addEventListener("click", function() {
        alert(j);
        myscroll.list[1].anchor.innerHTML = "hello" + j;
        item.anchor.innerHTML = "yellow" + j;
    });
});

试试这个:

var myscroll = {};
myscroll.list = document.getElementsByClassName("navbar-right")[0].getElementsByTagName("li");
for( var j=0; j < 5; j++) {
  (function(j) {
  
    /* j variable is just a local copy of the j variable from your loop */
    myscroll.list[j].anchor = document.getElementsByClassName("navbar-right")[0].getElementsByTagName("li")[j].getElementsByTagName("a")[0];
	myscroll.list[j].anchor.addEventListener("click", function() {
	
    alert(j);
	
    myscroll.list[1].anchor.innerHTML = "hello" + j;
                myscroll.list[j].anchor.innerHTML = "yellow" + j;  
	});
    
  }(j));
  
  
  
}
<div id="navbar" class="navbar-collapse collapse">
            <ul class="nav navbar-nav navbar-right">
              <li class="active"><a href="#">Home</a></li>
              <li><a href="#artists">Artists</a></li>
              <li><a href="#songs">Songs</a></li>
              <li><a href="#beats">Beats</a></li>
              <li><a href="#contact">Contact</a></li>
            </ul>
          </div>

正如@Andreas所注意到的,循环中有一个闭包。

事件不记得值,它们只保留一个链接(引用)创建它们的环境。在这种情况下,变量j碰巧生活在这三件事发生的环境中定义因此,所有事件,当它们需要访问价值时回到环境中,找到j的最新值循环中,j变量的值为5。因此,所有五个事件都指向相同的值。

使用这个:var myscroll={};

var list = document.getElementsByClassName("navbar-right")[0].getElementsByTagName("li");
myscroll.list = list;
for (var j = 0; j < 5; j++) {
    var anchor = list[j].getElementsByTagName("a")[0];
    anchor.setAttribute("index",j);
    myscroll.list[j].anchor = anchor;
    anchor.addEventListener("click", function () {
        alert(this.getAttribute("index"));
        this.innerHTML = "hello" + this.getAttribute("index");
        //this.innerHTML = "yellow" + this.getAttribute("index");
        this.style.backgroundColor = "yellow";
    });
}