一尘不染

使用循环和传递值的addEventListener

javascript

我试图使用for循环将事件侦听器添加到多个对象,但最终所有侦听器都针对同一对象->最后一个对象。

如果我通过为每个实例定义boxa和boxb手动添加侦听器,则它将起作用。我猜这是addEvent
for循环无法按我期望的方式工作。也许我完全使用了错误的方法。

在容器4上使用class =“ container”触发器4的示例按预期方式工作。在容器4上的容器1,2,3触发事件上触发,但仅当触发器已被激活时。

// Function to run on click:

function makeItHappen(elem, elem2) {

  var el = document.getElementById(elem);

  el.style.backgroundColor = "red";

  var el2 = document.getElementById(elem2);

  el2.style.backgroundColor = "blue";

}



// Autoloading function to add the listeners:

var elem = document.getElementsByClassName("triggerClass");



for (var i = 0; i < elem.length; i += 2) {

  var k = i + 1;

  var boxa = elem[i].parentNode.id;

  var boxb = elem[k].parentNode.id;



  elem[i].addEventListener("click", function() {

    makeItHappen(boxa, boxb);

  }, false);

  elem[k].addEventListener("click", function() {

    makeItHappen(boxb, boxa);

  }, false);

}


<div class="container">

  <div class="one" id="box1">

    <p class="triggerClass">some text</p>

  </div>

  <div class="two" id="box2">

    <p class="triggerClass">some text</p>

  </div>

</div>



<div class="container">

  <div class="one" id="box3">

    <p class="triggerClass">some text</p>

  </div>

  <div class="two" id="box4">

    <p class="triggerClass">some text</p>

  </div>

</div>

阅读 308

收藏
2020-04-25

共1个答案

一尘不染

关闭!:D

此固定代码按预期工作:

// Function to run on click:

function makeItHappen(elem, elem2) {

    var el = document.getElementById(elem);

    el.style.backgroundColor = "red";

    var el2 = document.getElementById(elem2);

    el2.style.backgroundColor = "blue";

}



// Autoloading function to add the listeners:

var elem = document.getElementsByClassName("triggerClass");



for (var i = 0; i < elem.length; i += 2) {

    (function () {

        var k = i + 1;

        var boxa = elem[i].parentNode.id;

        var boxb = elem[k].parentNode.id;

        elem[i].addEventListener("click", function() { makeItHappen(boxa,boxb); }, false);

        elem[k].addEventListener("click", function() { makeItHappen(boxb,boxa); }, false);

    }()); // immediate invocation

}


<div class="container">

  <div class="one" id="box1">

    <p class="triggerClass">some text</p>

  </div>

  <div class="two" id="box2">

    <p class="triggerClass">some text</p>

  </div>

</div>



<div class="container">

  <div class="one" id="box3">

    <p class="triggerClass">some text</p>

  </div>

  <div class="two" id="box4">

    <p class="triggerClass">some text</p>

  </div>

</div>

为什么可以解决此问题?

for(var i=0; i < elem.length; i+=2){
    var k = i + 1;
    var boxa = elem[i].parentNode.id;
    var boxb = elem[k].parentNode.id;

    elem[i].addEventListener("click", function(){makeItHappen(boxa,boxb);}, false);
    elem[k].addEventListener("click", function(){makeItHappen(boxb,boxa);}, false);
}

实际上是非严格的JavaScript。解释如下:

var i, k, boxa, boxb;
for(i=0; i < elem.length; i+=2){
    k = i + 1;
    boxa = elem[i].parentNode.id;
    boxb = elem[k].parentNode.id;

    elem[i].addEventListener("click", function(){makeItHappen(boxa,boxb);}, false);
    elem[k].addEventListener("click", function(){makeItHappen(boxb,boxa);}, false);
}

由于变量提升,因此var声明将移动到作用域的顶部。由于JavaScript没有块作用域(forifwhile等),他们无法移动到函数的顶部。
更新:
从ES6开始,您可以let用来获取块范围的变量。

当您的代码运行时,会发生以下情况:在for循环中添加click回调并分配boxa,但是其值在下一次迭代中将被覆盖。当点击事件触发回调运行和的值boxa是始终在列表的最后一个元素。

使用闭包(关闭的值boxaboxb等等),将值绑定到点击处理程序的作用域。


2020-04-25