javascript - addEventListener 使用 for 循环并传递值

标签 javascript for-loop addeventlistener

<分区>

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

如果我通过为每个实例定义 boxa 和 boxb 手动添加监听器,它就可以工作。我猜是 addEvent for 循环没有按我希望的方式工作。也许我完全使用了错误的方法。

示例使用 4 个 class="container" 容器 4 上的触发器按预期方式工作。 在容器 1、2、3 上触发在容器 4 上触发事件,但前提是触发器已经被激活。

// 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>

最佳答案

关闭! :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);
}

因为variable hoisting , var 声明被移动到范围的顶部。由于 JavaScript 没有 block 作用域(forifwhile 等),它们被移动到函数的顶部。 更新:从 ES6 开始,您可以使用 let获取 block 作用域变量。

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

使用闭包(关闭 boxaboxb 等的值)将值绑定(bind)到点击处理程序的范围。


代码分析工具,如JSLintJSHint将能够像这样捕获可疑代码。如果您正在编写大量代码,那么花时间学习如何使用这些工具是值得的。一些 IDE 内置了它们。

关于javascript - addEventListener 使用 for 循环并传递值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19586137/

相关文章:

Javascript 如何为命名空间对象的 'scope' 创建别名

javascript - 字段 : JavaScript regex required for Field 验证

python - 用逗号分隔值

python - 基于动态列表python的for循环

javascript - 迷宫游戏

Javascript:onchange 还是 addEventListener?

javascript - 在 Javascript 中添加位于现有 HTML 之前的innerHTML

r - 如何为这些回归建立一个循环?

javascript - Data-Target 无法使用 addEventListener

javascript - JavaScript 1.7 中的解构