Web APIs - Day 3

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:

  1. The third parameter of addEventListener determines whether the event is fired in the capture phase or in the bubbling phase

  2. 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.

  3. Event flow will only have an effect if parent and child elements have the same event type

  4. 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

Tags: Front-end Javascript servlet

Posted by Wolfsoap on Sat, 22 Oct 2022 05:26:21 +1030