2009-10-12 2 views
48

Jestem ciekawy, czy możliwe jest utworzenie niestandardowego zdarzenia w jQuery, które nie jest powiązane z elementem DOM.Zdarzenie niestandardowe w jQuery, które nie jest powiązane z elementem DOM?

Znacznie preferuję jQuery do YUI, ale jest coś w YUI, które lubię, które tworzy niestandardowe wydarzenia i możliwość subskrybowania ich później.

Na przykład ten tworzy zdarzenie, które jest związany do zmiennej, a nie do elementu DOM:

var myevent = new YAHOO.util.CustomEvent("mycustomevent"); 

Wszystkie przykłady i dokumentacji Czytałem dla jQuery wymagać czegoś takiego:

$('body').bind('mycustomevent', function(){ 
    //do stuff 
}); 
+1

Domyślam się, że jquery w ogóle nie zrozumie zdarzenia "mycustomevent" i YUI. Jednak możesz spróbować użyć wskaźnika: 'bind (myevent,' .. – jantimon

+0

Myślę, że podobnie jak Django, istnieją pewne najlepsze praktyki w JQuery - na początku wtyczki. Możesz stworzyć swoje niestandardowe wydarzenie jako klasa zewnętrzna, będąca wtyczką dla JQuery, i możesz po prostu powiązać swoje zdarzenie z elementem za pomocą dowolnych selektorów, takich jak $ ("# myDiv"). myPlugin ("robi wiele rzeczy") istnieje kilka sposobów robiąc to, ale powinieneś najpierw potwierdzić, czego dokładnie potrzebujesz.możesz trochę rozwinąć? mógłbym spróbować dokładniej skomentować) thx – 0100110010101

+0

Cześć! Przyjęta odpowiedź nie jest poprawna (lub nie jest poprawna * już *). Czy mógłbyś ewentualnie zmienić zaakceptowaną odpowiedź na moją? – sbichenko

Odpowiedz

43

można wywołać niestandardowych globalnych wydarzeń, takich jak ten w jQuery:

jQuery.event.trigger('mycustomevent', [arg1, arg2, arg3]); 

Spowoduje to uruchomienie dowolnego elementu.

Ponieważ jQuery jest zbudowany wokół obiektów DOM, musisz powiązać swoje zdarzenia z obiektami DOM. Prawdopodobnie możesz znaleźć sposób na powiązanie zdarzeń bez elementu (Ty to zrobiłeś), ale to nie jest obsługiwana metodologia.

Jak napisał w swoim własnym odpowiedź, można powiązać swoje wydarzenie do globalnej obiektu DOM, jeśli nie chcesz powiązać go z pojedynczego elementu strony:

$(document).bind('mycustomevent', function (e, arg1, arg2, arg3) { /* ... */ }); 
+7

wygląda na to, że jQuery obsługuje to teraz: http://bugs.jquery.com/ticket/7818#comment:26, http://forum.jquery.com/topic/triggering-custom-events-on-js-objects. Rozwiązanie problemu "triggerHandler" wspomniane w łączu zostało również naprawione w numerze 7930. – hyperslug

+2

Tak, jQuery faktycznie obsługuje to teraz (patrz moja odpowiedź: http://stackoverflow.com/a/26062543/710356) – sbichenko

6

dla przyszłych czytelników, jego dość proste do zrobienia. Po opublikowaniu mojego pytania zrobiłem dalsze badania. Niestety żaden z pozostałych komentatorów nie był poprawny.

W celu związania niestandardowe zdarzenie:

$().bind('mycustomevent', function(){ 
    //code here 
}); 

Ponadto, można zbudować danych do obiektu zdarzenia, który jest później dostępne:

$({mydata:'testdata'}).bind('mycustomevent',function(){ 
    //code here 
}); 
+17

Powinieneś wiedzieć, że z '$()' nadal jesteś wiążący go do obiektu DOM (' $() 'jest takie samo jak wykonanie' $ (dokument) '). '$ ({})' działa, ale powinieneś wiedzieć, że działa, ponieważ jQuery nigdy nie sprawdza, czy jest to obiekt DOM. Nadpisuje go obiektem jQuery, który ma takie metody, jak 'append (...)', które zatrzyma twój skrypt, jeśli zostanie wywołany. Ponadto zachowanie dla zawijania obiektów innych niż DOM jest niezdefiniowane i może się zmienić w przyszłości. Wciąż więc stoję za moją myślą w mojej odpowiedzi i zalecam, aby powiązać ją z '$ (dokumentem), a nie z obiektem JavaScript. – Blixt

3

Można nadal arbitralnie wyzwalać i reagować na zdarzenia przy użyciu jQuery, nawet jeśli nie wiesz, do którego elementu należy je dołączyć. Po prostu utwórz w dokumencie element "odbiorcy", do którego możesz powiązać wszystkie niestandardowe zdarzenia. Pozwala to zarządzać logiką obsługi zdarzeń w jednym miejscu, dla wszystkich zdarzeń niezwiązanych z elementem.

$(document).ready(function() { 

    $(body).append('<div id="receiver">'); 

    $("#receiver").bind("foo_event", function() { 
    // decide what to do now that foo_event has been triggered. 
    }); 

    $("#some_element").click(function() { 
    $("#receiver").trigger("foo_event"); 
    }); 

}); 
+0

Myślę, że to zły pomysł. Jeśli naprawdę chcesz, aby jakiś element dołączał zdarzenia, dlaczego nie użyć '$ ('body')' lub '$ (document)'? – Blixt

+5

To tylko konwencja, która działa.Wolę to od używania dokumentu lub ciała, ponieważ działa to jak w sterylnej izbie porządkowej na wydarzenia - znam wszystko, co w niej jest, i istnieje mniejsze prawdopodobieństwo, że coś złego stanie się niechciane przez przypadek. Czy możesz wyjaśnić, dlaczego uważasz, że to zły pomysł? –

5

Wiązanie z elementami innymi niż dom zostało usunięte w jQuery 1.4.4.

+0

Co to oznacza? – ppumkin

+0

Być może oznacza on zwykłe obiekty JavaScript? –

+0

Czy odnosisz się do odpowiedzi [this] (http://stackoverflow.com/a/26062543/4967497)? – JojOatXGME

3

jQuery Callbacks zapewnia prosty sposób wdrożenia systemu pub-sub niezależnego od DOM.

W dolnej części połączonej strony znajduje się przykład kodu, który pokazuje, jak to zrobić.

1

[EDIT]

Oto klasa robotnicza, która używa pojęcia napisane poniżej:

https://github.com/stratboy/image-preloader

To tylko kolejny obraz preloader. Możesz zapisać się na kilka wydarzeń. Spójrz.

[/ EDIT]

Stary post:

Oto kolejny przykład z Barebone callbacków jak sugeruje Himanshu P.

Buduję klasę i pochodzę Mootools, gdzie takie rzeczy jak Klasy i zdarzenia niestandardowe bezpośrednio zaimplementowane w klasach (niezwiązane z elementami DOM) są całkowicie naturalne. Tak więc spróbowałem obejść i udostępnić poniżej. rozwiązywane są

var step_slider; 

    //sandbox 
    ;(function($) { 

//constructor 
var StepSlider = function(slider_mask_selector,options) { 

    //this.onStep = $.Event('step'); 
    this.options = null; 
    this.onstep = $.Callbacks(); 

    this.init(); 
}//end constructor 

StepSlider.prototype = { 

    init:function(){ 
     this.set_events(); 
    },//end init 

    set_events:function(){ 

     if(this.options){ 
      if(this.options.onstep){ 
       this.subscribe('step',options.onstep); 
      } 
     } 

    },//set_events 

    subscribe:function(event,action){ 
     this['on'+event].add(action); 
    }, 

    fire_onstep:function(){ 
     this.onstep.fire({ data1:'ok' }); 
    } 

}//end prototype/class 

//-------------------- 

$(document).ready(function() { 

    step_slider = new StepSlider('selector'); 

    //for example, say that you have a div#next-button, you can then do this: 
    $('#next-button').click(function(){ 
     step_slider.fire_onstep(); 
    }); 

});//end domready 


})(jQuery); 
+0

to nie jest klasa. –

+0

@low_rents: może nie dla ES6, ale tak długo, jak można tworzyć instancje z niego (nowa nazwa ClassName), jest to klasa. Lub, (stary) sposób javascript zrobić coś jak klasa, pamiętając, że javascript nie ma prawdziwej składni/cukrów dziedziczenia/dziedziczenia jak ActionScript 3 i ES6. Prawdopodobnie jedna z najlepszych implementacji js oop przed ES6 była sposobem, w jaki coffescript tworzy klasy js (po prostu utwórz i zobacz skompilowany kod), ale powyższy jest prostszą implementacją i jest dobrym kompromisem, aby uzyskać samowystarczalny, dobrze zorganizowany obiekty, które mają być tworzone w nieskończonych czasach. – Stratboy

39

Według a comment by John Resig, wiążące zdarzenia do niestandardowych obiektów poprzez jQuery:

bez konkretnego powodu, dlaczego nie jest to udokumentowane (inne niż to raczej nietradycyjny dla większości użytkowników) - ale tak, wspieramy to i mamy dla niego testy jednostkowe.

Tak to działa:

var a = {foo: 'bar'}; 
$(a).on('baz', function() {console.log('hello')}); 
$(a).triggerHandler('baz'); 
>>> 'hello' 

Większość użytkowników będzie musiał triggerHandler() nie trigger(). Jeśli zostanie użyty .trigger("eventName"), będzie szukał właściwości "eventName" na obiekcie i spróbuje wykonać ją po wykonaniu wszystkich dołączonych procedur obsługi jQuery (Source).

EDIT (28.02.2017):

Po użyciu tego wzorca przez około 2 lata w dużym kodzie, mogę potwierdzić, że jest to zły pomysł. Te niestandardowe zdarzenia prowadzą do niezrozumiałych przepływów danych. Zamiast tego preferuj wywołania zwrotne.

+9

To powinna być zaakceptowana odpowiedź. – MatteoSp

+1

Głupie pytanie: czy ma powód, dla którego nie jest udokumentowany? Nie powinno się go używać? Czy można go usunąć/zmodyfikować w nowszej wersji? Zastanawiam się, czy powinienem użyć go na rzecz innych bibliotek sub pubów, takich jak [EvenEmitter] (https://github.com/Olical/EventEmitter). – robsch