2014-03-06 6 views
5

Ich habe zwei jquery Funktionen, die zusammenarbeiten, eine hängt von einer Klasse ab, eine andere entfernt die Klasse.JQuery-Selektor funktioniert immer noch, nachdem ich die Klasse entfernt habe?

Sobald es entfernt wird, würde ich die Funktionalität erwartet aufhören zu arbeiten, aber es trägt auf?

Was ist los? Hier

ist die fiddle, versuchen Sie es selbst heraus.

<div class="container disabled"> 
    <a href="www.google.com">Go to Google</a> 
</div> 
<label> 
    <input type="checkbox" />Enable link</label> 

Die JS

$('.disabled > a').click(function (e) { 
    e.preventDefault(); 
    e.stopPropagation(); 
    alert('should stop working'); 
}); 

$('input[type=checkbox]').change(function() { 
    $('.container').removeClass('disabled'); 
}); 
+0

Selbst zu überprüfen, ob Sie die Klasse entfernt haben, hat sich die Aktion bereits an das Element gebunden ist. Es wird nicht automatisch gelöst. –

Antwort

15

Es ist wie Sie eher als statische Event-Handler Event-Handler delegiert werden wollen verwenden aussieht. Lassen Sie mich erklären.

Wenn Sie eine Codezeile wie folgt ausführen:

$('.disabled > a').click(function (e) { 

dies einen Ereignishandler auf alle Objekte installiert werden, die in diesem Moment in der Zeit des Wahl entsprechen. Diese Ereignishandler sind dann für immer vorhanden. Sie schauen nicht mehr auf welche Klassen irgendwelche Elemente haben. Wenn Sie also nach der Installation eines statischen Ereignishandlers eine Klasse ändern, wirkt sich dies nicht darauf aus, auf welchen Elementen Ereignishandler vorhanden sind.

Wenn Sie dynanamic Verhalten wollen, wo welche Elemente auf ein Ereignis reagieren auf abhängt, welche Klassen vorhanden sind, zu einem bestimmten Zeitpunkt, dann müssen Sie Umgang mit delegierten Ereignis verwenden.

Mit delegierten Event-Handling, befestigen Sie das Ereignis „dauerhaft“ zu einem übergeordneten und wertet dann die Eltern, ob das Kind, wo das Ereignis jedes Mal das Ereignis ausgelöst entspricht der Auswahl entstanden. Wenn das Kind nicht mehr mit der Auswahl übereinstimmt, wird der Ereignishandler nicht ausgelöst. Wenn dies der Fall ist, wird dies geschehen und Sie können eine Klasse hinzufügen/entfernen, um das Verhalten zu ändern.

Die allgemeine Form von delegierten Event-Handler sind wie folgt aus:

$("#staticParent").on("click", ".childSelector", fn); 

Sie mögen im Idealfall einen Elternteil wählen, die möglichst nahe an das Kind wie möglich ist, ist aber selbst nicht dynamisch. In Ihrem speziellen Beispiel zeigen Sie kein Elternteil anderen als der Körper Objekt, so dass Sie diese verwenden:

$(document.body).on("click", ".disabled > a", function() { 
    e.preventDefault(); 
    e.stopPropagation(); 
    alert('should stop working');  
}); 

Dieser Code wird dann dynamisch reagieren, wenn Sie die disabled Klasse hinzufügen entfernen. Wenn die Klasse disabled vorhanden ist, wird der Ereignishandler ausgelöst. Wenn es nicht vorhanden ist, wird der Ereignishandler nicht ausgelöst.

Arbeits Demo: http://jsfiddle.net/jfriend00/pZeSA/

Weitere Referenzen auf delegierten Ereignisbehandlung:

jQuery .live() vs .on() method for adding a click event after loading dynamic html

jQuery .on does not work but .live does

Should all jquery events be bound to $(document)?

JQuery Event Handlers - What's the "Best" method

jQuery selector doesn't update after dynamically adding new elements

+0

Ich entdeckte das gerade, nachdem ich die Frage gepostet hatte, aber sehr detaillierte Erläuterung. – shenku

+0

Super Antwort. Vielen Dank. –

+0

Dies ist, was ich seit einer Stunde googeln. Ich danke dir sehr!! –

1

Wenn der Selektor ausgeführt wird, erhält er eine Liste von Elementen, einschließlich des betreffenden Elements, und fügt einen Click-Ereignishandler hinzu.

Dann entfernen Sie die Klasse - also alle nachfolgenden jQuery-Selektoren würden Ihr Element nicht bekommen - aber Sie haben das Ereignis bereits angehängt, so dass es immer noch feuern wird.

Der Selektor, den Sie verwendet haben, läuft auf der Zeile, die Sie deklariert haben - er wird nicht träge initialisiert, wenn Klicks passieren.

3

Das Ändern der Klasse, nachdem der Ereignishandler gebunden ist, hat absolut keine Auswirkung, da der Ereignishandler nicht plötzlich ungebunden ist, es ist immer noch an das gleiche Element gebunden.

Sie haben für die Klasse in der Event-Handler

$('.container > a').click(function (e) { 
    if ($(this).closest('.container').hasClass('disabled')) { 
     e.preventDefault(); 
     e.stopPropagation(); 
    } 
}); 

$('input[type=checkbox]').change(function() { 
    $('.container').toggleClass('disabled', !this.checked); 
}); 

FIDDLE

+0

Warum nicht einfach delegierte Event-Handler verwenden, damit der Event-Handler selbst dynamisch auf hinzugefügte/entfernte Klassen reagiert? – jfriend00

+0

@ jfriend00 - Das ist eine Option, in diesem Fall würde ich nur nach der Präsenz der Klasse suchen, aber das ist nur ich, so oder so ist es in Ordnung. – adeneo

+0

@ jfriend00 - Und das ist was ein delegierter Handler tut, er überprüft, ob das Ziel diese Klasse hat, also beschränke ich mich auf die Anzahl der Elemente, auf die der Event-Handler feuert, und ich denke zumindest, dass es effizienter ist . – adeneo

Verwandte Themen