生成的事件侦听器列表只触发最后一个



以下是演示的完整代码:http://jsfiddle.net/DF2Uw/4/

基本上,我使用FOR循环生成多个事件侦听器。我生成了多个<selects>,希望检测onChange事件并返回已更改的特定选择的ID。然而,似乎只有最后一个事件侦听器幸存下来,因为其他事件侦听器没有触发。

对这种行为有什么解释吗?

HTML

<ol id="slots"></ol>

JAVASCRIPT

var slotnameHtml = '';
for (var i = 0; i < 3; i += 1) {
    var slotname = document.createElement('select'),
        slottime = document.createElement('select'),
        slotlist = document.createElement('li');
    slotname.innerHTML = slotnameHtml;
    slottime.innerHTML = '<optgroup><option value="1">00:01</option><option value="2">00:02</option></optgroup>';
    slottime.id='test'+i;
    slotlist.appendChild(slotname);
    slotlist.appendChild(slottime);
    document.getElementById('slots').appendChild(slotlist);
    slottime.addEventListener('change', function () {
        alert(slottime.id)
    });;
}

这是因为绑定到change的处理程序不会立即运行,而是稍后运行。同时,for循环已经运行,slottime已经反弹到其最终值(您创建的最后一个<select>元素)。所有处理程序将只看到该值。

您可以引入一个闭包,以便处理程序可以访问正确的元素:

document.getElementById("slots").appendChild(slotlist);
(function(slottime) {
    slottime.addEventListener("change", function() {
        alert(slottime.id);
    });
})(slottime);

正如Teemu在评论中所说,最简单的解决方案是利用this绑定到处理程序内的目标元素的事实:

slottime.addEventListener("change", function() {
    alert(this.id);
});

您必须使用以下警报参数:

alert(this.getAttribute('id'));

最新更新