Il modo migliore per rimuovere un gestore eventi in jQuery?


1053

Ho un input type="image". Questo si comporta come le note di cella in Microsoft Excel. Se qualcuno inserisce un numero nella casella di testo a cui input-imageè associato, imposto un gestore eventi per il input-image. Quindi, quando l'utente fa clic su image, viene visualizzato un piccolo popup per aggiungere alcune note ai dati.

Il mio problema è che quando un utente inserisce uno zero nella casella di testo, devo disabilitare il input-imagegestore di eventi. Ho provato quanto segue, ma invano.

$('#myimage').click(function { return false; });

Risposte:


1626

jQuery ≥ 1.7

Con jQuery 1.7 in poi l'API dell'evento è stata aggiornata, .bind()/ .unbind()sono ancora disponibili per la compatibilità con le versioni precedenti, ma il metodo preferito sta usando le funzioni on () / off () . Il sotto sarebbe ora,

$('#myimage').click(function() { return false; }); // Adds another click event
$('#myimage').off('click');
$('#myimage').on('click.mynamespace', function() { /* Do stuff */ });
$('#myimage').off('click.mynamespace');

jQuery <1.7

Nel tuo codice di esempio stai semplicemente aggiungendo un altro evento click all'immagine, non sovrascrivendo il precedente:

$('#myimage').click(function() { return false; }); // Adds another click event

Verranno quindi attivati ​​entrambi gli eventi clic.

Come è stato detto dalle persone, puoi utilizzare unbind per rimuovere tutti gli eventi clic:

$('#myimage').unbind('click');

Se si desidera aggiungere un singolo evento e quindi rimuoverlo (senza rimuoverne altri eventualmente aggiunti), è possibile utilizzare lo spazio dei nomi degli eventi:

$('#myimage').bind('click.mynamespace', function() { /* Do stuff */ });

e per rimuovere solo il tuo evento:

$('#myimage').unbind('click.mynamespace');

6
C'è un modo per testare se unbind()funziona? L'ho aggiunto ed entrambi gli eventi sono ancora attivi.
David Yell,

19
Bene, se entrambi gli eventi sono ancora attivi, ovviamente non funziona. Dovresti fornire maggiori informazioni per ottenere una risposta adeguata. Prova a porre una domanda separata.
Samjudson,

13
Vecchia risposta, come le informazioni sullo spazio dei nomi incluse, ma dimentico; on / off restituisce l'oggetto jQ? In tal caso, forse una risposta più completa sarebbe il $('#myimage').off('click').on('click',function(){...})
collegamento

3
Sì, quindi sì, se si desidera cancellare tutti gli altri eventi clic e quindi aggiungere il proprio, è possibile effettuare la chiamata concatenata sopra.
Samjudson,

L'utilizzo .unbind()mi ha aiutato in una situazione in cui stavo attivando un sacco di caselle di controllo, ma mi sono reso conto che stavo aggiungendo nuovamente il .click()gestore ripetutamente, causando il blocco dell'app.
TecBrat,

63

Questo non era disponibile quando è stata data una risposta a questa domanda, ma puoi anche usare il metodo live () per abilitare / disabilitare gli eventi.

$('#myimage:not(.disabled)').live('click', myclickevent);

$('#mydisablebutton').click( function () { $('#myimage').addClass('disabled'); });

Ciò che accadrà con questo codice è che quando fai clic su #mydisablebutton, aggiungerà la classe disabilitata all'elemento #myimage. Questo farà sì che il selettore non corrisponda più all'elemento e l'evento non verrà generato fino a quando la classe 'disabled' viene rimossa rendendo nuovamente valido il selettore .live ().

Questo ha altri vantaggi aggiungendo uno stile basato anche su quella classe.


3
Bel modo di usare live(), non hai mai pensato di usarlo in questo modo prima ... A parte la convenienza della codifica, è più veloce o offre altri vantaggi nell'uso di bind / unbind?
Chakrit,

2
Se si aggiungono / rimuovono elementi, allora ci sono chiari vantaggi in termini di prestazioni rispetto al bind in quanto il bind con live viene eseguito una sola volta. jQuery sembra passare a più eventi live e delegati piuttosto che vincolanti a elementi specifici.
MacAnthony,

3
Per disabilitare il live puoi usare die ()
Moons

9
"A partire da jQuery 1.7, il metodo .live () è obsoleto. Utilizzare .on () per collegare i gestori di eventi. Gli utenti di versioni precedenti di jQuery dovrebbero utilizzare .delegate () preferibilmente a .live ()." api.jquery.com/live
Lucas Pottersky il

12
Ah, volubile jQuery, un giorno porti 300 rappresentanti a un ragazzo, il giorno dopo è obsoleto.
MrBoJangles,

37

Se vuoi rispondere a un evento solo una volta , la sintassi seguente dovrebbe essere davvero utile:

 $('.myLink').bind('click', function() {
   //do some things

   $(this).unbind('click', arguments.callee); //unbind *just this handler*
 });

Usando argomenti.callee , possiamo garantire che il gestore di una specifica funzione anonima venga rimosso e, quindi, abbia un solo gestore di tempo per un determinato evento. Spero che questo aiuti gli altri.


2
Assolutamente, anche se a volte potresti voler avere una certa logica su quando il gestore dovrebbe essere non associato (ad esempio, non separare a meno che non abbiano prima compilato una casella di testo).
Ghayes,

5
argument.callee è obsoleto in modalità rigorosa!
zloctb,

37

Questo può essere fatto usando la funzione unbind.

$('#myimage').unbind('click');

Puoi aggiungere più gestori di eventi allo stesso oggetto ed evento in jquery. Ciò significa che aggiungerne uno nuovo non sostituisce quelli vecchi.

Esistono diverse strategie per modificare i gestori di eventi, come gli spazi dei nomi degli eventi. Ci sono alcune pagine su questo nei documenti online.

Guarda questa domanda (è così che ho imparato a non separarmi). C'è una descrizione utile di queste strategie nelle risposte.

Come leggere le funzioni di callback con hover associato in jquery


32

forse il metodo unbind funzionerà per te

$("#myimage").unbind("click");

30

Ho dovuto impostare l'evento su null usando il prop e l'attr. Non potevo farlo con l'uno o l'altro. Inoltre, non riuscivo a far funzionare .unbind. Sto lavorando su un elemento TD.

.prop("onclick", null).attr("onclick", null)

1
Ho votato a favore perché ho cercato di sciogliere uno sfocato per circa 30 minuti. '.unbind' non ha funzionato, '.prop' non ha funzionato, '.attr' non ha funzionato, ma questo trucco con .prop e .attr insieme ha funzionato insieme. dispari. Sto usando Chrome con jquery 1.7.2
Jeremy

Anch'io! ho provato a rimuovere l'evento click dal semplice tag <a>! Grazie per questo. Nel mio caso .prop ("onclick", null) è stato sufficiente.
Jan Lobau,

anch'io. unbind and off non ha funzionato per me su FF con jq 1.7.2 e .prop ("onclick", null) è stato sufficiente nel mio caso
bryanallott il

4
Penso che il motivo per cui i metodi di cui sopra non hanno funzionato per voi ragazzi sia dovuto al modo in cui lo avete impostato. Se hai scritto il gestore eventi nel DOM, sì, cancellare questo attributo è necessario per cancellare il gestore eventi, tuttavia, penso che la maggior parte delle persone (incluso me stesso) desideri mantenere tali cose (javascrip, gestori eventi, ecc.) Fuori dal DOM, quindi quando vogliamo impostare un gestore di eventi usiamo qualcosa del genere in $("#elementId").click(function(){//Event execution code goes here});modo che non sia affatto nella pagina html. Per chiarire che abbiamo effettivamente bisogno di usare .unbind(), o il preferito.off()
VoidKing

Ecco un like da qualcuno che ha appena trascorso un'ora a scoprire che le proprietà aggiunte tramite jQuery non vengono visualizzate nel pannello degli elementi di Chrome. Ci ho provato unbinde offnon stava risolvendo il problema. Grazie mille!
Renan,

13

Se l'evento è collegato in questo modo e la destinazione deve essere scollegata:

$('#container').on('click','span',function(eo){
    alert(1);

    $(this).off(); //seams easy, but does not work

    $('#container').off('click','span'); //clears click event for every span

    $(this).on("click",function(){return false;}); //this works.

});​

11

È possibile che tu stia aggiungendo il onclickgestore come markup inline:

<input id="addreport" type="button" value="Add New Report" onclick="openAdd()" />

In tal caso, il jquery .off()o .unbind()non funzionerà. Devi aggiungere anche il gestore eventi originale in jquery:

$("#addreport").on("click", "", function (e) {
   openAdd();
});

Quindi jquery ha un riferimento al gestore eventi e può rimuoverlo:

$("#addreport").off("click")

VoidKing menziona questo un po 'più obliquamente in un commento sopra.


9

Aggiornato per il 2014

Usando l'ultima versione di jQuery, ora puoi separare tutti gli eventi su uno spazio dei nomi semplicemente $( "#foo" ).off( ".myNamespace" );


8

Il modo migliore per rimuovere l'evento onclick inline è $(element).prop('onclick', null);


8

A remove TUTTI event-handlers , questo è ciò che ha funzionato per me:

Rimuovere tutti i gestori di eventi significa avere la pianura HTML structuresenza tutto il relativo event handlersal elemente al suo child nodes. Per fare questo, jQuery's clone()aiutato.

var original, clone;
// element with id my-div and its child nodes have some event-handlers
original = $('#my-div');
clone = original.clone();
//
original.replaceWith(clone);

Con questo, avremo il cloneposto del originalsenza event-handlers.

In bocca al lupo...


7

Grazie per l'informazione. molto utile l'ho usato per bloccare l'interazione della pagina mentre ero in modalità modifica da un altro utente. L'ho usato insieme a ajaxComplete. Non necessariamente lo stesso comportamento ma in qualche modo simile.

function userPageLock(){
    $("body").bind("ajaxComplete.lockpage", function(){
        $("body").unbind("ajaxComplete.lockpage");
        executePageLock();      
    });
};  

function executePageLock(){
    //do something
}

5

Nel caso in cui il .on()metodo fosse precedentemente utilizzato con un particolare selettore, come nell'esempio seguente:

$('body').on('click', '.dynamicTarget', function () {
    // Code goes here
});

Sia unbind()e .off()metodi non sono andare a lavorare.

Tuttavia, il metodo .undelegate () potrebbe essere utilizzato per rimuovere completamente il gestore dall'evento per tutti gli elementi che corrispondono al selettore corrente:

$("body").undelegate(".dynamicTarget", "click")

1
Ho fatto scorrere l'intera pagina mentre cercavo questa soluzione, ha funzionato come un fascino.
Abhishek Pandey,

4

Se si utilizza $(document).on()per aggiungere un listener a un elemento creato dinamicamente, potrebbe essere necessario utilizzare quanto segue per rimuoverlo:

// add the listener
$(document).on('click','.element',function(){
    // stuff
});

// remove the listener
$(document).off("click", ".element");


2

se si imposta la onclickviahtml è necessarioremoveAttr ($(this).removeAttr('onclick'))

se lo imposti tramite jquery (come dopo il primo clic nei miei esempi sopra) allora devi farlo unbind($(this).unbind('click'))


2

So che arriva tardi, ma perché non usare JS semplice per rimuovere l'evento?

var myElement = document.getElementById("your_ID");
myElement.onclick = null;

oppure, se si utilizza una funzione denominata come gestore eventi:

function eh(event){...}
var myElement = document.getElementById("your_ID");
myElement.addEventListener("click",eh); // add event handler
myElement.removeEventListener("click",eh); //remove it

Buon consiglio, preferisco usare javascript nativo quando disponibile
Michiel

1

Tutti gli approcci descritti non hanno funzionato per me perché stavo aggiungendo l'evento click con on()al documento in cui l'elemento è stato creato in fase di esecuzione:

$(document).on("click", ".button", function() {
    doSomething();
});


La mia soluzione alternativa:

Dato che non potevo separare la classe ".button", ho appena assegnato un'altra classe al pulsante che aveva gli stessi stili CSS. In questo modo il gestore live / on-event ha finalmente ignorato il clic:

// prevent another click on the button by assigning another class
$(".button").attr("class","buttonOff");

Spero che aiuti.


1

Spero che il mio codice qui sotto spieghi tutto. HTML:

(function($){

     $("#btn_add").on("click",function(){
       $("#btn_click").on("click",added_handler);
       alert("Added new handler to button 1");
     });

  
 
     $("#btn_remove").on("click",function(){
       $("#btn_click").off("click",added_handler);
       alert("Removed new handler to button 1");
     });

  
   function fixed_handler(){
    alert("Fixed handler");
  }
  
   function added_handler(){
    alert("new handler");
  }
  
  $("#btn_click").on("click",fixed_handler);
  $("#btn_fixed").on("click",fixed_handler);
  
  
})(jQuery);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="btn_click">Button 1</button>
  <button id="btn_add">Add Handler</button>
  <button id="btn_remove">Remove Handler</button>
  <button id="btn_fixed">Fixed Handler</button>


1
perché stai passando })(jQuery);all'IIFE quando è già possibile accedervi a livello globale?
Bryan P,

2
Bella domanda Bryan. Questo metodo è stato inserito nel mio gene a causa della pratica. - Potrebbe esserci qualche possibilità per il plugin non jquery di avere la variabile $, quindi non posso usare $ direttamente. - L'uso frequente della parola "jQuery" in un file di script js può aumentare la dimensione in byte del file, dove jQuery è una stringa di 6 byte. Quindi preferisco usare "$" o qualsiasi variabile di singolo byte.
mysticmo,

0

Basta semplicemente rimuoverlo dal pulsante:

$('.classname').click(function(){
$( ".classname" ).remove();
});
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.