jQuery: динамическое связывание событий с объектами dom - PullRequest
0 голосов
/ 03 октября 2009

Несколько связанных вопросов уже существует на этом сайте и в других местах, но ни один из ответов, похоже, не относится к моей ситуации. У меня есть куча переключателей в HTML.

<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». То есть функция PK.b2 () запускается независимо от того, меняю ли я значение в кнопках b1 или b2. Если я изменю записи режимов, последний принимает значение. Как я могу успешно достичь его выше?

Ответы [ 4 ]

3 голосов
/ 03 октября 2009

JavaScript-замыкания используют область родительской функции, поэтому PK[mode] всегда будет ссылаться на последний mode. Вы можете сделать что-то подобное, чтобы избежать этого:

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

См., Например, Проблема печально известной петли раздел этой статьи для получения более подробной информации.

2 голосов
/ 03 октября 2009

В цикле for в вашем коде режим переменной устанавливается каждый раз для разных режимов. Однако он сохранит только последнее значение цикла. поэтому вместо этого вам нужно внести некоторые изменения в функцию внутри привязки.

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

Теперь мы используем jquery для определения имени элемента, с которым мы работаем, вместо того, чтобы полагаться на переменную, которая содержит только последний бит данных из цикла.

0 голосов
/ 03 октября 2009

Я правильно вас понимаю, если это то, что вы хотите сделать?

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();
            });
    }
},
0 голосов
/ 03 октября 2009

Есть две проблемы из того, что я вижу.

Во-первых, как Лрудор указал , mode в замыкании - это последний итеративный режим.

Во-вторых, используйте [name=whatever] вместо [name="whatever"].

...