Heim > Web-Frontend > js-Tutorial > Eine Einführung in den Ereignisfluss von JavaScript

Eine Einführung in den Ereignisfluss von JavaScript

coldplay.xixi
Freigeben: 2021-02-14 10:30:59
nach vorne
2701 Leute haben es durchsucht

Eine Einführung in den Ereignisfluss von JavaScript

Kostenlose Lernempfehlung: js-Video-Tutorial

Über den JavaScript-Ereignisfluss

  • Vorwort
  • Text
    • Was sind Ereignisse? ?
    • Was ist Event-Stream?
    • Ereignisblasen vs. Ereigniserfassung
    • DOM-Ereignisklassifizierung
    • DOM0-Ereignis
    • DOM2-Ereignis
  • Fazit

Vorwort

Bevor Sie diesen Artikel lesen, empfehle ich Ihnen, sich zuerst die JavaScript-Ereignisse anzusehen. Natürlich Für diejenigen, die es bereits wissen, sind keine Schleifen erforderlich. In diesem Artikel wird der Ereignisfluss von js erläutert.

Text

Wir alle wissen, dass einige entsprechende Ereignisse ausgelöst werden, wenn wir bestimmte Arten von Vorgängen auf einer Webseite ausführen, z. B. Klicken, Schieben usw. Wir wissen auch, dass die gesamte Webseite vom Browser tatsächlich in einen DOM-Baum geparst wird. Wenn ein Knoten ein Ereignis generiert, wird das Ereignis in einer bestimmten Reihenfolge zwischen dem Knoten und dem Wurzelknoten weitergegeben, und alle Knoten, die diesen Ausbreitungspfad durchlaufen, empfangen das Ereignis. Dieser gesamte Prozess wird als „DOM-Ereignisfluss“ bezeichnet.

Was sind Ereignisse?

Die Interaktion zwischen js und html wird tatsächlich durch „Ereignisse“ realisiert. Alle Benutzerklicks, Auswahlen, Folien usw. auf Webseiten sind Ereignisse in der js-Welt.

Bei Ereignissen muss es eine Antwort geben, wenn ein Ereignis auftritt. In js ist die sogenannte Antwort der Listener. Genau wie beim Beobachtermuster ist das Ereignis unser Subjekt, und wenn das Ereignis eintritt, müssen alle Zuhörer, die dem Ereignis (Subjekt) entsprechen, benachrichtigt werden, um entsprechende Antworten auszuführen.

Was ist Ereignisfluss?

Ereignisfluss beschreibt die Reihenfolge, in der Ereignisse von der Seite empfangen werden. Hauptsächlich in die folgenden zwei Typen unterteilt:

IEs Event-Bubbling

    Netscapes Event-Capture
  • Event-Bubbling vs. Event-Capture

Das von IE vorgeschlagene Event-Flow-Modell ist Event-Bubbling, also von unten nach oben , wird das vom Ziel ausgelöste Element Schritt für Schritt nach oben bis zum Dokumentobjekt propagiert.


Das von Netscape vorgeschlagene Ereignisflussmodell ist die Ereigniserfassung und erfolgt von oben nach unten, dh es wird Schritt für Schritt vom Dokumentobjekt zum Zielobjekt weitergegeben.


Das Obige ist der Ereignisflussmechanismus unter dem DOM0-Standard. Später standardisierte ECMAScript den Ereignisfluss in DOM2 weiter. In DOM2 ist der in einem Ereignis enthaltene Ereignisfluss in die folgenden drei Phasen unterteilt:

Ereigniserfassungsphase (Erfassung)

    Zielphase (Ziel)
  1. Ereignisblasenphase (Blase)

  2. DOM-Ereignis Klassifizierung

Wenn ein Ereignis auf einem DOM-Knoten auftritt, muss es natürlich entsprechend behandelt werden, und DOM-Ereignisse werden wie folgt in 4 Ebenen unterteilt:

Unter diesen sind DOM0/DOM2 die wichtigeren Auf sie konzentriert sich das Folgende.

DOM0-Ereignis

Ereignisse auf DOM0-Ebene werden hauptsächlich auf zwei Arten implementiert. Die erste ist das Inline-Modell, bei dem der Funktionsname direkt als Attributwert des Ereignisattributs im HTML-Tag verwendet wird. Wie folgt:

// js code// eventDOM.jsfunction btnClick() {
    console.log('Hello World')}
Nach dem Login kopieren
<!-- html code --><html>
    <head>
        <title>eventDOM demo</title>
    </head>
    <body>
        <p onclick="btnClick()" style="width: 30px; height: 30px; background-color:black"></p>
        <script type="text/javascript" src="eventDOM.js"></script>
    </body></html>
Nach dem Login kopieren
Aber das Inline-Modell weist einen offensichtlichen Mangel auf, nämlich dass es gegen die W3C-Anforderungen zur Trennung von Inhalt (HTML) und Verhalten (JS) verstößt. Es gibt also den zweiten Typ, das Skriptmodell (dynamisches Bindungsmodell). Die spezifische Methode besteht darin, einen bestimmten DOM-Knoten über ein JS-Skript auszuwählen und dem Knoten dann Ereignisattribute und Attributwerte hinzuzufügen. Wie folgt:

// js code// eventDOM.jslet btn = document.getElementById('btn')let btnClick = function() {
    console.log('Hello World')}btn.onclick = btnClick
Nach dem Login kopieren
<!-- html code --><html>
    <head>
        <title>eventDOM demo</title>
    </head>
    <body>
        <p id="btn" style="width: 30px; height: 30px; background-color:black"></p>
        <script type="text/javascript" src="eventDOM.js"></script>
    </body></html>
Nach dem Login kopieren
Klicken Sie und Hello World erscheint, kein Problem. Aber das Skriptmodell weist auch Mängel auf. Fügen Sie basierend auf dem obigen HTML-Code ein wenig js hinzu, wie folgt:

// js code// eventDOM.jslet btn = document.getElementById('btn')let btnClick = function() {
    console.log('Hello World')}let btnClick2 = function() {
    console.log('Hello World again')}btn.onclick = btnClick
btn.onclick = btnClick2
Nach dem Login kopieren
Wir haben festgestellt, dass jetzt nur noch Hallo Welt angezeigt wird. Daher erlaubt das Skriptmodell einem Knoten nur einmal, Ereignisse desselben Typs hinzuzufügen, und nachfolgende Ereignisse überschreiben die vorherigen.

Hello World,沒問題。但腳本模型一樣有缺點,基於上面的 html 代碼,添加一點 js,如下:

<!-- html code --><html>
    <head>
        <title>eventDOM demo</title>
    </head>
    <body>
        <p id="btn3" style="width: 400px; height: 400px; background-color:pink">
            btn3            <p id="btn2" style="width: 300px; height: 300px; background-color:skyblue">
                btn2                <p id="btn1" style="width: 200px; height: 200px; background-color:lightgreen">
                    btn1                </p>
            </p>
        </p>
        <script type="text/javascript" src="eventDOM.js"></script>
    </body></html>
Nach dem Login kopieren
Nach dem Login kopieren

我們發現,現在點擊只會出現 Hello World againSchauen wir uns zum Schluss noch ein interessantes Beispiel an:

// js code// eventDOM.jslet btn1 = document.getElementById('btn1')let btn2 = document.getElementById('btn2')let btn3 = document.getElementById('btn3')btn1.onclick = function() {
    console.log('1')}btn2.onclick = function() {
    console.log('2')}btn3.onclick = function() {
    console.log('3')}
Nach dem Login kopieren
<!-- html code --><html>
    <head>
        <title>eventDOM demo</title>
    </head>
    <body>
        <p id="btn" style="width: 200px; height: 200px; background-color:lightgreen"></p>
        <script type="text/javascript" src="eventDOM.js"></script>
    </body></html>
Nach dem Login kopieren
Nach dem Login kopieren

Wenn wir auf BTN3 klicken, ist die Ausgabe wie folgt:

Wie erwartet, aber was ist, wenn wir auf BTN1 klicken? Die Ausgabe ist wie folgt:

Das ist offensichtlich etwas seltsam. Wir haben nur einen Listener für BTN1 hinzugefügt Warum fühlt es sich an, als ob btn2 und btn3 zusammengezählt werden? Der Grund dafür ist, dass DOM0 zwar zwei Modelle hat: das vom IE vorgeschlagene Ereignis-Bubbling und das von Netscape vorgeschlagene Ereignis-Capturing, aber tatsächlich nur das Ereignis-Bubbling unterstützt. Daher ist der Ereignisfluss beim Klicken auf BTN1 wie folgt:

Das heißt, der Ereignisfluss durchläuft auch BTN2 und BTN3, sodass deren Ereignisverarbeitung ausgelöst wird. Aber offensichtlich ist dies nicht das Ergebnis, das wir wollen.

DOM2-Ereignisse

Nach weiterer Spezifikation gibt es einen Ereignishandler auf DOM2-Ebene. Es sind zwei Methoden definiert:

  • addEventListener() Ereignis-Listener hinzufügen
  • removeEventListener() Ereignis-Listener entfernen

Beide Funktionen haben drei Parameter, wie in der folgenden Tabelle gezeigt:

Parameters type Description
event String Der Name des überwachten Ereignisses, z. B. „Klick“. Beachten Sie, dass hier kein „Ein“ erforderlich ist.
Rückruf Funktion Die Rückruffunktion, die ausgeführt werden soll, um das Ereignis auszulösen in der Erfassungsphase verarbeitet

DOM2 中就可以對同一個節點綁定兩個以上的同類型事件監聽器了,看看下面例子:

<!-- html code --><html>
    <head>
        <title>eventDOM demo</title>
    </head>
    <body>
        <p id="btn" style="width: 200px; height: 200px; background-color:lightgreen"></p>
        <script type="text/javascript" src="eventDOM.js"></script>
    </body></html>
Nach dem Login kopieren
Nach dem Login kopieren
// js code// eventDOM.jslet btn = document.getElementById('btn')function hello() {
    console.log("Hello World")}function helloAgain() {
    console.log("Hello World again")}btn.addEventListener('click', hello, false)btn.addEventListener('click', helloAgain, false)
Nach dem Login kopieren

輸出如下:

解決了 DOM0 只能綁定一個同類型事件監聽器的缺點啦!值得注意的是,如果綁定同樣的監聽器兩次以上,仍然只會觸發一次。

再回到上面三個 p 的那個例子進行改寫如下:

<!-- html code --><html>
    <head>
        <title>eventDOM demo</title>
    </head>
    <body>
        <p id="btn3" style="width: 400px; height: 400px; background-color:pink">
            btn3            <p id="btn2" style="width: 300px; height: 300px; background-color:skyblue">
                btn2                <p id="btn1" style="width: 200px; height: 200px; background-color:lightgreen">
                    btn1                </p>
            </p>
        </p>
        <script type="text/javascript" src="eventDOM.js"></script>
    </body></html>
Nach dem Login kopieren
Nach dem Login kopieren
// js code// eventDOM.jslet btn1 = document.getElementById('btn1')let btn2 = document.getElementById('btn2')let btn3 = document.getElementById('btn3')btn1.addEventListener('click', function() {
    console.log('1')}, true)btn2.addEventListener('click', function() {
    console.log('2')}, true)btn3.addEventListener('click', function() {
    console.log('3')}, true)
Nach dem Login kopieren

注意,這邊我們把 addEventListener 的第三個參數設為 true,也就是事件會在捕獲階段觸發。點擊 btn1 輸出如下:

看到順序與 DOM0 的順序反過來了。首先最外層(btn3)的節點先被觸發了,而因為第三個參數被設為 true,事件會在捕獲階段就被處理,所以輸出才會是 3,2,1。如果都是 false,就會是 1,2,3。

可見 DOM2 的事件處理機制有了更彈性的操作空間。我們也可以在不同階段綁定事件監聽器,看看下面例子:

<!-- 沿用上一段 html 代碼 -->
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
// js code// eventDOM.jsbtn1.addEventListener('click',function() {
    console.log('btn1 capture')}, true)btn1.addEventListener('click',function() {
    console.log('btn1 bubble')}, false)btn2.addEventListener('click',function() {
    console.log('btn2 capture')}, true)btn2.addEventListener('click',function() {
    console.log('btn2 bubble')}, false)btn3.addEventListener('click',function() {
    console.log('btn3 capture')}, true)btn3.addEventListener('click',function() {
    console.log('btn3 bubble')}, false)
Nach dem Login kopieren

點擊 btn1 輸出如下:

改變一下順序,如下:

<!-- 沿用上一段 html 代碼 -->
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
// js code// eventDOM.jsbtn1.addEventListener('click',function() {
    console.log('btn1 bubble')}, false)btn1.addEventListener('click',function() {
    console.log('btn1 capture')}, true)btn2.addEventListener('click',function() {
    console.log('btn2 bubble')}, false)btn2.addEventListener('click',function() {
    console.log('btn2 capture')}, true)btn3.addEventListener('click',function() {
    console.log('btn3 bubble')}, false)btn3.addEventListener('click',function() {
    console.log('btn3 capture')}, true)
Nach dem Login kopieren

點擊 btn1 輸出如下:

注意 btn1 的輸出。雖然捕獲階段先發生了,但是因為 btn1 本身就是目標節點,所以在這種情況下,總結出規律:在目標元素上不區分冒泡還是捕獲,是根據腳本中的順序來執行。

有時候,我們希望對於某節點,不要再經過冒泡階段了,DOM2 也提供了相應函數,stopPropagation

<!-- 沿用上一段 html 代碼 -->
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
// js code// eventDOM.jsbtn1.addEventListener('click',function() {
    console.log('btn1 capture')}, true)btn1.addEventListener('click',function() {
    console.log('btn1 bubble')}, false)btn2.addEventListener('click',function(e) {
    e.stopPropagation()
    console.log('btn2 capture')}, true)btn2.addEventListener('click',function() {
    console.log('btn2 bubble')}, false)btn3.addEventListener('click',function() {
    console.log('btn3 capture')}, true)btn3.addEventListener('click',function() {
    console.log('btn3 bubble')}, false)
Nach dem Login kopieren

點擊 btn1 輸出如下:

可以看到,因為我們在 btn2 的捕獲階段就阻止了 btn2 的冒泡階段,所以 btn2 在捕獲後就不再繼續執行下去,確保不會冒泡,事件流如下:

加強一下前面提到的知識點,如果是在 btn1 阻止冒泡,會變成怎樣呢?

<!-- 沿用上一段 html 代碼 -->
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
// js code// eventDOM.jsbtn1.addEventListener('click',function(e) {
    e.stopPropagation()
    console.log('btn1 capture')}, true)btn1.addEventListener('click',function() {
    console.log('btn1 bubble')}, false)btn2.addEventListener('click',function() {
    console.log('btn2 capture')}, true)btn2.addEventListener('click',function() {
    console.log('btn2 bubble')}, false)btn3.addEventListener('click',function() {
    console.log('btn3 capture')}, true)btn3.addEventListener('click',function() {
    console.log('btn3 bubble')}, false)
Nach dem Login kopieren

點擊 btn1 輸出如下:

雖然我們對 btn1 阻止了冒泡,但是為什麼還是輸出了 btn bubble呢?原因就是前面提到了,目標節點不區分 捕獲/冒泡 階段,但是後面也就不會繼續冒泡了,算是個比較特殊的情況,可以稍微留意下。

結語

本篇大致介紹了 js 的事件流的各種模型以及階段上的工作任務,個人認為應該還算詳細。雖然個人感覺好像對編程本身沒有太明顯的幫助,但是還是算是 js 的一個重要的知識點,學習下也沒甚麼不好。若內容有誤,還歡迎指點!

相关免费学习推荐:javascript(视频)

Das obige ist der detaillierte Inhalt vonEine Einführung in den Ereignisfluss von JavaScript. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:csdn.net
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage