无法将事件传递给addEventListener:闭包问题

18

这个问题让我疯了... 我有一个循环,它向SVG对象添加事件监听器。为了举例,该对象是一个小圆圈,我必须为每个圆圈添加mouseover和mouseout事件。

我的第一个问题是标准的闭包作用域问题 - 因为所有的监听器都是在同一个循环中添加的,它们都看到相同的循环变量的无效值。我认为我可以解决这个问题,但第二个问题是我必须将 'event'传递给监听器,而我找不到同时解决这两个问题的方法。

我尝试了各种版本的以下代码:

for(month = 0; month < nMonths; month++) {
   ...
   shape.addEventListener(
     "mouseover", 
     (function(event, index) { popup_on(event, foo, index); })(event, month),
     false);
   group.appendChild(shape);
}

我使用的是这个版本出现了“event未定义”的错误。popup_on是真正的处理器,必须获取eventmonth的当前值。你知道我应该怎么做吗?谢谢。

1个回答

27

这个事件将会自动传递给您的函数,只需将其作为第一个参数传递到您传递给addEventListener的函数中即可。此外,默认情况下,捕获参数的值为false。

(function() {
    var i = month;
    shape.addEventListener("mouseover", function(e) { popup_on(e, foo, i); });
})();

另外,你是否介意在事件回调函数中关闭 foo?如果不介意,你可以像这样做。

(function() {
    var i = month;
    var f = foo;
    shape.addEventListener("mouseover", function(e) { popup_on(e, f, i); });
})();

如果所有这些局部变量让人感到烦人的话,您可以将它们作为参数传递,可能会使事情更加整洁。

(function(i, f) {
    shape.addEventListener("mouseover", function(e) { popup_on(e, f, i); });
})(month, foo);

抱歉这么蠢,但我应该把这个函数放在哪里呢?'shape'是在循环中创建的,可能有10到20次,并且每个新的'shape'(来自'createElementNS')都必须附加一个处理程序。所以似乎没有任何地方可以将此匿名函数放置在当前上下文中的“形状”中?鉴于此,我不得不把所有东西都放在“addEventListener”调用本身中吗?我认为,这会留下如何将'e'和'month'都作为参数传入的问题... ? - EML
@user785194 我认为我上面放置的代码会很好地工作。每次重新创建形状时,只需将上面的代码放入其中,以向该特定实例添加事件侦听器。 - Adam Rackis

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