¿La mejor manera de eliminar un controlador de eventos en jQuery?

1053

Tengo un input type="image". Esto actúa como las notas de celda en Microsoft Excel. Si alguien ingresa un número en el cuadro de texto con el que input-imageestá emparejado, configuro un controlador de eventos para el input-image. Luego, cuando el usuario hace clic en image, obtiene una pequeña ventana emergente para agregar algunas notas a los datos.

Mi problema es que cuando un usuario ingresa un cero en el cuadro de texto, necesito deshabilitar el input-imagecontrolador de eventos del. He intentado lo siguiente, pero fue en vano.

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

Respuestas:

1626

jQuery ≥ 1.7

Con jQuery 1.7 en adelante, la API de eventos se ha actualizado, .bind()/ .unbind()todavía están disponibles para la compatibilidad con versiones anteriores, pero el método preferido es usar las funciones on () / off () . Lo siguiente ahora sería,

$('#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

En su código de ejemplo, simplemente está agregando otro evento de clic a la imagen, sin anular el anterior:

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

Ambos eventos de clic se activarán.

Como la gente ha dicho, puede usar desvincular para eliminar todos los eventos de clic:

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

Si desea agregar un solo evento y luego eliminarlo (sin eliminar ningún otro que pueda haberse agregado), puede usar el espacio de nombres de eventos:

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

y para eliminar solo tu evento:

$('#myimage').unbind('click.mynamespace');
samjudson
fuente
66
¿Hay alguna forma de probar si unbind()está funcionando? Lo agregué y ambos eventos todavía se están activando.
David Yell
19
Bueno, si ambos eventos todavía se disparan, entonces obviamente no está funcionando. Tendría que dar más información para obtener una respuesta adecuada. Intenta hacer una pregunta por separado.
samjudson
13
Antigua respuesta -también como la información del espacio de nombres incluida- pero se me olvida; ¿on / off devuelve el objeto jQ? Si es así, quizás una respuesta más completa sería encadenar:$('#myimage').off('click').on('click',function(){...})
vol7ron
3
Sí, lo hacen, así que sí, si desea borrar todos los demás eventos de clic y luego agregar el suyo, puede hacer la llamada encadenada anterior.
samjudson
El uso .unbind()me ayudó en una situación en la que alternaba un montón de casillas de verificación, pero me di cuenta de que estaba volviendo a agregar el .click()controlador repetidamente, lo que provocó que la aplicación se bloqueara.
TecBrat
63

Esto no estaba disponible cuando se respondió esta pregunta, pero también puede usar el método live () para habilitar / deshabilitar eventos.

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

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

Lo que sucederá con este código es que cuando hace clic en el botón #disparable, agregará la clase deshabilitada al elemento #myimage. Esto hará que el selector ya no coincida con el elemento y el evento no se disparará hasta que se elimine la clase 'inhabilitada', lo que hace que el selector .live () sea válido nuevamente.

Esto tiene otros beneficios al agregar un estilo basado en esa clase también.

MacAnthony
fuente
3
Buena manera de usar live(), nunca antes pensé en usarlo de esta manera ... Además de la conveniencia de codificación, ¿es más rápido u ofrece otras ventajas al usar bind / unbind?
chakrit
2
Si está agregando / eliminando elementos, existen ventajas de rendimiento definitivas sobre el enlace, ya que el enlace con live solo se realiza una vez. jQuery parece estar moviéndose a más eventos en vivo y delegados en lugar de vincularse a elementos específicos.
MacAnthony
3
Para desactivar live puedes usar die ()
Moons
99
"A partir de jQuery 1.7, el método .live () está en desuso. Use .on () para adjuntar controladores de eventos. Los usuarios de versiones anteriores de jQuery deben usar .delegate () en lugar de .live ()". api.jquery.com/live
Lucas Pottersky
12
Ah, voluble jQuery, un día traes 300 repeticiones a un chico, al día siguiente es obsoleto.
MrBoJangles
37

Si desea responder a un evento solo una vez , la siguiente sintaxis debería ser realmente útil:

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

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

Usando argumentos.callee , podemos asegurarnos de que se elimine el controlador de una función anónima específica y, por lo tanto, tener un controlador de tiempo único para un evento determinado. Espero que esto ayude a otros.

ghayes
fuente
2
Absolutamente, aunque a veces es posible que desee tener cierta lógica sobre cuándo el controlador debe estar desvinculado (por ejemplo, no desvincular a menos que primero archiven un cuadro de texto).
ghayes
55
argumentos.callee se deprace en modo estricto!
zloctb
37

Esto se puede hacer utilizando la función de desvinculación.

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

Puede agregar múltiples controladores de eventos al mismo objeto y evento en jquery. Esto significa que agregar uno nuevo no reemplaza a los antiguos.

Existen varias estrategias para cambiar los controladores de eventos, como los espacios de nombres de eventos. Hay algunas páginas sobre esto en los documentos en línea.

Mira esta pregunta (así es como me enteré de desvincular). Hay alguna descripción útil de estas estrategias en las respuestas.

Cómo leer las funciones de devolución de llamada de desplazamiento del cursor en jquery

Mnebuerquo
fuente
32

tal vez el método de desvinculación funcione para ti

$("#myimage").unbind("click");
John Boker
fuente
30

Tuve que configurar el evento en nulo usando el accesorio y el attr. No podría hacerlo con uno u otro. Tampoco pude hacer que .unbind funcione. Estoy trabajando en un elemento TD.

.prop("onclick", null).attr("onclick", null)
dwhittenburg
fuente
1
He votado por esto porque he estado tratando de desvincular un desenfoque durante unos 30 minutos. '.unbind' no funcionó, '.prop' no funcionó, '.attr' no funcionó, pero este truco con .prop y .attr juntos funcionó. impar. Estoy usando Chrome con jquery 1.7.2
Jeremy
¡Igual que aquí! Traté de eliminar el evento de clic de la simple etiqueta <a>. Gracias por esto. En mi caso, .prop ("onclick", null) fue suficiente.
Jan Lobau
igual que aquí. desconectar y desconectar no funcionó para mí en FF con jq 1.7.2 y .prop ("onclick", null) también fue suficiente en mi caso
bryanallott
44
Creo que la razón por la que los métodos anteriores no funcionaron para ustedes es por cómo lo configuraron. Si escribió el controlador de eventos en el DOM, entonces sí, es necesario borrar este atributo para borrar el controlador de eventos, sin embargo, creo que la mayoría de las personas (incluyéndome a mí) desean mantener esas cosas (javascrip, controladores de eventos, etc.) fuera del DOM, así que cuando queremos configurar un controlador de eventos usamos algo así $("#elementId").click(function(){//Event execution code goes here});para que no esté en la página html. Para aclarar que realmente necesitamos usar .unbind(), o el preferido.off()
VoidKing
Aquí hay un comentario de alguien que acaba de pasar una hora para descubrir que las propiedades agregadas a través de jQuery no se muestran en el panel de elementos de Chrome. Lo intenté unbindy offno resolvió el problema. ¡Muchas gracias!
Renan
13

Si el evento se adjunta de esta manera , y el objetivo se debe desacoplar:

$('#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.

});​

fuente
11

Puede agregar el onclickcontrolador como marcado en línea:

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

Si es así, el jquery .off()o .unbind()no funcionará. También debe agregar el controlador de eventos original en jquery:

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

Luego, jquery tiene una referencia al controlador de eventos y puede eliminarlo:

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

VoidKing menciona esto un poco más oblicuamente en un comentario anterior.

davaus
fuente
9

Actualizado para 2014

Con la última versión de jQuery, ahora puede desvincular todos los eventos en un espacio de nombres simplemente haciendo $( "#foo" ).off( ".myNamespace" );

alexpls
fuente
8

La mejor manera de eliminar el evento onclick en línea es $(element).prop('onclick', null);

Shahrukh Azeem
fuente
8

Para remove TODOS event-handlers , esto es lo que funcionó para mí:

Eliminar todos los controladores de eventos significa tener el plano HTML structuresin todos los event handlersadjuntos al elementy su child nodes. Para hacer esto, jQuery's clone()ayudó.

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 esto, tendremos el clonelugar en lugar del originalsin event-handlersél.

Buena suerte...

Akash
fuente
7

Gracias por la información. muy útil, lo usé para bloquear la interacción de la página mientras estaba en modo de edición por otro usuario. Lo usé junto con ajaxComplete. No necesariamente el mismo comportamiento pero algo similar.

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

function executePageLock(){
    //do something
}
jquery_user
fuente
5

En caso de que el .on()método se haya utilizado previamente con un selector particular, como en el siguiente ejemplo:

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

Ambos unbind()y los .off()métodos no van a funcionar.

Sin embargo, el método .undelegate () podría usarse para eliminar completamente el controlador del evento para todos los elementos que coincidan con el selector actual:

$("body").undelegate(".dynamicTarget", "click")
Ilia Rostovtsev
fuente
1
Recorrí toda la página mientras buscaba esta solución, funcionó a las mil maravillas.
Abhishek Pandey
4

Si utiliza $(document).on()para agregar un agente de escucha a un elemento creado dinámicamente, es posible que deba usar lo siguiente para eliminarlo:

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

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

si configura la onclickvía htmlnecesitaremoveAttr ($(this).removeAttr('onclick'))

si lo configura a través de jquery (como después del primer clic en mis ejemplos anteriores), entonces necesita unbind($(this).unbind('click'))

Ishan Liyanage
fuente
2

Sé que esto llega tarde, pero ¿por qué no usar JS simple para eliminar el evento?

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

o, si usa una función con nombre como controlador de eventos:

function eh(event){...}
var myElement = document.getElementById("your_ID");
myElement.addEventListener("click",eh); // add event handler
myElement.removeEventListener("click",eh); //remove it
Silviu Preda
fuente
Buena sugerencia, prefiero usar JavaScript nativo cuando esté disponible
Michiel
1

Todos los enfoques descritos no funcionaron para mí porque estaba agregando el evento click on()al documento donde se creó el elemento en tiempo de ejecución:

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


Mi solución alternativa:

Como no podía desvincular la clase ".button", acabo de asignar otra clase al botón que tenía los mismos estilos CSS. Al hacerlo, el controlador de eventos / en vivo ignoró el clic finalmente:

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

Espero que ayude.

Kai Noack
fuente
1

Espero que mi siguiente código lo explique todo. 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>

mysticmo
fuente
1
¿Por qué pasa })(jQuery);al IIFE cuando ya se puede acceder a él globalmente?
Bryan P
2
Buena pregunta Bryan. Este método se ha introducido en mi gen debido a la práctica. - Puede haber alguna posibilidad de que el complemento no jquery tenga la variable $, por lo tanto, no puedo usar $ directamente. - El uso frecuente de la palabra "jQuery" en un archivo de script js puede aumentar el tamaño de bytes del archivo, donde jQuery es una cadena de 6 bytes. Por lo tanto, prefiero usar "$" o cualquier variable de un solo byte.
mysticmo
0

Simplemente elimine eso del botón:

$('.classname').click(function(){
$( ".classname" ).remove();
});
Mitra
fuente