Zdarzenie kliknięcia wiążę przyciskiem:
$('#myButton').bind('click', onButtonClicked);
W jednym scenariuszu jest to wywoływane wiele razy, więc kiedy robię trigger
, widzę wiele wywołań Ajax, którym chcę zapobiec.
Jak mam bind
tylko wtedy, gdy nie jest to związane wcześniej.
Odpowiedzi:
Aktualizacja 24 sierpnia '12 : W jQuery 1.8 nie można już uzyskać dostępu do zdarzeń elementu za pomocą
.data('events')
. (Zobacz ten błąd, aby uzyskać szczegółowe informacje.) Możliwe jest uzyskanie dostępu do tych samych danych zajQuery._data(elem, 'events')
pomocą wewnętrznej struktury danych, która jest nieudokumentowana, a zatem nie gwarantuje 100% stabilności. Nie powinno to jednak stanowić problemu, a odpowiedni wiersz powyższego kodu wtyczki można zmienić na następujący:var data = jQuery._data(this[0], 'events')[type];
Zdarzenia jQuery są przechowywane w obiekcie danych o nazwie
events
, więc możesz szukać w tym:var button = $('#myButton'); if (-1 !== $.inArray(onButtonClicked, button.data('events').click)) { button.click(onButtonClicked); }
Oczywiście najlepiej byłoby, gdybyś mógł ustrukturyzować swoją aplikację, tak aby ten kod był wywoływany tylko raz.
Można to umieścić we wtyczce:
$.fn.isBound = function(type, fn) { var data = this.data('events')[type]; if (data === undefined || data.length === 0) { return false; } return (-1 !== $.inArray(fn, data)); };
Możesz wtedy zadzwonić:
var button = $('#myButton'); if (!button.isBound('click', onButtonClicked)) { button.click(onButtonClicked); }
źródło
<a>
? Ponieważ kiedy spróbuję, mówi ojQuery._data()
następującym błędzieTypeError: a is undefined
var data = jQuery._data(this[0], 'events')[type];
w try catch i zwrócił false w catch. Jeśli żadne zdarzenia nie są powiązane z tym [0], to wywołanie [type] spowoduje pewną odmianę „Nie można pobrać właściwości 'kliknięcie' niezdefiniowanego lub zerowego odwołania” i oczywiście to również mówi ci, co musisz wiedzieć.for (var i = 0; i < data.length; i++) { if (data[i].handler.toString() === fn.toString()) { return true; } }
Jeszcze jedno - oznacz takie przyciski klasą CSS i filtrem:
$('#myButton:not(.bound)').addClass('bound').bind('click', onButtonClicked);
W ostatnich wersjach jQuery zastąpić
bind
zon
:$('#myButton:not(.bound)').addClass('bound').on('click', onButtonClicked);
źródło
Jeśli używasz jQuery 1.7+:
Możesz zadzwonić
off
wcześniejon
:$('#myButton').off('click', onButtonClicked) // remove handler .on('click', onButtonClicked); // add handler
Jeśli nie:
Możesz po prostu rozpiąć pierwsze zdarzenie:
$('#myButton').unbind('click', onButtonClicked) //remove handler .bind('click', onButtonClicked); //add handler
źródło
.unbind('click', onButtonClicked)
. Zobacz instrukcję$(sel).unbind("click.myNamespace");
$('#myButton').unbind('click', onButtonClicked).bind('click', onButtonClicked);
Najlepszym sposobem, jaki widzę, jest użycie live () lub delegate () do przechwytywania zdarzenia w rodzicu, a nie w każdym elemencie podrzędnym.
Jeśli twój przycisk znajduje się wewnątrz elementu #parent, możesz zastąpić:
$('#myButton').bind('click', onButtonClicked);
przez
$('#parent').delegate('#myButton', 'click', onButtonClicked);
nawet jeśli #myButton jeszcze nie istnieje, gdy ten kod jest wykonywany.
źródło
Napisałem bardzo małą wtyczkę o nazwie „raz”, która to robi. Wykonywanie i włączanie w elemencie.
$.fn.once = function(a, b) { return this.each(function() { $(this).off(a).on(a,b); }); };
Po prostu:
$(element).once('click', function(){ });
źródło
off
usuwa wszystkich programów obsługi dla danego typu? Czyli gdyby istniał oddzielny moduł obsługi kliknięć niepowiązany, ale dotyczący tego samego elementu, czy ten również nie zostałby usunięty?Dlaczego nie skorzystać z tego
unbind()
przedbind()
$('#myButton').unbind().bind('click', onButtonClicked);
źródło
$('#myButton').off().on('click', onButtonClicked);
działa również dla mnie.Oto moja wersja:
Utils.eventBoundToFunction = function (element, eventType, fCallback) { if (!element || !element.data('events') || !element.data('events')[eventType] || !fCallback) { return false; } for (runner in element.data('events')[eventType]) { if (element.data('events')[eventType][runner].handler == fCallback) { return true; } } return false; };
Stosowanie:
Utils.eventBoundToFunction(okButton, 'click', handleOkButtonFunction)
źródło
Na podstawie odpowiedzi @ konrad-garus, ale używam
data
, ponieważ uważam, żeclass
powinno być używane głównie do stylizacji.if (!el.data("bound")) { el.data("bound", true); el.on("event", function(e) { ... }); }
źródło
Aby uniknąć sprawdzania / wiązania / usuwania powiązań, możesz zmienić swoje podejście! Dlaczego nie używasz Jquery .on ()?
Ponieważ Jquery 1.7, .live (), .delegate () są przestarzałe, teraz możesz używać .on () do
Oznacza to, że możesz dołączyć zdarzenie do elementu nadrzędnego, który wciąż istnieje i dołączyć elementy potomne, czy są obecne, czy nie!
Kiedy używasz .on () w ten sposób:
$('#Parent').on('click', '#myButton' onButtonClicked);
Wychwytujesz zdarzenie, klikasz na rodzica i wyszukujesz podrzędny „#myButton”, jeśli istnieje ...
Dlatego kiedy usuwasz lub dodajesz element podrzędny, nie musisz się martwić, czy dodać lub usunąć powiązanie zdarzenia.
źródło
.off
której, jak sądzę, usunęłaby niepowiązane procedury obsługi w procesie.Próbować:
if (typeof($("#myButton").click) != "function") { $("#myButton").click(onButtonClicked); }
źródło
if ($("#btn").data('events') != undefined && $("#btn").data('events').click != undefined) { //do nothing as the click event is already there } else { $("#btn").click(function (e) { alert('test'); }); }
źródło
Od czerwca 2019 r. Zaktualizowałem tę funkcję (i działa zgodnie z potrzebami)
$.fn.isBound = function (type) { var data = $._data($(this)[0], 'events'); if (data[type] === undefined || data.length === 0) { return false; } return true; };
źródło
JQuery ma rozwiązanie :
$( "#foo" ).one( "click", function() { alert( "This will be displayed only once." ); });
równowartość:
$( "#foo" ).on( "click", function( event ) { alert( "This will be displayed only once." ); $( this ).off( event ); });
źródło