Detailed explanation of JavaScript event flow


DOM event stream

To understand the flow of events, we must first understand three things:

  • Elements are not independent, they are concatenated
  • When a single element triggers an event, it will affect other elements
  • The way of event flow: event capture (proposed by Netscape), event bubbling (proposed by IE)
    insert image description here

Let's take the above picture as an example. Suppose you bind a click event to the div. When you click on the div, other elements will also be involved, which will cause the effect of affecting the whole body .


There are two ways of event flow: 事件冒泡,事件捕获

event bubbling

insert image description here
Event bubbling stage: trigger the target event immediately after clicking on the div , and then bubble up layer by layer

event capture

insert image description here
Event capture stage: After clicking on the div, the event of the div will not be triggered immediately , but will be captured layer by layer, and the event will be triggered when the div is finally reached.


In fact, these two stages may be encountered in future project development, because different binding event methods create different event stages (bubbling/capturing)

Scenario 1: Bind events directly in HTML

<body onclick="console.log('我是body')">
    <button onclick="console.log('我是button')">
        <span onclick="console.log('我是span')">快乐按钮</span>
    </button>
</body>

Effect:
Please add image description
As can be seen from the above figure, when we click on the span tag, the events on the upper button and the events on the body will be executed in the order of bubbling


Scenario 2: [domNode].onclick() method - DOM0 level

html:

<body>
    <button>
        <span>快乐按钮</span>
    </button>
</body>

javascript:

var body = document.getElementsByTagName('body')[0];
var button = document.getElementsByTagName('button')[0];
var span = document.getElementsByTagName('span')[0];

body.onclick = function() {
    
    console.log('我是body')};
button.onclick = function() {
    
    console.log('我是button')};
span.onclick = function() {
    
    console.log('我是span')};

Effect:
Please add image description
We found that the way of binding events at DOM0 level is still in the form of bubbling


Scenario 3: [domNode].addEventListener() method - DOM2 level

addEvenListener(事件名事件触发后的回调布尔值)

false (default): Indicates that the event handler is invoked during the bubbling phase
true: Indicates that the event handler is invoked during the capturing phase

html:

<body>
    <button>
        <span>快乐按钮</span>
    </button>
</body>

javascript:

var body = document.getElementsByTagName('body')[0];
var button = document.getElementsByTagName('button')[0];
var span = document.getElementsByTagName('span')[0];

function theName() {
    
    console.log('我是' + this.nodeName)};

body.addEventListener('click',theName,false);
button.addEventListener('click',theName,false);
span.addEventListener('click',theName,false);

Effect:
Please add image description
We can see that when the third parameter of addEventListener is false (the default is false if not written), the event flow is bubbling.

When we change the third parameter to true:

......
body.addEventListener('click',theName,true);
button.addEventListener('click',theName,true);
span.addEventListener('click',theName,true);

Please add image description
We found that the execution order is body --> button --> span, which is the event capture phase.


DOM level 2 regulations:

  • The event flow consists of three stages (1. Capture stage 2. Target stage 3. Bubbling stage)
  • 执行循序Should be followed: Capture Phase -> Target Phase -> Bubble Phase

That is to say, when you click on the target element, the trigger event will not be executed immediately, but the event capture phase will be executed first -> then in the target phase (trigger event) -> event bubbling phase

Let's take a look at a classic interview question: What is the output order when we click on baby?
insert image description here
html:

<body>
    <div class="grandma">grandma奶奶
        <div class="mother">mother妈妈
            <div class="daughter">daughter
                <div class="baby">baby婴儿</div>
            </div>
        </div>
    </div>
</body>

javascript:

var grandma = document.getElementsByClassName('grandma')[0]
var mother = document.getElementsByClassName('mother')[0]
var daughter = document.getElementsByClassName('daughter')[0]
var baby = document.getElementsByClassName('baby')[0]

function theName() {
    
    
    console.log('我是' + this.className);
}

baby.addEventListener('click', theName, false)//冒泡
daughter.addEventListener('click', theName, true)//捕获
mother.addEventListener('click', theName, true)//捕获
grandma.onclick = theName//冒泡

Result: The
insert image description here
idea of ​​​​doing the question:

  1. First divide the elements that bind the event to capture? bubble? we can see daughterand motherfor 捕获; babyand grandmafor冒泡
  2. Because DOM2 stipulates that the first capture and then bubbling , so one of daughter and mother will be printed first
  3. Because the capture is from top to bottom (dom root -> div), so first print mother and then daughter
  4. Because the bubbling is from bottom to top (div->dom root), so print baby and then print grandma

Guess you like

Origin blog.csdn.net/weixin_60297362/article/details/123314010