1. Event flow

The event stream is the order in which the page receives events,

That is, events are propagated between element nodes in a particular order, and this propagation is called a DOM event stream

The event flow is divided into three phases:

  1. Capture phase
  2. Current target stage
  3. Bubbling phase

Event bubbling: A process first proposed by IE in which an event is initially received by a specific element and propagated hierarchically up to the topmost node of the DOM

Event capture: First described by Netscape, the process of starting with the topmost node of the DOM and propagating down the hierarchy to the most specific element received

Target stage: Specific elements to reach

When we register a click event for div:

1.1 Capture phase and bubble phase

  1. JavaScript can only capture or bubble one of the phases
  2. onclickattachEventYou just get the bubble phase
  3. addEventListener(type, listener[, useCapture])And the third argument if it’strue, indicating that the event handler is invoked during the event capture phase; If it isfalse(Do not write The default isfalse) to invoke the event handler during the event bubbling phase
  4. Some events are not bubbling, such as:onblur,onfocus,onmouseenter,onmouseleave
  5. In real development, we rarely use event capture, we focus more on event bubbling
<div class="parent">
    <div class="son"></div>
</div>
Copy the code
let parent = document.querySelector('.parent')
let son = document.querySelector('.son');
Copy the code

Capture stage:

Document -> HTML -> body -> father -> son
// When you click on son, pop father, then pop son

son.addEventListener('click'.function() {
    alert('son')},true)

parent.addEventListener('click'.function() {
    alert('father')},true)
Copy the code

Bubbling stage:

// Son -> father -> body -> HTML -> document
// When clicking on son, pop son first, then pop father

son.addEventListener('click'.function() {
    alert('son')},false)

parent.addEventListener('click'.function() {
    alert('father')},false)
Copy the code

2.2 Preventing events from bubbling

To prevent bubbling: e.topPropagation ()

The method is simple: place the statement in the event handler at which node you want to prevent event bubbling

  • e.stopPropagation();Add it to the son element when clickedsonWhen, none of the parent elements above it will appear;
  • iffatherYou also have parents on it and you don’t want them to pop out, you also need to be infatherTo adde.stopPropagation();
<div class="parent">
    <a href="https://www.baidu.com"></a>
</div>
Copy the code
let parent = document.querySelector('.parent')
let baidu = document.querySelector('a');

// When we click baidu, we go directly to baidu home page instead of father
baidu.addEventListener('click'.function(e) {
	e.stopPropagation()
})

parent.addEventListener('click'.function() {
    alert('father')})Copy the code

But be warned,

  • e.stopPropagation()Compatibility issues
  • For earlier versions of browsers:window.event.cancelBubble = true, non-standard

When you need to consider compatibility issues, you can make a judgment:

if (e && e.stopPropagation()) {
    e.stopPropagation()
} else {
    window.event.cancelBubble = true
}
Copy the code

E.toppropagation () is the best way to do this

2.3 Event Delegation

Most of the time, bubbling events do cause us trouble, and we all choose to prevent them from bubbling, but bubbling events aren’t all bad

When we click on the li below, we want to add a style to it. Previously, we used to find the Li with for, binding a click event to each LI, which is tedious, and the more times we visit the DOM, this will increase the interaction ready time of the entire page

<ul>
    <li>Love really takes courage</li>
    <li>Love really takes courage</li>
    <li>Love really takes courage</li>
    <li>Love really takes courage</li>
    <li>Love really takes courage</li>
</ul>
Copy the code

Now we can use event delegates to simplify this process

Event delegates are also called event proxies, or event delegates in jQuery

Event delegation principle

Instead of setting event listeners separately for each child node, you set event listeners on its parent node and then affect each child node using the bubbling principle

So, in the above example, we can register a click event for UL, and then use the target of the event object to find the current hit li. The event will bubble up to ul, the parent of LI. Ul has a registration event, which will trigger the event listener

What the event delegate does: We only manipulate the DOM once, improving performance

let ul = document.querySelector('ul')
let lis = document.querySelectorAll('li');

ul.addEventListener('click'.function(e) {
	// e.target finds the currently clicked object li
	// Exclusivity
    for (let i = 0; i < lis.length; i++) {
        lis[i].style.color = ' '
    }
    // Add a style to it
    e.target.style.color = 'red'
})
Copy the code