JavaScript: eliminar escucha de eventos


136

Estoy tratando de eliminar un detector de eventos dentro de una definición de detector:

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

¿Cómo podría hacer eso? este = evento ... Gracias.


8
triviales, pero para las referencias futuras if(click == 50) {deberían ser if( click === 50 )o if( click >= 50 ), no cambiarán la salida, pero por razones de cordura, estas comprobaciones tienen más sentido.
— rlemon

Buena pregunta ... ¿cómo lo elimino si no tengo acceso al contenido? Quiero eliminar ventanas emergentes para hacer clic en los botones que usan greasemonkey para otros sitios, pero a menos que pueda hacer referencia a la función por nombre, no parece encontrar una manera de eliminarla.
— JasonXA

Respuestas:


122

Necesita usar funciones con nombre.

Además, la clickvariable debe estar fuera del controlador 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);

EDITAR: Puede cerrar la click_countervariable de esta manera:

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

De esta manera puede incrementar el contador en varios elementos.


Si no quieres eso y quieres que cada uno tenga su propio contador, haz esto:

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

EDITAR: Me había olvidado de nombrar el controlador que se devolvió en las últimas dos versiones. Fijo.


14
+1: convertí esto en un violín y no funcionó. Pero eso fue porque necesitaba hacer clic cincuenta veces :) Qué idiota soy. Ejemplo simplificado aquí: jsfiddle.net/karim79/aZNqA
— karim79

44
@ karim79: Ojalá pudiera decir que nunca antes había hecho algo así. : o) Gracias por el jsFiddle.
— user113716

+1 La tercera opción funcionó para mí. Asignación de un evento clave a un campo de entrada para borrar la validación. Nice one thanks
— Gurnard

Votación a favor, la tercera opción aquí es una parte importante de la comprensión de la vinculación / desvinculación de JS
— SW4

se myClick = function(event){...}consideraría una función con nombre también?
— Daniel Möller

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

Deberías hacerlo.


14
¡Esto es genial! Doc arguments.calleepara partes interesadas: developer.mozilla.org/en/JavaScript/Reference/…
— Ender

Gracias, esto ayudó mucho.
— John O

2
Desafortunadamente, esto no funciona con ECMAScript 5 (2009) o posterior, desde el enlace de MDN: "La quinta edición de ECMAScript (ES5) prohíbe el uso arguments.callee()en modo estricto. Evite usar arguments.callee()dando un nombre a las expresiones de función o una declaración de función donde una función debe llamarse a sí misma ". (aunque se está utilizando en callee()lugar de callee, todavía se elimina, ¡boo!)
— Dai

59

Puede usar una expresión de función con nombre (en este caso, la función se llama abc), así:

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 ...
}

Ejemplo de trabajo rápido y sucio: http://jsfiddle.net/8qvdmLz5/2/ .

Más información sobre expresiones de funciones con nombre: http://kangax.github.io/nfe/ .


Inteligente. Uno de esos casos raros donde NFE son útiles. Gracias.
— 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

Si la solución de @ Cybernate no funciona, intente romper el gatillo en su propia función para que pueda hacer referencia a ella.

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

4

Si alguien usa jquery, puede hacerlo así:

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 pueda ayudar a alguien. Tenga en cuenta que la respuesta dada por @ user113716 funciona bien :)


2

Creo que es posible que deba definir la función del controlador con anticipación, de esta manera:

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

Esto le permitirá eliminar el controlador por nombre de sí mismo.


-4

Intenta esto, funcionó para mí.

<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>
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.