JavaScript: Ereignis-Listener entfernen

136

Ich versuche, einen Ereignis-Listener innerhalb einer Listener-Definition zu entfernen:

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

Wie könnte ich das machen? this = event ... Danke.

Thomas
quelle
8
trivial, aber für die Zukunft if(click == 50) {sollten Referenzen sein if( click === 50 )oder if( click >= 50 )- sie werden die Ausgabe nicht ändern, aber aus Gründen der Vernunft sind diese Überprüfungen sinnvoller.
Rlemon
Gute Frage ... wie entferne ich es, wenn ich keinen Zugriff auf den Inhalt habe? Ich möchte Popups zum Klicken auf Schaltflächen mit greasemonkey für andere Websites entfernen, aber wenn ich die Funktion nicht namentlich referenzieren kann, finde ich anscheinend keine Möglichkeit, sie zu entfernen.
JasonXA

Antworten:

121

Sie müssen benannte Funktionen verwenden.

Außerdem muss sich die clickVariable außerhalb des Handlers befinden, um sie zu erhöhen.

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: Sie können die click_counterVariable folgendermaßen schließen:

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

Auf diese Weise können Sie den Zähler über mehrere Elemente erhöhen.


Wenn Sie das nicht möchten und jeder einen eigenen Zähler haben soll, gehen Sie folgendermaßen vor:

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

EDIT: Ich hatte vergessen, den Handler zu benennen, der in den letzten beiden Versionen zurückgegeben wurde. Fest.

user113716
quelle
14
+1 - Ich habe daraus eine Geige gemacht und es hat nicht funktioniert. Aber das war, weil ich fünfzig Mal klicken musste :) Was für ein Idiot ich bin. Vereinfachtes Beispiel hier: jsfiddle.net/karim79/aZNqA
karim79
4
@ karim79: Ich wünschte ich könnte sagen, dass ich so etwas noch nie gemacht habe. : o) Danke für die jsFiddle.
user113716
+1 Die dritte Option hat bei mir funktioniert. Zuweisen eines Schlüsselereignisses zu einem Eingabefeld, um die Validierung zu löschen. Netter Dank
Gurnard
Upvote, dritte Option hier ist ein wichtiger Teil des Verständnisses von JS Bindung / Entbindung
SW4
würde myClick = function(event){...}auch als benannte Funktion angesehen werden?
Daniel Möller
80
   canvas.addEventListener('click', function(event) {
      click++;
      if(click == 50) {
          this.removeEventListener('click',arguments.callee,false);
      }

Sollte es tun.

edeverett
quelle
14
Das ist cool! Doc on arguments.calleefür Interessenten: developer.mozilla.org/en/JavaScript/Reference/…
Ender
Danke, das hat sehr geholfen.
John O
2
Leider funktioniert dies nicht mit ECMAScript 5 (2009) oder höher über den MDN-Link: "Die 5. Ausgabe von ECMAScript (ES5) verbietet die Verwendung arguments.callee()im strengen Modus. Vermeiden Sie die Verwendung, arguments.callee()indem Sie Funktionsausdrücken einen Namen geben oder eine Funktionsdeklaration verwenden wo eine Funktion sich selbst aufrufen muss. " (obwohl es callee()anstelle von verwendet wird callee, ist es immer noch entfernt, Boo!)
Dai
59

Sie können einen benannten Funktionsausdruck verwenden (in diesem Fall wird die Funktion benannt abc), wie folgt :

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

Beispiel für schnelles und schmutziges Arbeiten: http://jsfiddle.net/8qvdmLz5/2/ .

Weitere Informationen zu benannten Funktionsausdrücken: http://kangax.github.io/nfe/ .

Tama
quelle
Klug. Einer dieser seltenen Fälle, in denen NFE nützlich ist. Vielen Dank.
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;
};
};
Vinyl Windows
quelle
6

Wenn die Lösung von @ Cybernate nicht funktioniert, versuchen Sie, den Auslöser in seine eigene Funktion zu unterteilen, damit Sie darauf verweisen können.

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

Wenn jemand jquery verwendet, kann er dies folgendermaßen tun:

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

Hoffe, dass es jemandem helfen kann. Beachten Sie, dass die Antwort von @ user113716 gut funktioniert :)

Youssman
quelle
2

Ich denke, Sie müssen möglicherweise die Handlerfunktion im Voraus definieren, wie folgt:

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

Auf diese Weise können Sie den Handler anhand seines Namens aus sich selbst entfernen.

Ender
quelle
-4

Versuchen Sie das, es hat bei mir funktioniert.

<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>
user3870075
quelle