如何向对象数组添加事件监听器

24

我有一个对象数组(具体来说是easelJS图像)- 类似于这样:

var imageArray = new Array;
gShape  = new createjs.Shape();
// shape is something
imageArray.push(gShape);

我想要做的是使用事件监听器,而不是:

gShape.addEventListener("click", function() {alert"stuff"});

我希望程序知道具体点击了哪个区域,这样我就可以以以下方式发送警告框:

imageArray[index].addEventListener("click", function(){
    alert " you clicked region number " + index}

你想要的和你现在拥有的有什么不同? - user2625787
它应该可以工作。你试过了吗? - putvande
@Jeffman,看起来它在一个循环中,回调函数中的“index”可能不正确。 - Ian
啊,我被“region”这个词卡住了。 - user2625787
2
实际上不是这样的,显然我只是在将对象推入数组之前尝试添加事件侦听器,今天早上我才注意到这一点...我以为我的语法有问题...这个问题并没有什么意义...但感谢所有的答案!!! - Ryan Williams
与extjs无关,应该删除标签。 - boyukbas
6个回答

27

没问题。你可以使用闭包来保存那次迭代的索引。否则它们会在同一函数作用域中共享,从而给出相同迭代的值。为每个创建一个单独的函数将保存该函数内部的状态。

var imageArray = new Array;
gShape = new createjs.Shape();
 // shape is something
 imageArray.push(gShape); // Dumped all the objects

for (var i = 0; i < imageArray.length; i++) {
   (function(index) {
        imageArray[index].addEventListener("click", function() {
           console.log("you clicked region number " + index);
         })
   })(i);
}

或者更好

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

 function bindClick(i) {
    return function() {
        console.log("you clicked region number " + i);
    };
 }

ES6 来拯救

let imageArray = [];
gShape = new createjs.Shape();
// shape is something
imageArray.push(gShape); // Dumped all the objects

for (let i = 0; i < imageArray.length; i++) {
  imageArray[i].addEventListener("click", function() {
    console.log("you clicked region number " + i);
  });
}

使用 let 关键字可以为迭代中的变量创建块级作用域,在事件处理程序被调用时会具有正确的索引。


1
您可以随意选择,但我会建议删除第一个例子。不仅是因为其他答案已经有了,而且我认为当您可以使用更清晰、更高效的第二个例子时,它真的没有必要使用第一个。 - Ian
5
@Ian..我同意你的看法。但也许有些情况下,用户不理解它实际是如何工作的,除非他们看到一个详细的例子。这就是我留出第一个例子的原因,这样他们就可以比较第一个例子如何更清晰地写出来。 - Sushanth --
谢谢@Sushanth-- - 我以前遇到过这种“lambda提升”的情况,通常可以找到更好的解决方法,但看到两个并排的例子还是很好的。 - phatskat

8

以下类似的代码应该能够正常工作:

for (var i = 0 ; i < imageArray.length ; ++i) {
    function(index) {
        imageArray[index].addEventListener("click", function() {
            alert ("You clicked region number: " + index");
        });
    } ( i);
}

它之所以有效,是因为它创建了一个闭包,保存了index的值,这个值将在弹出窗口中显示。每次循环都会创建另一个闭包,保存另一个index的值。


2
有人可能没有检查时间戳,认为你复制了上面的答案。 - Spencer May

2
//gShape must be an array of HTMLElement
gShape.forEach(element => element.addEventListener("click", function () {
    // this, refers to the current element.
    alert ("You clicked region number: " + this.getAttribute('data-region'));
}));

1
当然,闭包是一种解决方案,但既然他已经加载了Ext,他可以使用它并获得一些非常易读的代码。索引作为第二个参数传递给Ext.Array.each(别名为Ext.each)。
Ext.each(imageArray, function(gShape, index) {
    gShape.addEventListener("click", function() {
        alert("You clicked region number " + index);
    });
});

0

这是我用于 div id 的代码:

var array = ['all', 'what', 'you', 'want'];

function fName () {
    for (var i = 0; i < array.length; i++)
    document.getElementById(array[i]).addEventListener('click', eventFunction);
};

祝你好运!


0
一个简单的方法是通过调用 querySelectorAll() 方法获取所有元素,并使用循环来迭代并执行一个函数,该函数包含该特定数组索引的数据。当元素被点击时,EventListener 就会被触发。

代码片段

获取所点击元素的id属性。

document.querySelectorAll('li').forEach(element => {
  element.addEventListener('click', () => {              
    console.log(element.getAttribute('id'))
  })
})
li{cursor:pointer}
<ul>
  <li id="id-one">One</li>
  <li id="id-two">Two</li>
  <li id="id-three">Three</li>
  <li id="id-four">Four</li>
</ul>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接