2013-07-19 21 views
6

Jestem pośrednim programistą JS na poziomie frontowym i próbuję wzorca modułu opisanego przez Chrisa Coyyera here.Zdarzenie kliknięcia jQuery nie działa podczas korzystania z "Wzorca modułu"

Ale kiedy przechowuję selektor jQuery w ustawieniach, nie mogę go użyć do wywołania zdarzenia kliknięcia. Zobacz poniższy kod z moimi komentarzami ... Każda pomoc jest bardzo doceniana!

var s, 
TestWidget = { 
    settings: { 
    testButton: $("#testing") 
    }, 
    init: function() { 
    s = this.settings; 
    this.bindUIActions(); 
    }, 
    bindUIActions: function() { 
    console.log(s.testButton); // This works: [context: document, selector: "#testing", constructor: function, init: function, selector: ""…] 

    //This doesn't work - why????? 
    s.testButton.click(function() { 
     //Why isn't this triggered? 
     alert('testButton clicked'); 
    }); 

    /*This works, obviously: 
    $('#testing').click(function() { 
     alert('testButton clicked'); 
    }); 
    */ 

    } 
}; 
$(document).ready(function() { 
    TestWidget.init(); 
}); 

Odpowiedz

10

Problemem jest to, że zanim zainicjować $("#testing") DOM jest gotowy, więc ten obiekt jQuery jest pusty.

Prostym rozwiązaniem jest umieszczenie całego kodu w gotowym oddzwonieniu.

Kolejny byłoby zastąpienie

settings: { 
    testButton: $("#testing") 
    }, 
    init: function() { 
    s = this.settings; 
    this.bindUIActions(); 
    }, 

z

settings: { 
    }, 
    init: function() { 
    s = this.settings; 
    s.testButton = $("#testing"); 
    this.bindUIActions(); 
    }, 

Ale trudno się dostać, dlaczego używasz tyle kod taka prosta sprawa. Być może nadużywasz tego wzoru i nie jest on tak naprawdę czysty, ponieważ masz dwie zmienne globalne: s i TestWidget, gdy jedna z nich byłaby już dużo.

Oto niewielkie zmiany swojego kodu, który byłby, moim zdaniem, do czyszczenia, a jednocześnie za pomocą modułów (IIFE variant)

TestWidget = (function(){ 
    var settings = {}; 
    return { 
     init: function() { 
      settings.testButton = $("#testing"); 
      this.bindUIActions(); 
     }, 
     bindUIActions: function() { 
      console.log(settings.testButton); 
      settings.testButton.click(function() { 
       alert('testButton clicked'); 
      }); 
     } 
    } 

})(); 
$(document).ready(function() { 
    TestWidget.init(); 
}); 

settings jest utrzymywany w zamknięciu i nie wycieka w światowym przestrzeń nazw. Zauważ, że nawet ta wersja nie ma sensu, jeśli nie zrobisz więcej z modułem.

+2

+1 za "nadużywanie wzoru" – Bergi

+1

Myślę, że op po prostu podążał za przykładem sztuczek CSS, aby zrozumieć wzór. Być może istnieje większe zadanie pod ręką? Jeśli celem jest zrozumienie enkapsulacji poprzez modularyzację, polecam czytanie wzorców projektowych przez addy osmani. – stavarotti

+1

Umieszczenie bloków skryptu u dołu strony, po całej zawartości, rozwiązałoby ten problem. Umożliwiłoby to umieszczenie kodu w całości wewnątrz modułu bez wycieku do globalnej przestrzeni nazw. –

Powiązane problemy