Melhor maneira de remover um manipulador de eventos no jQuery?

1053

Eu tenho um input type="image". Isso age como as anotações da célula no Microsoft Excel. Se alguém digitar um número na caixa de texto com a qual ele input-imageestá emparelhado, eu configurarei um manipulador de eventos para o input-image. Então, quando o usuário clica no botão image, ele exibe um pequeno pop-up para adicionar algumas notas aos dados.

Meu problema é que, quando um usuário digita zero na caixa de texto, preciso desativar o input-imagemanipulador de eventos. Eu tentei o seguinte, mas sem sucesso.

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

Respostas:

1626

jQuery ≥ 1,7

Com o jQuery 1.7 em diante, a API do evento foi atualizada, .bind()/ .unbind()ainda está disponível para compatibilidade com versões anteriores, mas o método preferido é usar as funções on () / off () . O abaixo seria agora,

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

No seu código de exemplo, você está simplesmente adicionando outro evento de clique à imagem, não substituindo o anterior:

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

Os dois eventos de clique serão acionados.

Como as pessoas disseram, você pode usar o unbind para remover todos os eventos de clique:

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

Se você deseja adicionar um único evento e removê-lo (sem remover nenhum outro que possa ter sido adicionado), use o espaço para nome do evento:

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

e para remover apenas o seu evento:

$('#myimage').unbind('click.mynamespace');
samjudson
fonte
6
Existe uma maneira de testar se unbind()está funcionando? Eu adicionei e os dois eventos ainda estão disparando.
David Yell
19
Bem, se os dois eventos ainda estão disparando, obviamente não está funcionando. Você precisaria fornecer mais informações para obter uma resposta adequada. Tente fazer uma pergunta separada.
samjudson
13
Resposta antiga - também como as informações do namespace incluído - mas eu esqueço; on / off retorna o objeto jQ? Se assim for, talvez uma resposta mais completa seria a cadeia:$('#myimage').off('click').on('click',function(){...})
vol7ron
3
Sim, eles sim, então sim, se você quiser limpar todos os outros eventos de clique e adicionar o seu, poderá fazer a chamada em cadeia acima.
samjudson
O uso .unbind()me ajudou em uma situação em que eu estava alternando várias caixas de seleção, mas, reliz, estava adicionando o .click()manipulador repetidamente, causando a interrupção do aplicativo.
TecBrat 18/03/2014
63

Isso não estava disponível quando esta pergunta foi respondida, mas você também pode usar o método live () para ativar / desativar eventos.

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

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

O que acontecerá com esse código é que, quando você clicar em #mydisablebutton, ele adicionará a classe desativada ao elemento #myimage. Isso fará com que o seletor não corresponda mais ao elemento e o evento não seja acionado até que a classe 'disabled' seja removida, tornando o seletor .live () válido novamente.

Isso tem outros benefícios ao adicionar estilos baseados nessa classe também.

MacAnthony
fonte
3
Ótima maneira de usar live(), nunca pensou em usá-lo dessa maneira antes ... Além da conveniência de codificação, é mais rápido ou oferece outras vantagens ao usar o bind / unbind?
chakrit
2
Se você estiver adicionando / removendo elementos, há vantagens definidas de desempenho sobre a ligação, pois a ligação com live é feita apenas uma vez. O jQuery parece estar migrando para mais eventos ao vivo e delegados, em vez de vincular-se a elementos específicos.
MacAnthony 26/03
3
Para desativar o live, você pode usar die ()
Moons
9
"A partir do jQuery 1.7, o método .live () está obsoleto. Use .on () para anexar manipuladores de eventos. Usuários de versões mais antigas do jQuery devem usar .delegate () em vez de .live ()." api.jquery.com/live
Lucas Pottersky
12
Ah, inconstante jQuery, um dia você traz 300 representantes para um cara, no dia seguinte é obsoleto.
27413 MrBoJangles
37

Se você deseja responder a um evento apenas uma vez , a seguinte sintaxe deve ser realmente útil:

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

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

Usando argument.callee , podemos garantir que um único manipulador de função anônima específico seja removido e, portanto, tenha um único manipulador de tempo para um determinado evento. Espero que isso ajude os outros.

ghayes
fonte
2
Absolutamente, embora às vezes você deseje ter uma certa lógica sobre quando o manipulador deve ser desvinculado (por exemplo, não desvincule, a menos que eles tenham preenchido uma caixa de texto primeiro).
ghayes
5
argument.callee está obsoleto no modo estrito!
Zloctb # 26/13
37

Isso pode ser feito usando a função unbind.

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

Você pode adicionar vários manipuladores de eventos ao mesmo objeto e evento no jquery. Isso significa que adicionar um novo não substitui os antigos.

Existem várias estratégias para alterar manipuladores de eventos, como namespaces de eventos. Existem algumas páginas sobre isso nos documentos on-line.

Olhe para esta pergunta (foi assim que aprendi a desatar). Há alguma descrição útil dessas estratégias nas respostas.

Como ler as funções de retorno de chamada em foco suspenso no jquery

Mnebuerquo
fonte
32

talvez o método unbind funcione para você

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

Eu tive que definir o evento como nulo usando o prop e o attr. Eu não poderia fazer isso com um ou outro. Também não consegui .unbind para o trabalho. Estou trabalhando em um elemento TD.

.prop("onclick", null).attr("onclick", null)
Dwhittenburg
fonte
1
Votei nisso porque estou tentando desvendar um onblur há cerca de 30 minutos. '.unbind' não funcionou, '.prop' não funcionou, '.attr' não funcionou, mas esse truque com .prop e .attr juntos funcionou. ímpar. Estou usando o Chrome com jquery 1.7.2
Jeremy
O mesmo aqui! Eu tentei remover o evento click da simples tag <a>! Thanx por isso. No meu caso, .prop ("onclick", null) foi suficiente.
Jan Lobau
o mesmo aqui. unbind e off não funcionou para mim no FF com jq 1.7.2 e .prop ("onclick", null) também foi suficiente no meu caso
bryanallott 27/03/13
4
Eu acho que a razão pela qual os métodos acima não funcionaram para vocês é por causa de como você os configurou. Se você escreveu o manipulador de eventos no DOM, sim, é necessário limpar esse atributo para limpar o manipulador de eventos. No entanto, acho que a maioria das pessoas (inclusive eu) deseja manter essas coisas (javascrip, manipuladores de eventos etc.) fora do diretório DOM, portanto, quando queremos configurar um manipulador de eventos, usamos algo parecido $("#elementId").click(function(){//Event execution code goes here});para que ele não esteja na página html. Para limpar que realmente precisa para uso .unbind(), ou o preferido.off()
VoidKing
Aqui está um exemplo de alguém que passou apenas uma hora para descobrir que as propriedades adicionadas via jQuery não são exibidas no painel de elementos do Chrome. Estive tentando unbinde offnão estava resolvendo o problema. Muito obrigado!
Renan
13

Se o evento for anexado dessa maneira , e o destino deve ser desanexado:

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

});​

fonte
11

Você pode adicionar o onclickmanipulador como marcação embutida:

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

Se sim, o jquery .off()ou .unbind()não funcionará. Você também precisa adicionar o manipulador de eventos original no jquery:

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

Em seguida, o jquery tem uma referência ao manipulador de eventos e pode removê-lo:

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

O VoidKing menciona isso um pouco mais obliquamente no comentário acima.

davaus
fonte
9

Atualizado para 2014

Usando a versão mais recente do jQuery, agora você pode desvincular todos os eventos em um espaço para nome simplesmente executando $( "#foo" ).off( ".myNamespace" );

alexpls
fonte
8

A melhor maneira de remover o evento onclick embutido é $(element).prop('onclick', null);

Shahrukh Azeem
fonte
8

Para remove TODOS event-handlers , é isso que funcionou para mim:

Remover todos os manipuladores de eventos significa ter a planície HTML structuresem todos os event handlersanexados ao elemente ao child nodes. Para fazer isso, jQuery's clone()ajudou.

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);

Com isso, teremos o clonelugar do originalsem event-handlersnele.

Boa sorte...

Akash
fonte
7

Obrigado pela informação. muito útil eu usei para bloquear a interação da página enquanto estava no modo de edição por outro usuário. Eu o usei em conjunto com o ajaxComplete. Não necessariamente o mesmo comportamento, mas um pouco semelhante.

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

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

No caso, o .on()método foi usado anteriormente com um seletor específico, como no exemplo a seguir:

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

Ambos unbind()e .off()métodos não são indo para o trabalho.

No entanto, o método .undelegate () pode ser usado para remover completamente o manipulador do evento para todos os elementos que correspondem ao seletor atual:

$("body").undelegate(".dynamicTarget", "click")
Ilia Rostovtsev
fonte
1
Eu rolei a página inteira enquanto procurava esta solução, funcionava como um encanto.
Abhishek Pandey
4

Se você $(document).on()adicionar um ouvinte a um elemento criado dinamicamente, poderá ser necessário o seguinte para removê-lo:

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

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

se você definir a onclickviahtml precisaráremoveAttr ($(this).removeAttr('onclick'))

se você configurá-lo via jquery (como após o primeiro clique nos meus exemplos acima), será necessário unbind($(this).unbind('click'))

Ishan Liyanage
fonte
2

Eu sei que isso chega tarde, mas por que não usar JS simples para remover o evento?

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

ou, se você usar uma função nomeada como manipulador 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
fonte
Boa sugestão, eu prefiro usar o javascript nativo quando disponível
Michiel
1

Todas as abordagens descritas não funcionaram para mim porque eu estava adicionando o evento click on()ao documento em que o elemento foi criado em tempo de execução:

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


Minha solução alternativa:

Como não pude desvendar a classe ".button", acabei de atribuir outra classe ao botão que tinha os mesmos estilos CSS. Ao fazer isso, o manipulador ao vivo / no evento ignorou o clique finalmente:

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

Espero que ajude.

Kai Noack
fonte
1

Espero que meu código abaixo explique tudo. 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
fonte
1
por que você está })(jQuery);entrando no IIFE quando ele já pode ser acessado globalmente?
Bryan P
2
Boa pergunta Bryan. Este método foi inserido no meu gene devido à prática. - Pode haver alguma possibilidade de o plugin não jquery ter a variável $, portanto não posso usar $ diretamente. - O uso frequente da palavra "jQuery" em um arquivo de script js pode aumentar o tamanho de byte do arquivo, onde jQuery é uma string de 6 bytes. Por isso, prefiro usar "$" ou qualquer variável de byte único.
Mysticmo
0

Simplesmente remova isso do botão:

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