2015-01-28 4 views
1

Я пытаюсь создать плагин, где передаю функции обработчика для определенных событий. В простом примере ниже у меня есть две кнопки. Когда я нажимаю кнопку 1, ее метка должна меняться на «Button A», и когда я нажимаю кнопку 2, ее метка должна быть изменена на «Button B».Закрытие JQuery в цикле

Однако, что происходит, когда я нажимаю кнопку 1, метка меняется на «Button B». Я знаю, что это имеет какое-то отношение к закрытию функции обработчика в цикле, но я просто не могу понять, как это исправить.

<body> 
    <button class="btn1">Button 1</button> 
    <button class="btn2">Button 2</button> 
</body>  

Вот мой JQuery:

$(function() { 

    $("body").myplugin({ 
     helperFunctions : { 
      funcA : function(obj) { 
       $(obj).text("Button A"); 
      }, 

      funcB : function(obj) { 
       $(obj).text("Button B"); 
      } 
     }, 

     handlers : [ 
      { 
      on : "click", 
      selector : ".btn1", 
      handlerFunc : function(funcs, obj){ 
           funcs.funcA(obj); 
          } 

      }, 

      { 
      on : "click", 
      selector : ".btn2", 
      handlerFunc : function(funcs, obj){ 
           funcs.funcB(obj); 
          } 

      } 
     ] 
    }); 

}); 


(function ($) { 
    $.fn.extend({ 
     myplugin: function (settings) { 
      var $this = $(this); 

      function createHandlerFunction(func, obj){ 
       return func(settings.helperFunctions, obj) ; 
      } 

      for(var handlerIdx in settings.handlers){ 
       var handler = settings.handlers[ handlerIdx ]; 
       $this.on( 
        handler.on, 
        handler.selector, 
        function() { 
         return createHandlerFunction(handler.handlerFunc, this) }); 
        } 
      } 
    }); 
})(jQuery); 

К сожалению, если пример немного долго. Вот http://jsfiddle.net/30nL07db/

+0

Put ваше выражение функции внутри 'createHandlerFunction' (так, чтобы оно было возвращено), а не вокруг вызова, и оно будет работать. – Bergi

+0

Немного не по теме: вы не должны использовать 'for..in' для итерации массивов. –

ответ

1

Вот ваша обновленная рабочая скрипка: http://jsfiddle.net/30nL07db/42/

for(var handlerIdx in settings.handlers){ 
    var handler = settings.handlers[ handlerIdx ]; 
    $this.on(handler.on, handler.selector, handler, function(event) { 
     return createHandlerFunction(event.data.handlerFunc, this); 
    }); 
} 

Просто передайте обработчик в качестве параметра данных для регистрации событий, или переменного обработчика будет указывать до последнего присвоенного значения (то есть, последнего значения петля);

1

Так что проблема в вашем коде с этим:

for(var handlerIdx in settings.handlers){ 
    var handler = settings.handlers[ handlerIdx ]; 
... 

Вы используете в делегировании Ивентов handler переменных, которая связана с внешней переменной handlerIdx и becouse того, что при выходе из для петель, handlerIdx будет последним идентификатором ...

Вот противопоказан пример с 3 идентификаторами: see fiddle

Посмотрите на другой вопрос о замыканиях: here

Учебник о замыканиях: here

Итак, давайте создадим функцию, которая создает делегирование событий, вне цикла, а внутри просто передать эту функцию, например:

function createEvent(id) { 
    $this.on(
     settings.handlers[id].on, 
     settings.handlers[id].selector, 
     function() { 
     settings.handlers[id].handlerFunc(settings.helperFunctions, this) 
     } 
    ); 
} 

for(var handlerIdx in settings.handlers){ 
    var handler = settings.handlers[ handlerIdx ]; 
    var s = handler.selector; 
    createEvent(handlerIdx); 
} 

See fiddle with this answer, working as you expect

Смежные вопросы