Maison > Article > interface Web > Une introduction au flux d'événements de JavaScript
Recommandations d'apprentissage gratuites : tutoriel vidéo js
À propos du flux d'événements JavaScript
Avant-propos
Avant de lire cet article, je vous suggère de lire d'abord sur la boucle d'événements JavaScript. Bien sûr, pour ceux qui l'ont déjà fait. sachez-le Pas besoin ! Cet article va discuter du flux d’événements de js.
Texte
Nous savons tous que lorsque nous effectuons certains types d'opérations sur une page Web, comme cliquer, glisser, etc., certains événements correspondants seront déclenchés . Nous savons également que la page Web entière est en fait analysée dans une arborescence DOM par le navigateur. Lorsqu'un nœud génère un événement, l'événement se propagera dans un certain ordre entre le nœud et le nœud racine, et tous les nœuds passant par ce chemin de propagation recevront l'événement. L'ensemble de ce processus est appelé Flux d'événements DOM.
Que sont les événements ?
L'interaction entre js et html est en fait réalisée à travers des "événements". Tous les clics, sélections, diapositives, etc. des utilisateurs sur les pages Web sont tous des événements dans le monde js. Pour les événements, lorsqu'un événement se produit, il doit y avoir une réponse en js, la soi-disant réponse est un écouteur. Tout comme le modèle d'observateur, l'événement est notre sujet, et lorsque l'événement se produit, tous les auditeurs correspondant à l'événement (sujet) doivent être avertis pour effectuer les réponses correspondantes.Qu'est-ce que le flux d'événements ?
Le flux d'événements décrit l'ordre dans lequel les événements sont reçus de la page. Principalement divisé en deux types suivants :Bouillonnement d'événements vs capture d'événements
Le modèle de flux d'événements proposé par IE est un événement bouillonnant, c'est-à-dire que de bas en haut, il se propage vers le haut, étape par étape, depuis l'élément déclenché par la cible, jusqu'à l'objet document.Classification des événements DOM
Lorsqu'un événement se produit sur un nœud DOM, vous devez bien sûr faites le département correspondant, et les événements DOM sont divisés en 4 niveaux, comme suit :
Parmi eux, les plus importants sont DOM0/DOM2, nous allons donc nous concentrer sur eux ci-dessous.
Événement DOM0
Il existe deux manières principales d'implémenter des événements de niveau DOM0. La première est le modèle en ligne, qui utilise directement le nom de la fonction comme attribut d'événement dans le fichier. balise html. Comme suit :// js code// eventDOM.jsfunction btnClick() { console.log('Hello World')}
<!-- 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>Cependant, le modèle en ligne présente un défaut évident, c'est-à-dire qu'il viole l'exigence du W3C concernant la séparation du contenu (html) et du comportement (js). Il existe donc le deuxième type, qui est le modèle de script (modèle de liaison dynamique). La méthode spécifique consiste à sélectionner un nœud DOM spécifique via un script js, puis à ajouter des attributs d'événement et des valeurs d'attribut au nœud. Comme suit :
// js code// eventDOM.jslet btn = document.getElementById('btn')let btnClick = function() { console.log('Hello World')}btn.onclick = btnClickrrreeCliquez et
apparaîtra, pas de problème. Mais le modèle de script présente également des défauts. Sur la base du code html ci-dessus, ajoutez un petit js, comme suit : Hello World
<!-- 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>Nous avons constaté que désormais seul
apparaîtra lorsque vous cliquez. Par conséquent, le modèle de script permet à un seul nœud d'ajouter une seule fois des événements du même type, et les événements suivants écraseront les précédents. Hello World again
// 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
<!-- 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>
Quand on clique sur btn3, le résultat est le suivant :
Comme prévu, mais que se passe-t-il si on clique sur btn1 ? Le résultat est le suivant :
C'est un peu étrange, évidemment nous n'avons ajouté qu'un seul écouteur pour btn1, pourquoi avons-nous l'impression de l'avoir ajouté avec btn2 et btn3 ? La raison est que, bien que DOM0 ait deux modèles : le bouillonnement d'événements proposé par IE et la capture d'événements ? proposé par Netscape, en fait DOM0 ne prend en charge que le bouillonnement d'événements. Par conséquent, le flux d'événements en cliquant sur btn1 est le suivant :
Autrement dit, le flux d'événements passe également par btn2 et btn3, leur traitement d'événement est donc déclenché. Mais ce n’est évidemment pas le résultat que nous souhaitons.
Événements DOM2
Après des spécifications plus approfondies, il existe un gestionnaire d'événements de niveau DOM2. Deux méthodes sont définies :
Ces deux fonctions Chacune a trois paramètres comme indiqué dans le tableau ci-dessous :
參數 | 類型 | 描述 |
---|---|---|
event | String | 監聽的事件名稱,比如’click’。注意這邊都不需要"on" |
callback | function | 觸發事件所要執行的回調函數 |
useCapture | Boolean(default:false) | 事件是否在捕獲階段進行處理 |
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>
// 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)
輸出如下:
解決了 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>
// 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)
注意,這邊我們把 addEventListener
的第三個參數設為 true,也就是事件會在捕獲階段觸發。點擊 btn1 輸出如下:
看到順序與 DOM0 的順序反過來了。首先最外層(btn3)的節點先被觸發了,而因為第三個參數被設為 true,事件會在捕獲階段就被處理,所以輸出才會是 3,2,1。如果都是 false,就會是 1,2,3。
可見 DOM2 的事件處理機制有了更彈性的操作空間。我們也可以在不同階段綁定事件監聽器,看看下面例子:
<!-- 沿用上一段 html 代碼 -->
// 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)
點擊 btn1 輸出如下:
改變一下順序,如下:
<!-- 沿用上一段 html 代碼 -->
// 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)
點擊 btn1 輸出如下:
注意 btn1 的輸出。雖然捕獲階段先發生了,但是因為 btn1 本身就是目標節點,所以在這種情況下,總結出規律:在目標元素上不區分冒泡還是捕獲,是根據腳本中的順序來執行。
有時候,我們希望對於某節點,不要再經過冒泡階段了,DOM2 也提供了相應函數,stopPropagation
。
<!-- 沿用上一段 html 代碼 -->
// 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)
點擊 btn1 輸出如下:
可以看到,因為我們在 btn2 的捕獲階段就阻止了 btn2 的冒泡階段,所以 btn2 在捕獲後就不再繼續執行下去,確保不會冒泡,事件流如下:
加強一下前面提到的知識點,如果是在 btn1 阻止冒泡,會變成怎樣呢?
<!-- 沿用上一段 html 代碼 -->
// 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)
點擊 btn1 輸出如下:
雖然我們對 btn1 阻止了冒泡,但是為什麼還是輸出了 btn bubble
呢?原因就是前面提到了,目標節點不區分 捕獲/冒泡 階段,但是後面也就不會繼續冒泡了,算是個比較特殊的情況,可以稍微留意下。
結語
本篇大致介紹了 js 的事件流的各種模型以及階段上的工作任務,個人認為應該還算詳細。雖然個人感覺好像對編程本身沒有太明顯的幫助,但是還是算是 js 的一個重要的知識點,學習下也沒甚麼不好。若內容有誤,還歡迎指點!
相关免费学习推荐:javascript(视频)
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!