【问题标题】:Adding addEventListener() in loop only works for last button在循环中添加 addEventListener() 仅适用于最后一个按钮
【发布时间】:2016-08-25 01:50:19
【问题描述】:

我从 dynamodb 获得一个 json 数组,并在遍历按钮时将 addEventListener() 添加到按钮。但只有最后一个按钮对此做出响应。

这是 SO 上的 asked before 并且是 google 上的第一次点击,所以我更改了循环以使用闭包。但是除了最后一个按钮之外,我仍然无法将 addEventListener() 附加到其他按钮。

我最初尝试过这个:

for (var i = 0; i < array_length; ++i) {
    (function(j) {
        var obj = data.Items[j];

        adiv.innerHTML = adiv.innerHTML + "<div class='row'><div class='center-div six columns'>" + obj.Event + ", " + obj.Location + "</div></div>";
        adiv.innerHTML = adiv.innerHTML + "<div class='row'><div class='center-div six columns'>" + obj.Date + ", " + obj.Time + "</div></div>";
        adiv.innerHTML = adiv.innerHTML + "<div class='row'><div class='center-div six columns'><button id='yay_button_" + i + "' class='button-primary'>Deltag</button></div></div>";

        var elem = document.getElementById('yay_button_' + j);
        elem.addEventListener('click', function() {
            alert('id: ' + j);
        });
    })(i);
}

然后是这个较短的版本:

(function(j) {
    document.getElementById('yay_button_' + j).addEventListener('click', function() {
        alert('id: ' + j);
    });
}(i));

我尝试的另一个 variant 是使用 new 创建一个按钮:

function Button(id, number) {
    document.getElementById(id + number).addEventListener('click', function() {
        alert('click: ' + id + number);
    });
}

new Button('yay_button_', i);

我在 el capitan 上尝试了 safari 和 chrome,在控制台中没有出现错误。当我检查按钮时,按钮具有正确的 ID,yay_button_0 和 _1。

【问题讨论】:

    标签: javascript arrays json addeventlistener


    【解决方案1】:

    主要问题是你每次迭代都重新定义了adiv的HTML完全。这意味着您已经绑定到adiv 的子元素的任何事件处理程序都会在您执行adviv.innerHTML = ... 的那一刻丢失。尽管您分配了相同的 HTML 加上一些新的 HTML,但您并未分配之前定义的事件处理程序。所以他们迷路了。

    只有您在最后一次迭代中分配的事件处理程序不会以这种方式销毁。

    解决方案

    一个快速的解决方案是首先循环创建所有 HTML,然后执行一个单独的循环来分配事件处理程序:

    // First add all the new content:
    var html = adiv.innerHTML;
    for (var i = 0; i < array_length; ++i) {
        var obj = data.Items[i];
    
        html += "<div class='row'><div class='center-div six columns'>" + obj.Event + ", " + obj.Location + "</div></div>";
        html += "<div class='row'><div class='center-div six columns'>" + obj.Date + ", " + obj.Time + "</div></div>";
        html += "<div class='row'><div class='center-div six columns'><button id='yay_button_" + i + "' class='button-primary'>Deltag</button></div></div>";
    }
    adiv.innerHTML = html;
    
    // Now bind the event handlers
    // By using "let" instead of "var" the right value is retained
    // in the handlers
    for (let i = 0; i < array_length; ++i) {
        var elem = document.getElementById('yay_button_' + i);
        elem.addEventListener('click', function() {
            alert('id: ' + i);
        });
    }
    

    如果您的浏览器不支持 ES2015(对于let),那么您可以使用bind

    for (var i = 0; i < array_length; ++i) {
        var elem = document.getElementById('yay_button_' + i);
        elem.addEventListener('click', function(i) {
            alert('id: ' + i);
        }.bind(null, i));
    }
    

    【讨论】:

    • 谢谢。你是对的。我也试过了,但没有关闭。但现在我用它做了一个额外的循环,它可以工作了。介意我编辑您的帖子并粘贴代码吗?
    • 我个人更喜欢let 解决方案而不是额外的关闭。但是您可以将其发布为您自己的答案,这可能会引起未来的访问者的兴趣。
    • 谢谢。我使用严格模式,不允许使用关键字 let。 '在严格模式下意外使用保留字'let''。我会发布一个答案。
    • 哦,好吧,我也用严格模式,没问题。我猜你在 Safari 上,它还不符合这个 ES2015 语法。我使用bind() 添加了另一个选项。
    【解决方案2】:

    在 trincot 的善意建议下,我遍历了数组两次。首先生成 html,然后应用 addEventListener()。第二次我用闭包包围对 addEventListener() 的调用。

    for (var i = 0; i < array_length; ++i) {
        var obj = data.Items[i];
    
        adiv.innerHTML = adiv.innerHTML + "<div class='row'><div class='center-div six columns'>" + obj.Event + ", " + obj.Location + "</div></div>";
        adiv.innerHTML = adiv.innerHTML + "<div class='row'><div class='center-div six columns'>" + obj.Date + ", " + obj.Time + "</div></div>";
        adiv.innerHTML = adiv.innerHTML + "<div class='row'><div class='center-div six columns'><button id='yay_button_" + i + "' class='button-primary'>Deltag</button></div></div>";
    
    }
    
    for (var i = 0; i < array_length; ++i) {
        var obj = data.Items[i];
        (function(j, event) {
            document.getElementById('yay_button_' + j).addEventListener('click', function() {
                alert('id: ' + j + ', ' + event);
            });
        }(i, obj.Event));
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-04-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-24
      相关资源
      最近更新 更多