JavaScript: remover ouvinte de evento


136

Estou tentando remover um ouvinte de evento dentro de uma definição de ouvinte:

canvas.addEventListener('click', function(event) {
    click++;
    if(click == 50) {
        // remove this event listener here!
    }
// More code here ...

Como eu pude fazer isso? this = event ... Obrigado.


8
trivial, mas para o futuro as referências if(click == 50) {devem ser if( click === 50 )ou if( click >= 50 )- elas não mudarão a saída, mas por razões de sanidade essas verificações fazem mais sentido.
Rlemon 14/03

Boa pergunta ... como removê-lo se não tenho acesso ao conteúdo? Desejo remover pop-ups por botões onclick usando greasemonkey para outros sites, mas, a menos que eu consiga referenciar a função pelo nome, não encontro uma maneira de removê-la.
JasonXA

Respostas:


122

Você precisa usar funções nomeadas.

Além disso, a clickvariável precisa estar fora do manipulador para incrementar.

var click_count = 0;

function myClick(event) {
    click_count++;
    if(click_count == 50) {
       // to remove
       canvas.removeEventListener('click', myClick);
    }
}

// to add
canvas.addEventListener('click', myClick);

EDIT: Você pode fechar em torno da click_countervariável assim:

var myClick = (function( click_count ) {
    var handler = function(event) {
        click_count++;
        if(click_count == 50) {
           // to remove
           canvas.removeEventListener('click', handler);
        }
    };
    return handler;
})( 0 );

// to add
canvas.addEventListener('click', myClick);

Dessa forma, você pode incrementar o contador em vários elementos.


Se você não quer isso e deseja que cada um tenha seu próprio contador, faça o seguinte:

var myClick = function( click_count ) {
    var handler = function(event) {
        click_count++;
        if(click_count == 50) {
           // to remove
           canvas.removeEventListener('click', handler);
        }
    };
    return handler;
};

// to add
canvas.addEventListener('click', myClick( 0 ));

Edição: Eu tinha esquecido de nomear o manipulador sendo retornado nas duas últimas versões. Fixo.


14
+1 - Transformei isso em um violino e não funcionou. Mas isso foi porque eu precisava clicar cinquenta vezes :) Que idiota eu sou. Exemplo simplificado aqui: jsfiddle.net/karim79/aZNqA
karim79

4
@ karim79: Eu gostaria de poder dizer que nunca fiz nada assim antes. : o) Obrigado pelo jsFiddle.
usar o seguinte comando

+1 A terceira opção funcionou para mim. Atribuindo um evento-chave a um campo de entrada para limpar a validação. Agradável um #
Gurnard

Upvote, terceira opção aqui é parte importante da JS compreensão de ligação / desligamento
SW4

seria myClick = function(event){...}considerada uma função nomeada também?
Daniel Möller

80
   canvas.addEventListener('click', function(event) {
      click++;
      if(click == 50) {
          this.removeEventListener('click',arguments.callee,false);
      }

Deveria fazê-lo.


14
Isso é legal! Documento arguments.calleepara as partes interessadas: developer.mozilla.org/en/JavaScript/Reference/…
Ender

Obrigado, isso ajudou muito.
John O

2
Infelizmente, isso não funciona com o ECMAScript 5 (2009) ou posterior, no link MDN: "A 5ª edição do ECMAScript (ES5) proíbe o uso arguments.callee()no modo estrito. Evite usar arguments.callee()dando um nome às expressões de função ou usando uma declaração de função onde uma função deve se chamar ". (embora esteja usando em callee()vez de callee, ainda é removido, boo!)
Dai

59

Você pode usar uma expressão de função nomeada (nesse caso, a função é nomeada abc), assim:

let click = 0;
canvas.addEventListener('click', function abc(event) {
    click++;
    if (click >= 50) {
        // remove event listener function `abc`
        canvas.removeEventListener('click', abc);
    }
    // More code here ...
}

Exemplo de trabalho rápido e sujo: http://jsfiddle.net/8qvdmLz5/2/ .

Mais informações sobre expressões de funções nomeadas: http://kangax.github.io/nfe/ .


Inteligente. Um daqueles casos raros em que a ENF é útil. Obrigado.
21419 DanMan

7
element.querySelector('.addDoor').onEvent('click', function (e) { });
element.querySelector('.addDoor').removeListeners();


HTMLElement.prototype.onEvent = function (eventType, callBack, useCapture) {
this.addEventListener(eventType, callBack, useCapture);
if (!this.myListeners) {
    this.myListeners = [];
};
this.myListeners.push({ eType: eventType, callBack: callBack });
return this;
};


HTMLElement.prototype.removeListeners = function () {
if (this.myListeners) {
    for (var i = 0; i < this.myListeners.length; i++) {
        this.removeEventListener(this.myListeners[i].eType, this.myListeners[i].callBack);
    };
   delete this.myListeners;
};
};

6

Se a solução do @ Cybernate não funcionar, tente ativar o gatilho para sua própria função, para que você possa fazer referência a ele.

clickHandler = function(event){
  if (click++ == 49)
    canvas.removeEventListener('click',clickHandler);
}
canvas.addEventListener('click',clickHandler);

4

Se alguém usa jquery, ele pode fazer assim:

var click_count = 0;
$( "canvas" ).bind( "click", function( event ) {
    //do whatever you want
    click_count++;
    if ( click_count == 50 ) {
        //remove the event
        $( this ).unbind( event );
    }
});

Espero que possa ajudar alguém. Observe que a resposta dada por @ user113716 funciona muito bem :)


2

Eu acho que você pode precisar definir a função de manipulador com antecedência, assim:

var myHandler = function(event) {
    click++; 
    if(click == 50) { 
        this.removeEventListener('click', myHandler);
    } 
}
canvas.addEventListener('click', myHandler);

Isso permitirá que você remova o manipulador por nome de dentro dele.


-4

Tente isso, funcionou para mim.

<button id="btn">Click</button>
<script>
 console.log(btn)
 let f;
 btn.addEventListener('click', f=function(event) {
 console.log('Click')
 console.log(f)
 this.removeEventListener('click',f)
 console.log('Event removed')
})  
</script>
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.