Further study event advancement, realize more interactive web page special effects, and optimize the efficiency of event execution combined with the characteristics of event flow
-
Learn how to stop events from bubbling
-
Understand the implementation principle of event delegation
event stream
The event flow is a description of the event execution process. Understanding the event execution process helps to deepen the understanding of the event and improve the flexibility of the event application in development practice.
As shown in the figure above, when any event is triggered, it will always go through two phases: the [capture phase] and the [bubbling phase].
In short, the capture phase is the transmission process from the father to the son, and the bubbling phase is the transmission process from the son to the father.
catching and bubbling
Now that we understand what event flow is, let's see how event flow affects event execution:
<body> <h3>event stream</h3> <p>Event flow is the underlying mechanism of event execution, which is mainly reflected in the execution of events between parent and child boxes.</p> <div class="outer"> <div class="inner"> <div class="child"></div> </div> </div> <script> // Get nested 3 nodes const outer = document.querySelector('.outer'); const inner = document.querySelector('.inner'); const child = document.querySelector('.child'); // html element add event document.documentElement.addEventListener('click', function () { console.log('html...') }) // body element add event document.body.addEventListener('click', function () { console.log('body...') }) // Outer box add event outer.addEventListener('click', function () { console.log('outer...') }) // middle box add event outer.addEventListener('click', function () { console.log('inner...') }) // Inner box add event outer.addEventListener('click', function () { console.log('child...') }) </script> </body>
After executing the above code, it is found that when the click event is triggered, the click events of its ancestor elements are also triggered successively. Why is this?
Combined with the characteristics of event flow, we know that when an event of an element is triggered, the event will always pass through its ancestors to reach the current element, and then passed from the current element to the ancestor. The event encounters the same The event will be triggered.
Another detail to pay attention to is the [execution order] of events triggered one after another. The execution order of events is controllable, that is, it can be executed in the capture phase or in the bubbling phase.
If the event is executed in the bubbling phase, we call it bubbling mode. It will execute the child box event first and then execute the parent box event. The default is bubbling mode.
If the event is executed in the capture phase, we call it capture mode, it will first execute the parent box event and then execute the child box event.
<body> <h3>event stream</h3> <p>Event flow is the underlying mechanism of event execution, which is mainly reflected in the execution of events between parent and child boxes.</p> <div class="outer"> <div class="inner"></div> </div> <script> // Get nested 3 nodes const outer = document.querySelector('.outer') const inner = document.querySelector('.inner') // outer box outer.addEventListener('click', function () { console.log('outer...') }, true) // true to execute the event during the capture phase // middle box outer.addEventListener('click', function () { console.log('inner...') }, true) </script> </body>
in conclusion:
-
The third parameter of addEventListener determines whether the event is fired in the capture phase or in the bubbling phase
-
The third parameter of addEventListener is true, which means that the capture phase is triggered, and false means that the bubbling phase is triggered. The default value is false.
-
Event flow will only have an effect if parent and child elements have the same event type
-
Most scenes use the default bubbling mode (one of the reasons is that early IE does not support capture)
stop bubbling
Preventing bubbling refers to blocking the flow of events, ensuring that events are only executed on the current element and no longer affect its corresponding ancestor elements.
<body> <h3>stop bubbling</h3> <p>Preventing bubbling refers to blocking the flow of events, ensuring that events are only executed on the current element and no longer affect its corresponding ancestor elements.</p> <div class="outer"> <div class="inner"> <div class="child"></div> </div> </div> <script> // Get nested 3 nodes const outer = document.querySelector('.outer') const inner = document.querySelector('.inner') const child = document.querySelector('.child') // outer box outer.addEventListener('click', function () { console.log('outer...') }) // middle box inner.addEventListener('click', function (ev) { console.log('inner...') // prevent events from bubbling ev.stopPropagation() }) // inner box child.addEventListener('click', function (ev) { console.log('child...') // Stop events from bubbling up with the help of event objects ev.stopPropagation() }) </script> </body>
Conclusion: The ev.stopPropagation method in the event object is designed to stop the event from bubbling.
Mouse over event:
mouseover and mouseout will have a bubbling effect
mouseenter and mouseleave have no bubbling effect (recommended)
event delegation
Event delegation is a knowledge skill that uses the characteristics of event flow to solve some practical development needs, and its main function is to improve program efficiency.
A large number of event listeners are more performance-intensive, as shown in the following code
Using the characteristics of event flow, the above code can be optimized. The bubbling mode of the event will always flow the event to its parent element. If the parent element listens to the same event type, the event of the parent element will be triggered. And execute, it is to use this feature to optimize the above code, as shown in the following code:
<script> // Suppose there are 10000 button elements in the page let buttons = document.querySelectorAll('table button'); // Suppose the common ancestor element of the above 10000 button elements is table let parents = document.querySelector('table'); parents.addEventListener('click', function () { console.log('Clicking on any child element will trigger an event...'); }) </script>
Our ultimate goal is to ensure that the callback function of the event is executed only when the button sub-element is clicked. How to determine which sub-element the user clicks?
The attribute target or srcElement in the event object represents the element that actually triggers the event, which is a node of element type.
<script> // Suppose there are 10000 button elements in the page const buttons = document.querySelectorAll('table button') // Suppose the common ancestor element of the above 10000 button elements is table const parents = document.querySelector('table') parents.addEventListener('click', function (ev) { // console.log(ev.target); // Only the button element will actually execute the logic if(ev.target.tagName === 'BUTTON') { // logic to execute } }) </script>
The optimized code only adds event listeners to ancestor elements, which is much more efficient than adding event listeners to 10,000 elements! ! !
other events
page load event
Event fired when loading external resources (such as images, out-line CSS, JavaScript, etc.)
Sometimes you need to wait for all the page resources to be processed to do something
Event name: load
Monitor the page when all resources are loaded:
window.addEventListener('load', function() { // xxxxx })
element scroll event
The event that is fired continuously while the scroll bar is scrolling
window.addEventListener('scroll', function() { // xxxxx })
page size event
The event will be fired when the window size changes:
window.addEventListener('resize', function() { // xxxxx })
Element size and position
Get the element's own width and height, including the width and height set by the element itself, padding, border
offsetWidth and offsetHeight
The obtained value is a numerical value, which is convenient for calculation
Note: Obtained is the visible width and height, if the box is hidden, the obtained result is 0