EventTarget: Methode addEventListener()

Baseline Widely available

This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.

Hinweis: Diese Funktion ist in Web Workers verfügbar.

Die Methode addEventListener() der EventTarget-Schnittstelle richtet eine Funktion ein, die immer dann aufgerufen wird, wenn das angegebene Ereignis an das Ziel übermittelt wird.

Häufige Ziele sind Element, oder dessen Kinder, Document und Window, aber das Ziel kann jedes Objekt sein, das Ereignisse unterstützt (wie z.B. IDBRequest).

Hinweis: Die Methode addEventListener() ist die empfohlene Methode, um einen Ereignis-Listener zu registrieren. Die Vorteile sind:

  • Sie ermöglicht das Hinzufügen von mehr als einem Handler für ein Ereignis. Dies ist besonders nützlich für Bibliotheken, JavaScript-Module oder jede andere Art von Code, der gut mit anderen Bibliotheken oder Erweiterungen zusammenarbeiten muss.
  • Im Gegensatz zur Verwendung einer onXYZ-Eigenschaft bietet sie eine feinere Kontrolle über die Phase, in der der Listener aktiviert wird (Erfassung vs. Blasen).
  • Sie funktioniert bei jedem Ereignisziel, nicht nur bei HTML- oder SVG-Elementen.

Die Methode addEventListener() funktioniert, indem sie eine Funktion oder ein Objekt, das eine handleEvent()-Funktion implementiert, zur Liste der Ereignis-Listener für den angegebenen Ereignistyp auf dem EventTarget hinzufügt, auf dem sie aufgerufen wird. Wenn die Funktion oder das Objekt bereits in der Liste der Ereignis-Listener für dieses Ziel vorhanden ist, wird die Funktion oder das Objekt nicht ein zweites Mal hinzugefügt.

Hinweis: Wenn eine bestimmte anonyme Funktion in der Liste der Ereignis-Listener für ein bestimmtes Ziel registriert ist und später im Code eine identische anonyme Funktion in einem addEventListener-Aufruf angegeben wird, wird die zweite Funktion ebenfalls zur Liste der Ereignis-Listener für dieses Ziel hinzugefügt.

Tatsächlich sind anonyme Funktionen nicht identisch, selbst wenn sie mit dem gleichen unveränderten Quellcode, der wiederholt aufgerufen wird, definiert wurden, selbst in einer Schleife.

Das wiederholte Definieren derselben unbenannten Funktion in solchen Fällen kann problematisch sein. (Siehe Speicherprobleme weiter unten.)

Wenn ein Ereignis-Listener von einem EventTarget aus einem anderen Listener hinzugefügt wird — das heißt, während der Verarbeitung des Ereignisses — wird dieses Ereignis den neuen Listener nicht auslösen. Der neue Listener kann jedoch in einer späteren Phase des Ereignisflusses ausgelöst werden, zum Beispiel während der Bubbel-Phase.

Syntax

js
addEventListener(type, listener)
addEventListener(type, listener, options)
addEventListener(type, listener, useCapture)

Parameter

type

Ein Fall-sensitiver String, der den zu hörenden Ereignistyp darstellt.

listener

Das Objekt, das eine Benachrichtigung erhält (ein Objekt, das die Event-Schnittstelle implementiert), wenn ein Ereignis des angegebenen Typs auftritt. Dies muss null sein, ein Objekt mit einer handleEvent()-Methode oder eine JavaScript Funktion. Siehe Der Callback für den Ereignis-Listener für Details zum Callback selbst.

options Optional

Ein Objekt, das die Eigenschaften über den Ereignis-Listener angibt. Die verfügbaren Optionen sind:

capture Optional

Ein boolescher Wert, der angibt, dass Ereignisse dieses Typs an den registrierten listener übergeben werden, bevor sie an irgendein EventTarget darunter im DOM-Baum übergeben werden. Wenn nicht angegeben, ist der Standardwert false.

once Optional

Ein boolescher Wert, der angibt, dass der listener höchstens einmal nach dem Hinzufügen aufgerufen werden soll. Wenn true, wird der listener automatisch entfernt, wenn er aufgerufen wurde. Wenn nicht angegeben, ist der Standardwert false.

passive Optional

Ein boolescher Wert, der, wenn true, angibt, dass die Funktion, die von listener angegeben wird, niemals preventDefault() aufrufen wird. Wenn ein passiver Listener preventDefault() aufruft, wird nichts passieren, und es kann eine Konsolenwarnung generiert werden.

Wenn diese Option nicht angegeben ist, ist der Standardwert false – mit der Ausnahme, dass in anderen Browsern als Safari, sie für die Ereignisse wheel, mousewheel, touchstart und touchmove standardmäßig true ist. Siehe Verwendung passiver Listener, um mehr zu erfahren.

signal Optional

Ein AbortSignal. Der Listener wird entfernt, wenn die Methode abort() des angegebenen AbortSignal-Objekts aufgerufen wird. Wenn nicht angegeben, ist kein AbortSignal mit dem Listener verbunden.

useCapture Optional

Ein boolescher Wert, der angibt, ob Ereignisse dieses Typs an den registrierten listener bevor sie an irgendein EventTarget darunter im DOM-Baum übergeben werden. Ereignisse, die sich nach oben durch den Baum bewegen, werden keinen Listener auslösen, der für die Erfassung vorgesehen ist. Das Ereignispropagationsmodus bestimmt die Reihenfolge, in der die Elemente das Ereignis empfangen. Siehe DOM Level 3 Events und JavaScript Event-Reihenfolge für eine detaillierte Erklärung. Wenn nicht angegeben, ist der Standardwert für useCapture false.

Hinweis: Für Ereignis-Listener, die zum Ereignisziel hinzugefügt wurden, befindet sich das Ereignis in der Zielphase, anstatt in den Erfassungs- und Bubbel-Phasen. Ereignis-Listener in der Erfassungs-Phase werden vor den Ereignis-Listenern in den Ziel- und Bubbel-Phasen aufgerufen.

wantsUntrusted Optional Nicht standardisiert

Ein Firefox (Gecko)-spezifischer Parameter. Wenn true, erhält der Listener synthetische Ereignisse, die von Web-Inhalten gesendet werden (der Standardwert ist false für Browser chrome und true für reguläre Webseiten). Dieser Parameter ist nützlich für Code, der in Add-ons oder im Browser selbst gefunden wird.

Rückgabewert

Keiner (undefined).

Verwendungshinweise

Der Callback des Ereignis-Listeners

Der Ereignis-Listener kann entweder als Callback-Funktion oder als Objekt angegeben werden, dessen Methode handleEvent() als Callback-Funktion dient.

Die Callback-Funktion selbst hat dieselben Parameter und denselben Rückgabewert wie die Methode handleEvent(); das heißt, der Callback akzeptiert einen einzigen Parameter: ein Objekt, das auf Event basiert, das das aufgetretene Ereignis beschreibt, und es gibt nichts zurück.

Zum Beispiel könnte ein Ereignis-Handler-Callback, der sowohl fullscreenchange als auch fullscreenerror verarbeitet, folgendermaßen aussehen:

js
function handleEvent(event) {
  if (event.type === "fullscreenchange") {
    /* handle a full screen toggle */
  } else {
    /* handle a full screen toggle error */
  }
}

Der Wert von "this" innerhalb des Handlers

Es ist oft wünschenswert, auf das Element zu verweisen, auf dem der Ereignis-Handler ausgelöst wurde, z.B. wenn ein generischer Handler für eine Reihe ähnlicher Elemente verwendet wird.

Wenn eine Handler-Funktion an ein Element mit addEventListener() gebunden wird, wird der Wert von this innerhalb des Handlers eine Referenz auf das Element sein. Es wird derselbe Wert wie die currentTarget-Eigenschaft des Ereignisarguments sein, das dem Handler übergeben wird.

js
my_element.addEventListener("click", function (e) {
  console.log(this.className); // logs the className of my_element
  console.log(e.currentTarget === this); // logs `true`
});

Zur Erinnerung: Pfeilfunktionen haben keinen eigenen this-Kontext.

js
my_element.addEventListener("click", (e) => {
  console.log(this.className); // WARNING: `this` is not `my_element`
  console.log(e.currentTarget === this); // logs `false`
});

Wenn ein Ereignis-Handler (z.B. onclick) auf ein Element im HTML-Quellcode angegeben wird, wird der JavaScript-Code im Attributwert effektiv in einer Handler-Funktion verpackt, die den Wert von this konsistent mit addEventListener() bindet; ein Vorkommen von this innerhalb des Codes stellt eine Referenz auf das Element dar.

html
<table id="my_table" onclick="console.log(this.id);">
  <!-- `this` refers to the table; logs 'my_table' -->
  …
</table>

Beachten Sie, dass der Wert von this innerhalb einer Funktion, aufgerufen von dem Code im Attributwert, sich gemäß den Standardregeln verhält. Dies wird im folgenden Beispiel gezeigt:

html
<script>
  function logID() {
    console.log(this.id);
  }
</script>
<table id="my_table" onclick="logID();">
  <!-- when called, `this` will refer to the global object -->
  …
</table>

Der Wert von this innerhalb von logID() ist eine Referenz auf das globale Objekt Window (oder undefined im Fall von Strict Mode.

Festlegen von "this" mithilfe von bind()

Die Methode Function.prototype.bind() ermöglicht es Ihnen, einen festen this-Kontext für alle nachfolgenden Aufrufe festzulegen — Probleme zu umgehen, bei denen es unklar ist, was this sein wird, abhängig vom Kontext, aus dem Ihre Funktion aufgerufen wurde. Beachten Sie jedoch, dass Sie eine Referenz zum Listener behalten müssen, damit Sie ihn später entfernen können.

Dies ist ein Beispiel mit und ohne bind():

js
class Something {
  name = "Something Good";
  constructor(element) {
    // bind causes a fixed `this` context to be assigned to `onclick2`
    this.onclick2 = this.onclick2.bind(this);
    element.addEventListener("click", this.onclick1, false);
    element.addEventListener("click", this.onclick2, false); // Trick
  }
  onclick1(event) {
    console.log(this.name); // undefined, as `this` is the element
  }
  onclick2(event) {
    console.log(this.name); // 'Something Good', as `this` is bound to the Something instance
  }
}

const s = new Something(document.body);

Eine andere Lösung ist die Verwendung einer speziellen Funktion namens handleEvent(), um alle Ereignisse abzufangen:

js
class Something {
  name = "Something Good";
  constructor(element) {
    // Note that the listeners in this case are `this`, not this.handleEvent
    element.addEventListener("click", this, false);
    element.addEventListener("dblclick", this, false);
  }
  handleEvent(event) {
    console.log(this.name); // 'Something Good', as this is bound to newly created object
    switch (event.type) {
      case "click":
        // some code here…
        break;
      case "dblclick":
        // some code here…
        break;
    }
  }
}

const s = new Something(document.body);

Eine weitere Möglichkeit, mit dem this-Bezug umzugehen, besteht darin, eine Pfeilfunktion zu verwenden, die keinen separaten this-Kontext erstellt.

js
class SomeClass {
  name = "Something Good";

  register() {
    window.addEventListener("keydown", (e) => {
      this.someMethod(e);
    });
  }

  someMethod(e) {
    console.log(this.name);
    switch (e.code) {
      case "ArrowUp":
        // some code here…
        break;
      case "ArrowDown":
        // some code here…
        break;
    }
  }
}

const myObject = new SomeClass();
myObject.register();

Daten in einen und aus einem Ereignis-Listener übertragen

Ereignis-Listener nehmen nur ein Argument entgegen, ein Event oder eine Unterklasse von Event, die automatisch an den Listener übergeben wird, und der Rückgabewert wird ignoriert. Daher müssen Sie, um Daten in und aus einem Ereignis-Listener zu bringen, anstatt die Daten durch Parameter und Rückgabewerte zu übergeben, stattdessen Closures erstellen.

Die als Ereignis-Listener übergebenen Funktionen haben Zugriff auf alle Variablen, die in den äußeren Bereichen, die die Funktion enthalten, deklariert sind.

js
const myButton = document.getElementById("my-button-id");
let someString = "Data";

myButton.addEventListener("click", () => {
  console.log(someString);
  // 'Data' on first click,
  // 'Data Again' on second click

  someString = "Data Again";
});

console.log(someString); // Expected Value: 'Data' (will never output 'Data Again')

Lesen Sie den Funktionsleitfaden für weitere Informationen zu Funktionsbereichen.

Speicherprobleme

js
const elts = document.getElementsByTagName("*");

// Case 1
for (const elt of elts) {
  elt.addEventListener(
    "click",
    (e) => {
      // Do something
    },
    false,
  );
}

// Case 2
function processEvent(e) {
  // Do something
}

for (const elt of elts) {
  elt.addEventListener("click", processEvent, false);
}

Im ersten Fall oben wird mit jeder Iteration der Schleife eine neue (anonyme) Handler-Funktion erstellt. Im zweiten Fall wird dieselbe zuvor deklarierte Funktion als Ereignis-Handler verwendet, was zu einem geringeren Speicherverbrauch führt, da nur eine Handler-Funktion erstellt wird. Darüber hinaus ist es im ersten Fall nicht möglich, removeEventListener() aufzurufen, da keine Referenz auf die anonyme Funktion beibehalten wird (oder hier, nicht auf eine der mehreren anonymen Funktionen, die die Schleife möglicherweise erstellt). Im zweiten Fall ist es möglich, myElement.removeEventListener("click", processEvent, false) zu tun, da processEvent die Funktionsreferenz ist.

In Bezug auf den Speicherverbrauch ist eigentlich das Fehlen einer Funktionenreferenz nicht das eigentliche Problem; vielmehr ist es das Fehlen einer statischen Funktionsreferenz.

Verwendung passiver Listener

Wenn ein Ereignis eine Standardaktion hat — zum Beispiel ein wheel-Ereignis, das standardmäßig das Container scrollt — kann der Browser im Allgemeinen nicht die Standardaktion anfangen, bis der Ereignis-Listener beendet ist, weil er nicht im Voraus weiß, ob der Ereignis-Listener möglicherweise die Standardaktion durch Aufruf von Event.preventDefault() abbrechen wird. Wenn der Ereignis-Listener zu lange benötigt, um auszuführen, kann dies eine spürbare Verzögerung verursachen, auch bekannt als Jank, bevor die Standardaktion ausgeführt werden kann.

Indem Sie die Option passive auf true setzen, erklärt ein Ereignis-Listener, dass er die Standardaktion nicht abbrechen wird, sodass der Browser sofort mit der Standardaktion beginnen kann, ohne auf das Ende des Listeners zu warten. Wenn der Listener dann Event.preventDefault() aufruft, wird dies keine Wirkung haben.

Die Spezifikation für addEventListener() definiert den Standardwert für die Option passive als immer false. Um jedoch die Scroll-Leistungsfähigkeit passiver Listener im Legacy-Code zu realisieren, haben moderne Browser den Standardwert der Option passive für die Ereignisse wheel, mousewheel, touchstart und touchmove auf den dokumentenebenen Knoten Window, Document und Document.body geändert. Das verhindert, dass der Ereignis-Listener das Ereignis abbrechen kann, sodass er das Rendering der Seite nicht blockieren kann, während der Benutzer scrollt.

Aus diesem Grund, wenn Sie dieses Verhalten überschreiben und sicherstellen möchten, dass die Option passive false ist, müssen Sie die Option explizit auf false setzen (anstatt sich auf den Standardwert zu verlassen).

Sie brauchen sich keine Sorgen über den Wert von passive für das grundlegende scroll-Ereignis zu machen. Da es nicht abgebrochen werden kann, können Ereignis-Listener das Seitenrendering nicht blockieren.

Siehe [Verbesserung der Scroll-Leistung mit passiven Listener] (https://developers.google.com/web/updates/2016/06/passive-event-listeners#improving-scroll-performance-using-passive-listeners) für ein Beispiel, das die Wirkung passiver Listener zeigt.

Beispiele

Einen einfachen Listener hinzufügen

Dieses Beispiel zeigt, wie addEventListener() verwendet wird, um Klicks mit der Maus auf ein Element zu beobachten.

HTML

html
<table id="outside">
  <tr>
    <td id="t1">one</td>
  </tr>
  <tr>
    <td id="t2">two</td>
  </tr>
</table>

JavaScript

js
// Function to change the content of t2
function modifyText() {
  const t2 = document.getElementById("t2");
  const isNodeThree = t2.firstChild.nodeValue === "three";
  t2.firstChild.nodeValue = isNodeThree ? "two" : "three";
}

// Add event listener to table
const el = document.getElementById("outside");
el.addEventListener("click", modifyText, false);

In diesem Code ist modifyText() ein Listener für click-Ereignisse, der mit addEventListener() registriert wurde. Ein Klick irgendwo in der Tabelle wird an den Handler weitergegeben und führt modifyText() aus.

Ergebnis

Einen abbrechbaren Listener hinzufügen

Dieses Beispiel zeigt, wie man einen addEventListener()-Aufruf hinzufügt, der mit einem AbortSignal abgebrochen werden kann.

HTML

html
<table id="outside">
  <tr>
    <td id="t1">one</td>
  </tr>
  <tr>
    <td id="t2">two</td>
  </tr>
</table>

JavaScript

js
// Add an abortable event listener to table
const controller = new AbortController();
const el = document.getElementById("outside");
el.addEventListener("click", modifyText, { signal: controller.signal });

// Function to change the content of t2
function modifyText() {
  const t2 = document.getElementById("t2");
  if (t2.firstChild.nodeValue === "three") {
    t2.firstChild.nodeValue = "two";
  } else {
    t2.firstChild.nodeValue = "three";
    controller.abort(); // remove listener after value reaches "three"
  }
}

Im obigen Beispiel modifizieren wir den Code aus dem vorherigen Beispiel so, dass nach dem Ändern des Inhalts der zweiten Zeile zu "drei" abort() aus dem AbortController aufgerufen wird, den wir dem addEventListener()-Aufruf übergeben haben. Das führt dazu, dass der Wert für immer "drei" bleibt, da wir keinen Code mehr haben, der auf ein Klickereignis hört.

Ergebnis

Ereignis-Listener mit anonymer Funktion

Hier sehen wir uns an, wie man eine anonyme Funktion verwendet, um Parameter an den Ereignis-Listener zu übergeben.

HTML

html
<table id="outside">
  <tr>
    <td id="t1">one</td>
  </tr>
  <tr>
    <td id="t2">two</td>
  </tr>
</table>

JavaScript

js
// Function to change the content of t2
function modifyText(new_text) {
  const t2 = document.getElementById("t2");
  t2.firstChild.nodeValue = new_text;
}

// Function to add event listener to table
const el = document.getElementById("outside");
el.addEventListener(
  "click",
  function () {
    modifyText("four");
  },
  false,
);

Beachten Sie, dass der Listener eine anonyme Funktion ist, die Code einkapselt, der dann in der Lage ist, Parameter an die modifyText()-Funktion zu senden, die für die eigentliche Antwort auf das Ereignis verantwortlich ist.

Ergebnis

Ereignis-Listener mit einer Pfeilfunktion

Dieses Beispiel zeigt einen Ereignis-Listener, der mit Pfeilfunktion-Notation implementiert ist.

HTML

html
<table id="outside">
  <tr>
    <td id="t1">one</td>
  </tr>
  <tr>
    <td id="t2">two</td>
  </tr>
</table>

JavaScript

js
// Function to change the content of t2
function modifyText(new_text) {
  const t2 = document.getElementById("t2");
  t2.firstChild.nodeValue = new_text;
}

// Add event listener to table with an arrow function
const el = document.getElementById("outside");
el.addEventListener(
  "click",
  () => {
    modifyText("four");
  },
  false,
);

Ergebnis

Bitte beachten Sie, dass anonyme und Pfeilfunktionen ähnlich sind, sie jedoch unterschiedliche this-Bindings haben. Während anonyme (und alle traditionellen JavaScript-Funktionen) ihre eigenen this-Bindings erstellen, erben Pfeilfunktionen das this-Binding der enthaltenen Funktion.

Das bedeutet, dass die Variablen und Konstanten, die der enthaltenen Funktion zur Verfügung stehen, auch dem Ereignis-Handler zur Verfügung stehen, wenn eine Pfeilfunktion verwendet wird.

Beispiel für die Verwendung von Optionen

HTML

html
<div class="outer">
  outer, once & none-once
  <div class="middle" target="_blank">
    middle, capture & none-capture
    <a class="inner1" href="https://www.mozilla.org" target="_blank">
      inner1, passive & preventDefault(which is not allowed)
    </a>
    <a class="inner2" href="https://developer.mozilla.org/" target="_blank">
      inner2, none-passive & preventDefault(not open new page)
    </a>
  </div>
</div>
<hr />
<button class="clear-button">Clear logs</button>
<section class="demo-logs"></section>

CSS

css
.outer,
.middle,
.inner1,
.inner2 {
  display: block;
  width: 520px;
  padding: 15px;
  margin: 15px;
  text-decoration: none;
}
.outer {
  border: 1px solid red;
  color: red;
}
.middle {
  border: 1px solid green;
  color: green;
  width: 460px;
}
.inner1,
.inner2 {
  border: 1px solid purple;
  color: purple;
  width: 400px;
}

JavaScript

js
const outer = document.querySelector(".outer");
const middle = document.querySelector(".middle");
const inner1 = document.querySelector(".inner1");
const inner2 = document.querySelector(".inner2");

const capture = {
  capture: true,
};
const noneCapture = {
  capture: false,
};
const once = {
  once: true,
};
const noneOnce = {
  once: false,
};
const passive = {
  passive: true,
};
const nonePassive = {
  passive: false,
};

outer.addEventListener("click", onceHandler, once);
outer.addEventListener("click", noneOnceHandler, noneOnce);
middle.addEventListener("click", captureHandler, capture);
middle.addEventListener("click", noneCaptureHandler, noneCapture);
inner1.addEventListener("click", passiveHandler, passive);
inner2.addEventListener("click", nonePassiveHandler, nonePassive);

function onceHandler(event) {
  log("outer, once");
}
function noneOnceHandler(event) {
  log("outer, none-once, default\n");
}
function captureHandler(event) {
  //event.stopImmediatePropagation();
  log("middle, capture");
}
function noneCaptureHandler(event) {
  log("middle, none-capture, default");
}
function passiveHandler(event) {
  // Unable to preventDefault inside passive event listener invocation.
  event.preventDefault();
  log("inner1, passive, open new page");
}
function nonePassiveHandler(event) {
  event.preventDefault();
  //event.stopPropagation();
  log("inner2, none-passive, default, not open new page");
}

Ergebnis

Klicken Sie auf die äußeren, mittleren, inneren Container, um zu sehen, wie die Optionen funktionieren.

Ereignis-Listener mit mehreren Optionen

Sie können mehr als eine der Optionen im options-Parameter festlegen. Im folgenden Beispiel werden zwei Optionen festgelegt:

  • passive, um zu bestätigen, dass der Handler nicht preventDefault() aufruft
  • once, um sicherzustellen, dass der Ereignis-Handler nur einmal aufgerufen wird.

HTML

html
<button id="example-button">You have not clicked this button.</button>
<button id="reset-button">Click this button to reset the first button.</button>

JavaScript

js
const buttonToBeClicked = document.getElementById("example-button");

const resetButton = document.getElementById("reset-button");

// the text that the button is initialized with
const initialText = buttonToBeClicked.textContent;

// the text that the button contains after being clicked
const clickedText = "You have clicked this button.";

// we hoist the event listener callback function
// to prevent having duplicate listeners attached
function eventListener() {
  buttonToBeClicked.textContent = clickedText;
}

function addListener() {
  buttonToBeClicked.addEventListener("click", eventListener, {
    passive: true,
    once: true,
  });
}

// when the reset button is clicked, the example button is reset,
// and allowed to have its state updated again
resetButton.addEventListener("click", () => {
  buttonToBeClicked.textContent = initialText;
  addListener();
});

addListener();

Ergebnis

Verbesserung der Scroll-Leistung mit passiven Listener

Das folgende Beispiel zeigt die Wirkung des Setzens von passive. Es enthält ein <div> mit etwas Text und ein Kontrollkästchen.

HTML

html
<div id="container">
  <p>
    But down there it would be dark now, and not the lovely lighted aquarium she
    imagined it to be during the daylight hours, eddying with schools of tiny,
    delicate animals floating and dancing slowly to their own serene currents
    and creating the look of a living painting. That was wrong, in any case. The
    ocean was different from an aquarium, which was an artificial environment.
    The ocean was a world. And a world is not art. Dorothy thought about the
    living things that moved in that world: large, ruthless and hungry. Like us
    up here.
  </p>
</div>

<div>
  <input type="checkbox" id="passive" name="passive" checked />
  <label for="passive">passive</label>
</div>

JavaScript

Der Code fügt einen Listener für das wheel-Ereignis des Containers hinzu, das standardmäßig den Container scrollt. Der Listener führt eine langlaufende Operation durch. Zunächst wird der Listener mit der Option passive hinzugefügt, und immer wenn das Kontrollkästchen umgeschaltet wird, wird die Option passive umgeschaltet.

js
const passive = document.querySelector("#passive");
passive.addEventListener("change", (event) => {
  container.removeEventListener("wheel", wheelHandler);
  container.addEventListener("wheel", wheelHandler, {
    passive: passive.checked,
    once: true,
  });
});

const container = document.querySelector("#container");
container.addEventListener("wheel", wheelHandler, {
  passive: true,
  once: true,
});

function wheelHandler() {
  function isPrime(n) {
    for (let c = 2; c <= Math.sqrt(n); ++c) {
      if (n % c === 0) {
        return false;
      }
    }
    return true;
  }

  const quota = 1000000;
  const primes = [];
  const maximum = 1000000;

  while (primes.length < quota) {
    const candidate = Math.floor(Math.random() * (maximum + 1));
    if (isPrime(candidate)) {
      primes.push(candidate);
    }
  }

  console.log(primes);
}

Ergebnis

Der Effekt ist Folgender:

  • Zunächst ist der Listener passiv, sodass das Versuchen, den Container mit dem Rad zu scrollen, sofort erfolgt.
  • Wenn Sie "passive" deaktivieren und versuchen, den Container mit dem Rad zu scrollen, gibt es eine spürbare Verzögerung, bevor der Container scrollt, da der Browser auf das Ende des langlaufenden Listeners warten muss.

Spezifikationen

Specification
DOM Standard
# ref-for-dom-eventtarget-addeventlistener③

Browser-Kompatibilität

BCD tables only load in the browser

Siehe auch