addEventListener 使用 for 循环和传递值 [英] addEventListener using for loop and passing values

查看:24
本文介绍了addEventListener 使用 for 循环和传递值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 for 循环向多个对象添加事件侦听器,但最终所有侦听器都针对同一个对象 --> 最后一个.

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

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

//点击时运行的函数:函数 makeItHappen(elem, elem2) {var el = document.getElementById(elem);el.style.backgroundColor = "红色";var el2 = document.getElementById(elem2);el2.style.backgroundColor = "蓝色";}//自动加载函数以添加侦听器:var elem = document.getElementsByClassName("triggerClass");for (var i = 0; i 

<div class="one" id="box1"><p class="triggerClass">一些文字</p>

<div class="two" id="box2"><p class="triggerClass">一些文字</p>

<div class="容器"><div class="one" id="box3"><p class="triggerClass">一些文字</p>

<div class="two" id="box4"><p class="triggerClass">一些文字</p>

解决方案

关闭!:D

这个固定的代码如你所愿:

//点击时运行的函数:函数 makeItHappen(elem, elem2) {var el = document.getElementById(elem);el.style.backgroundColor = "红色";var el2 = document.getElementById(elem2);el2.style.backgroundColor = "蓝色";}//自动加载函数以添加侦听器:var elem = document.getElementsByClassName("triggerClass");for (var i = 0; i 

<div class="one" id="box1"><p class="triggerClass">一些文字</p>

<div class="two" id="box2"><p class="triggerClass">一些文字</p>

<div class="容器"><div class="one" id="box3"><p class="triggerClass">一些文字</p>

<div class="two" id="box4"><p class="triggerClass">一些文字</p>

<小时>

为什么要修复它?

for(var i=0; i 

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

var i, k, boxa, boxb;for(i=0; i 

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

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

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

<小时>

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

I'm trying to add event listener to multiple objects using a for loop, but end up with all listeners targeting the same object --> the last one.

If I add the listeners manually by defining boxa and boxb for every instance, it works. I guess it's the addEvent for-loop that's not working the way I hoped for. Maybe I use the wrong approach altogether.

Example using 4 of the class="container" Trigger on container 4 works the way it´s supposed to. Trigger on container 1,2,3 trigger event on container 4, but only if trigger has already been activated.

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

解决方案

Closures! :D

This fixed code works as you intended:

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


Why does this fix it?

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);
}

Is actually non-strict JavaScript. It's interpretted like this:

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);
}

Because of variable hoisting, the var declarations get moved to the top of the scope. Since JavaScript doesn't have block scope (for, if, while etc.) they get moved to the top of the function. Update: as of ES6 you can use let to get block scoped variables.

When your code runs the following happens: in the for loop you add the click callbacks and you assign boxa, but its value gets overwritten in the next iteration. When the click event fires the callback runs and the value of boxa is always the last element in the list.

Using a closure (closing the values of boxa, boxb etc) you bind the value to the scope of the click handler.


Code analysis tools such JSLint or JSHint will be able to catch suspicious code like this. If you're writing a lot of code it's worthwhile to take the time to learn how to use these tools. Some IDEs have them built-in.

这篇关于addEventListener 使用 for 循环和传递值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆