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.