在循环中添加addEventListener()仅适用于最后一个按钮

kom*_*ten 0 javascript arrays json addeventlistener

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

这是在SO上问过的,并且是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);
}
Run Code Online (Sandbox Code Playgroud)

然后是这个较短的版本:

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

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

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

new Button('yay_button_', i);
Run Code Online (Sandbox Code Playgroud)

我在capitan上尝试了野生动物园和Chrome浏览器,但在控制台中没有出现错误。我检查按钮时具有正确的ID,即yay_button_0和_1。

tri*_*cot 5

主要问题是每次迭代时都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);
    });
}
Run Code Online (Sandbox Code Playgroud)

如果您的浏览器不支持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));
}
Run Code Online (Sandbox Code Playgroud)