jQuery:将事件动态绑定到dom对象

问题描述:

本网站和其他地方已经存在几个相关的问题,但没有一个答案似乎适用于我的情况。我在HTML中有一堆单选按钮。jQuery:将事件动态绑定到dom对象

<input type="radio" name="b1" value="aa"> aa<br> 
<input type="radio" name="b1" value="ab"> ab<br> 
<input type="radio" name="b1" value="ac"> ac<br> 

<input type="radio" name="b2" value="ba"> ba<br> 
<input type="radio" name="b2" value="bb"> bb<br> 
<input type="radio" name="b2" value="bc"> bc<br> 

<script type="text/javascript"> 
var PK = {  
    modes: ["b1", "b2"], 

    init: function() {   
     // attach actions to radio buttons 
     for (var key in this.modes) { 
      var mode = this.modes[key]; 
      $("input[name='" + mode + "']").bind(
       "change", 
       function() { 
       PK[mode]($("input[name='" + mode + "']:checked").val()); 
       } 
     ); 
     } 
    }, 

    b1: function(val) { .. do something .. }, 

    b2: function(val) { .. do something else .. }, 
}; 

$(document).ready(function() { 
    PK.init(); 
}); 
</script> 

以上根本不起作用。我尝试过.live而不是.bind,甚至不能按预期工作。事实上,它们都将动作绑定到模式中的最后一项,在上面的“b2”中。也就是说,无论我更改b1或b2按钮中的值,都会触发函数PK.b2()。如果我将这些模式条目反转,最后一个将取值。我如何成功地完成他?

JavaScript关闭使用父函数作用域,所以PK[mode]将始终引用最后的mode。你可以做这样的事情,以避免它:

$("input[name=" + mode + "]").bind(
    "change", 
    function(mode) { 
     return function() { 
      PK[mode]($("input[name='" + mode + "']:checked").val()); 
     }; 
    }(mode) 
); 

例如,见臭名昭著的循环问题更多细节部分of this article

在代码中的for循环中,每次为不同模式设置变量模式。但它只会保留循环的最后一个值。所以您需要对绑定中的函数进行一些更改。

$("input[name=" + mode + "]").bind(
    "change", 
    function(e) { 
     PK[$(this).attr('name')]($(this).val()); 
    } 
); 

现在我们使用jQuery找出我们正在与合作,而不是依赖于仅具有数据从一个循环的最后一位的变量项目的名称。

从我看到的有两个问题。

首先,由于lrudor pointed outmode在闭包中是最后一种迭代模式。第二,用[name=whatever]代替[name="whatever"]

如果这是你想要做的事情,我能理解你吗?

init: function() { 
    // attach actions to radio buttons 
    for (var key in this.modes) { 
     var mode = this.modes[key]; 
     $("input[name='" + mode + "']") 
      .bind("change", function(e) { 
       var radio = e.srcElement; 
       PK[radio.name](radio.value); 
      }) 
      .bind("click", function() { 
       // Loose focus of the radio button once clicked, 
       // so the change-event fires 
       this.blur(); 
      }); 
    } 
},