Heim  >  Artikel  >  Web-Frontend  >  Eine eingehende Analyse der Ereignisdelegation in JS

Eine eingehende Analyse der Ereignisdelegation in JS

青灯夜游
青灯夜游nach vorne
2021-02-01 17:50:341797Durchsuche

Eine eingehende Analyse der Ereignisdelegation in JS

Warum brauchen Sie eine Veranstaltungsdelegation?

Implementieren Sie zunächst eine kleine Funktion: Nachdem Sie auf die HTML-Schaltfläche geklickt haben, geben Sie die Nachricht an die Konsole aus.

Um diese kleine Funktion zu implementieren, müssen Sie die Schaltfläche auswählen und dann die Methode addEventListener() verwenden, um einen Ereignis-Listener anzuhängen: addEventListener() 方法来附加事件监听器:

<button id="buttonId">Click me</button>

<script>
  document.getElementById(&#39;buttonId&#39;)
    .addEventListener(&#39;click&#39;, () => console.log(&#39;Clicked!&#39;));
</script>

以上就是侦听单个元素(尤其是按钮)上事件的方式。

如果需要监听多个按钮上的事件呢?下面是一种可能的实现:

<div id="buttons">
  <button class="buttonClass">Click me</button>
  <button class="buttonClass">Click me</button>
  <!-- buttons... -->
  <button class="buttonClass">Click me</button>
</div>

<script>
  const buttons = document.getElementsByClassName(&#39;buttonClass&#39;);
  for (const button of buttons) {
    button.addEventListener(&#39;click&#39;, () => console.log(&#39;Clicked!&#39;));
  }
</script>

你可以在 Codesandbox 上查看它是怎样工作的

按钮列表被迭代为 for (const button of buttons) ,并且每个按钮都被附加了一个新的侦听器。另外在列表中的按钮被添加或删除后,你必须还要手动删除或附加事件监听器。

有没有更好的方法?

幸运的是,如果我们使用“事件委托”模式的话,侦听多个元素上的事件只需要一个事件侦听器。

事件委托使用事件传播机制的细节。想要要了解事件委托的工作原理,应该先了解什么是事件传播。

事件传播

当你单击下面 html 中的按钮时:

<html>
  <body>
    <div id="buttons">
      <button class="buttonClass">Click me</button>
    </div>
  </body>
</html>

点击事件会触发多少个元素?毫无疑问,按钮本身会收到单击事件。而且所有按钮的祖先,甚至包括 documentwindow 对象也会收到。

点击事件的传播分三个阶段:

  • 捕获阶段 —— 从windowdocument 和根元素开始,事件向下扩散至目标元素的祖先

  • 目标阶段 —— 事件在用户单击的元素上触发

  • 冒泡阶段——最后,事件冒泡通过目标元素的祖先,一直到根元素 documentwindow

Eine eingehende Analyse der Ereignisdelegation in JS

Eine eingehende Analyse der Ereignisdelegation in JS

addEventListener 方法的第三个参数 captureOrOptions

element.addEventListener(eventType, handler[, captureOrOptions]);

使你可以捕获来自不同阶段的事件。

  • 如果缺少 captureOrOptions 参数,或者参数为 false{capture:false},那么侦听器将捕获目标(target)和 冒泡阶段(bubble phases)的事件
  • 如果参数是 true{capture:true},那么侦听器将会侦听捕获阶段(capture phase)的事件。

通过下面的代码,你会侦听到在 元素上发生的捕获阶段的点击事件:

document.body.addEventListener(&#39;click&#39;, () => {
  console.log(&#39;Body click event in capture phase&#39;);
}, true);

在这个 Codesandbox 演示中,单击按钮时,你可以在控制台中查看事件的传播方式。

那么事件传播是怎样帮助捕获多个按钮事件的呢?

该算法很简单:把事件侦听器附加到按钮的父级,并在单击按钮时捕获冒泡事件。这就是事件委托的工作方式。

3.事件委托

让我们用事件委托来捕获多个按钮上的点击:

<div id="buttons"> <!-- Step 1 -->
  <button class="buttonClass">Click me</button>
  <button class="buttonClass">Click me</button>
  <!-- buttons... -->
  <button class="buttonClass">Click me</button>
</div>

<script>
  document.getElementById(&#39;buttons&#39;)
    .addEventListener(&#39;click&#39;, event => { // Step 2
      if (event.target.className === &#39;buttonClass&#39;) { // Step 3
        console.log(&#39;Click!&#39;);
      }
    });
</script>

打开Codesandbox 演示,然后单击任意按钮,你会看到  'Click!' 消息被记录到控制台。

事件委托的思想很简单。你不需要把委托事件监听器直接附加到按钮上,而是可以委托父监听 <div id="buttons">。单击按钮时,父元素的侦听器将会捕获<strong>冒泡事件</strong>(还记得前面所说事件传播吗?)。<p>使用事件委托需要3个步骤:</p> <h4>步骤1:确定要监视事件的元素的父级元素</h4> <p>在上面的例子中, <code><div id="buttons">  是按钮的父元素。<h4>步骤2:把事件侦听器附加到父元素</h4> <p><code>document.getElementById('buttons') .addEventListener('click', handler)

// ...
.addEventListener(&#39;click&#39;, event => {
    if (event.target.className === &#39;buttonClass&#39;) {      
        console.log(&#39;Click!&#39;);
    }
});
Oben erfahren Sie, wie Sie auf Ereignisse warten ein einzelnes Element (insbesondere der Knopf) Weg.

Was ist, wenn Sie Ereignisse auf mehreren Tasten anhören müssen? Hier ist eine mögliche Implementierung: 🎜rrreee🎜Sie können Sehen Sie, wie es auf Codesandbox funktioniert. 🎜🎜Die Liste der Schaltflächen wird als for (const button of button) iteriert und an jede Schaltfläche wird ein neuer Listener angehängt. Darüber hinaus müssen Sie nach dem Hinzufügen oder Entfernen von Schaltflächen zur Liste auch Ereignis-Listener manuell entfernen oder anhängen. 🎜🎜Gibt es einen besseren Weg? 🎜🎜 Wenn wir das Muster „Ereignisdelegierung“ verwenden, ist zum Abhören von Ereignissen auf mehreren Elementen glücklicherweise nur ein Ereignis-Listener erforderlich. 🎜🎜Details zum 🎜Ereignisverbreitungsmechanismus, der von der Ereignisdelegation verwendet wird. Um zu verstehen, wie die Ereignisdelegation funktioniert, sollten Sie zunächst verstehen, was Ereignisweitergabe ist. 🎜

Ereignisweitergabe🎜🎜Wenn Sie auf die Schaltfläche im HTML unten klicken: 🎜rrreee🎜Wie viele Elemente wird das Klickereignis auslösen? Zweifellos empfängt die Schaltfläche selbst das Klickereignis. Und alle Button-Vorfahren, sogar document- und window-Objekte, erhalten es ebenfalls. 🎜🎜Die Verbreitung von Klickereignissen ist in drei Phasen unterteilt: 🎜
  • 🎜🎜Erfassungsphase🎜 – von window, Ausgehend vom Dokument und dem Stammelement breitet sich das Ereignis nach unten zu den Vorfahren des Zielelements aus🎜
  • 🎜🎜Zielphase🎜 – das Ereignis wird auf dem vom Benutzer angeklickten Element ausgelöst🎜
  • 🎜🎜Bubbling-Phase🎜 – Schließlich sprudelt das Ereignis durch die Vorfahren des Zielelements bis zu den Stammelementen document und window. 🎜
🎜1 .png🎜🎜Eine eingehende Analyse der Ereignisdelegation in JS🎜🎜addEventListener Der dritte Parameter der Methode captureOrOptions: 🎜rrreee🎜 ermöglicht es Ihnen, Ereignisse aus verschiedenen Phasen zu erfassen. 🎜
  • Wenn der Parameter captureOrOptions fehlt oder false oder {capture: false ist, dann führt der Listener eine Erfassung durch 🎜Ereignisse der Ziel- und Blasenphase🎜
  • Wenn der Parameter true oder {capture: true ist, dann erkennt der Listener auf Ereignisse in die 🎜Erfassungsphase🎜.
🎜Mit dem folgenden Code hören Sie sich das Klickereignis der Erfassungsphase an, das im Element auftritt: 🎜rrreee🎜In diesem Codesandbox-Demo, klicken Sie auf die Schaltfläche, Sie Sie können sehen, wie sich das Ereignis in der Konsole ausbreitet. 🎜🎜Wie hilft die Ereignisweitergabe dabei, mehrere Schaltflächenereignisse zu erfassen? 🎜🎜Der Algorithmus ist einfach: Hängen Sie einen Ereignis-Listener an das übergeordnete Element der Schaltfläche an und erfassen Sie das Blasenereignis, wenn auf die Schaltfläche geklickt wird. So funktioniert die Event-Delegation. 🎜

3. Ereignisdelegation 🎜🎜Lassen Sie uns die Ereignisdelegation verwenden, um Klicks auf mehrere Schaltflächen zu erfassen: 🎜rrreee🎜Öffnen Sie Codesandbox Demo, klicken Sie dann auf eine beliebige Schaltfläche und Sie sehen 'Click! ' Die Nachricht wird in der Konsole protokolliert. 🎜🎜Die Idee der Event-Delegation ist einfach. Sie müssen keinen delegierten Ereignis-Listener direkt an die Schaltfläche anhängen. Stattdessen können Sie den übergeordneten Listener <div id="buttons"> delegieren. Wenn auf die Schaltfläche geklickt wird, erfasst der Listener des übergeordneten Elements das „Blasenereignis“ (erinnern Sie sich, was wir zuvor über die Ereignisausbreitung gesagt haben?). 🎜🎜Die Verwendung der Ereignisdelegierung erfordert 3 Schritte: 🎜<h4>Schritt 1: Bestimmen Sie das übergeordnete Element des Elements, um das Ereignis zu überwachen</h4>🎜Im obigen Beispiel ist <code><div id="buttons"> ist das übergeordnete Element der Schaltfläche. 🎜<h4>Schritt 2: Ereignis-Listener an übergeordnetes Element anhängen</h4>🎜<code>document.getElementById('buttons') .addEventListener('click', handler) Ereignis-Listener anhängen Das übergeordnete Element, an das angehängt wird die Taste. Dieser Ereignis-Listener reagiert auch auf Schaltflächenklicks, da das 🎜Schaltflächenklick-Ereignis durch Vorfahrenelemente 🎜 nach oben sprudelt (aufgrund der Ereignisweitergabe). 🎜

步骤3:用 event.target 选择目标元素

单击按钮时,将会用event 对象参数调用处理函数。属性 event.target  访问在其上调度了事件的元素,在例子中是一个按钮:

// ...
.addEventListener(&#39;click&#39;, event => {
    if (event.target.className === &#39;buttonClass&#39;) {      
        console.log(&#39;Click!&#39;);
    }
});

顺便说明一下,event.currentTarget 指向事件侦听器直接附加到的元素。在例子中,event.currentTarget 是  <div id="buttons">。<p>现在,你可以看到事件委托模式的好处:事件委托仅需要一个事件侦听器,而不必像本文最初那样将侦听器附加到每一个按钮上。</p> <h2 id="item-4">总结</h2> <p>当发生点击事件(或传播的任何其他事件)时:</p> <ul> <li>事件从 <code>windowdocument、根元素向下传播,并经过目标元素的祖先(捕获阶段);

  • 事件发生在目标(目标阶段)上;
  • 最后,事件在目标祖先之间冒出气泡,直到根元素 documentwindow(冒泡阶段)。
  • 该机制称为事件传播

    事件委托是一种有用的模式,因为你可以只需要用一个事件处理程序就能侦听多个元素上的事件。

    使用事件委托需要三个步骤:

    • 确定要监视事件的元素的父级元素

    • 把将事件侦听器附加到父元素

    • event.target 选择目标元素

    更多计算机编程相关知识,请访问:编程视频!!

    Das obige ist der detaillierte Inhalt vonEine eingehende Analyse der Ereignisdelegation in JS. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

    Stellungnahme:
    Dieser Artikel ist reproduziert unter:51cto.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen
    Vorheriger Artikel:Lösung für AngularJS-DatenbindungsfehlerNächster Artikel:Lösung für AngularJS-Datenbindungsfehler

    In Verbindung stehende Artikel

    Mehr sehen