Javascript removeEventListener

Javascript removeEventListener

Event Listener bestehen weiter nachdem sie aufgerufen wurden. Für einige Events ist das auch so gewünscht: z.B. wenn ein Button mehrmals geklickt werden kann. Für andere Events ist das weitere Abhören des Events überflüssig und kann auch zu unvorhersehbaren Verhalten führen.

23-02-02 SITEMAP CSS HTML JS Basis JS Web Tutorial SVG

removeEventListener Event Handler entbinden

Zu addEventListener gibt es ein Gegenstück removeEventListener, das den Event Handler vom Event entbindet oder entkoppelt. removeEventListener räumt auf und entfernt das Event aus dem Ereignishorizont.

let elem = document.getElementById('elem');

// Event Handler auf elem ansetzen
elem.addEventListener("click", myFunction);

// Event Handler von elem entfernen
elem.removeEventListener("click", myFunction);

removeEventListener funktioniert nur bei externen Funktionsaufrufen. Wurde der Event Handler durch eine anonyme Funktion aktiviert, funktioniert removeEventListener nicht.

Gibt man der anonymen Funktion allerdings einen Namen, entsteht eine Callback-Funktion und der Event Handler kann entfernt werden.

elem.addEventListener ("click", function removeText () {
    this.innerHTML = "";
    this.removeEventListener ("click", removeText);
});

Beispiel: removeEventListener bei mouseover

Bei einer Reihe von Events – z.B. bei einem mouseover – reicht es nicht, wenn sich der Event Handler um das Event selber kümmert. Gerade beim mouseover muss u.U. auch das mouseout-Event abgefangen werden.

  • json-img-3-600
  • json-img-5-600
  • json-img-6-600
const scaleup = document.querySelector(".scaleup1");
scaleup.addEventListener ("mouseover", function (evt) {
   if (evt.target.className === "scale") {
      const elem = document.createElement ("DIV");
      elem.className = "preview";
      evt.target.parentNode.appendChild(elem);
      
      const myImg = document.createElement("IMG");
      const imgSrc = evt.target.src.replace("200.jpg","600.jpg");
      myImg.src = imgSrc;
      elem.appendChild (myImg);
   }
});

Bei jedem mouseover würde erneut ein Vorschaubild angehangen. Also muss auch auf das mouseout-Event gehorcht werden.

  • json-img-3-600
  • json-img-5-600
  • json-img-6-600

Um beim mouseout das angehängte div.preview zu entfernen, muss nach elem.appendChild (myImg); vor der schließenden geschweiften Klammer ein weiterer EventListener eingesetzt werden.

…
   elem.appendChild (myImg);
 
   evt.target.addEventListener ("mouseout", function handler (eve) {
      const preview = eve.target.parentNode.querySelector("div.preview");
      preview.parentNode.removeChild (preview);
   }, false);

}

Das würde zwar auf den ersten Blick Abhilfe schaffen, aber zu einer Flut von Fehlern in der Console führen:

  • TypeError: null is not an object (evaluating 'preview.parentNode') oder
  • Uncaught TypeError: Cannot read property 'parentNode' of null oder
  • TypeError: preview is null

Da bleiben also Events unter dem Event Listener weiterhin aktiv. Der EventListener muss entfernt werden. Dafür ist addEventListener nicht mit einer anonymen Funktion aufgerufen worden, sondern die Funktion hat einen Namen: handler.

evt.target.addEventListener ("mouseout", function handler (eve) {
   const preview = eve.target.parentNode.querySelector("div.preview");
   preview.parentNode.removeChild (preview);
   evt.target.removeEventListener ("mouseout", handler, false);
}, false);

addEventHandler mit once: true

Statt den Event Listener mit removeEventListener zu beenden, kann die neuere Option once in addEventListener eingesetzt werden. Das hält den Code übersichtlicher.

evt.target.addEventListener ("mouseout", function (eve) {
   const preview = eve.target.parentNode.querySelector("div.preview");
   preview.parentNode.removeChild (preview);
}, {once: true});

oder allgemein:

elem.addEventListener('click', function (event) {
   // nur einmal auszuführen
}, {once: true});