【问题标题】:Append onclick method using for loop使用 for 循环附加 onclick 方法
【发布时间】:2014-01-24 02:17:13
【问题描述】:

我将 onclick 事件附加到我动态创建的元素中。我正在使用下面的代码,这只是重要的部分。

Test.prototype.Show= function (contents) {
    for (i = 0; i <= contents.length - 1; i++) {
         var menulink = document.createElement('a');
         menulink.href = "javascript:;";
         menulink.onclick = function () { return that.ClickContent.apply(that, [contents[i]]); };
    }
}

首先它说它是未定义的。然后我更改并添加:

var content = content[i];
menulink.onclick = function () { return that.ClickContent.apply(that, [content]); };

现在发生的事情是它总是将最后一个元素附加到所有 onclick 事件(也称为元素)。我在这里做错了什么?

【问题讨论】:

  • 确实,谢谢!有了这个标题,它就不太可能被发现,但它很有用:)
  • 另请注意,您的代码正在成为The Horror of Implicit Globals 的牺牲品:您需要声明i
  • 你是对的,谢谢!
  • 可以使用i &lt;= contents.length - 1而不是i &lt; contents.length

标签: javascript object onclick apply


【解决方案1】:

这是一个经典问题。当回调被调用时,循环结束,所以i的值为content.length

以此为例:

Test.prototype.Show= function (contents) {
    for (var i = 0; i < contents.length; i++) { // no need to have <= and -1
         (function(i){ // creates a new variable i
           var menulink = document.createElement('a');
           menulink.href = "javascript:;";
           menulink.onclick = function () { return that.ClickContent.apply(that, [contents[i]]); };
         })(i);
    }
}

这个立即调用的函数为一个新变量i创建了一个作用域,它的值因此受到保护。

更好的是,将制作处理程序的代码分成一个函数,既是为了清晰,也是为了避免不必要地创建和丢弃构建器函数:

Test.prototype.Show = function (contents) {
    for (var i = 0; i <= contents.length - 1; i++) {
        var menulink = document.createElement('a');
        menulink.href = "javascript:;";
        menulink.onclick = makeHandler(i);
    }

    function makeHandler(index) {
        return function () {
            return that.ClickContent.apply(that, [contents[index]]);
        };
    }
};

如果您不需要compatibility with IE8,则完全避免此问题的一种方法是使用forEach 引入范围,而不是使用for 循环:

Test.prototype.Show = function (contents) {
  contents.forEach(function(content) {
    var menulink = document.createElement('a');
    menulink.href = "javascript:;";
    menulink.onclick = function() {
      return that.ClickContent.call(that, content);
    };
  });
}

【讨论】:

  • 我不喜欢menulink.href = "javascript:;"; 部分。如果目的是有一个指针光标,那么可以用 css 以一种使目的明确的方式来完成。
  • 很好的答案!非常感谢。正如你所说,一个我不知道的经典问题。谢谢!
  • 与preventdefault相关的那部分。有时我对 chrome 有奇怪的行为。更改该部分后一切正常,但也许有更好的解决方案
  • 这应该做 AFAIK:menu.onclick = function(e){ e.preventDefault(); ... }
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-25
  • 2016-03-20
  • 2021-06-24
  • 2017-12-27
  • 2017-09-29
  • 2013-12-31
相关资源
最近更新 更多