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:
- Capture phase
- Current target stage
- 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
- JavaScript can only capture or bubble one of the phases
onclick
和attachEvent
You just get the bubble phaseaddEventListener(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- Some events are not bubbling, such as:
onblur
,onfocus
,onmouseenter
,onmouseleave
等 - 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 clickedson
When, none of the parent elements above it will appear;- if
father
You also have parents on it and you don’t want them to pop out, you also need to be infather
To 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