Maison > interface Web > js tutoriel > le corps du texte

Une introduction au flux d'événements de JavaScript

coldplay.xixi
Libérer: 2021-02-14 10:30:59
avant
2663 Les gens l'ont consulté

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
  • Texte
    • Qu'est-ce qu'un événement ?
    • Qu'est-ce que S'agit-il d'un flux d'événements ?
    • Bouillonnement d'événements vs capture d'événements
    • Hiérarchie des événements DOM
    • Événement DOM0
    • Événement DOM2
  • Conclusion

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 d'IE
  • Capture d'événements de Netscape

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.


Le modèle de flux d'événements proposé par Netscape est la capture d'événements, contrairement au bouillonnement d'événements, il se fait de haut en bas, c'est-à-dire qu'il se propage de l'objet document à l'étape de l'objet cible. par étape.


Ce qui précède est le mécanisme de flux d'événements selon la norme DOM0. Plus tard, ECMAScript a standardisé davantage le flux d'événements dans DOM2. Dans DOM2, le flux d'événements contenu dans un événement est divisé en trois étapes suivantes :

    Étape de capture d'événement (capture)
  1. Étape cible (cible)
  2. Étape de bouillonnement d'événements (bulle)

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')}
Copier après la connexion
<!-- 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>
Copier après la connexion
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 = btnClick
Copier après la connexion
rrreeCliquez 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>
Copier après la connexion
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

Enfin, regardons un exemple intéressant :

// 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
Copier après la connexion
<!-- 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>
Copier après la connexion
Copier après la connexion

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 :

  • addEventListener() Ajouter un écouteur d'événement
  • removeEventListener() Supprimer un écouteur d'événement

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>
Copier après la connexion
// 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)
Copier après la connexion

輸出如下:

解決了 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>
Copier après la connexion
Copier après la connexion
// 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)
Copier après la connexion

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

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

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

<!-- 沿用上一段 html 代碼 -->
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
// 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)
Copier après la connexion

點擊 btn1 輸出如下:

改變一下順序,如下:

<!-- 沿用上一段 html 代碼 -->
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
// 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)
Copier après la connexion

點擊 btn1 輸出如下:

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

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

<!-- 沿用上一段 html 代碼 -->
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
// 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)
Copier après la connexion

點擊 btn1 輸出如下:

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

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

<!-- 沿用上一段 html 代碼 -->
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
// 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)
Copier après la connexion

點擊 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!

Étiquettes associées:
source:csdn.net
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal