JavaScript Web APIs Day 3 Notes

Insert image description here

Web APIs - Day 3

Learn more about event advancement, achieve more interactive web page special effects, and optimize the efficiency of event execution by combining the characteristics of event streams.

  • Learn how to stop events from bubbling up
  • Understand the implementation principles of event delegation

event stream

Event flow is a description of the event execution process. Understanding the event execution process can help deepen the understanding of events and improve the flexibility of event use in development practice.

The external link image transfer failed. The source site may have an anti-leeching mechanism. It is recommended to save the image and upload it directly.

As shown in the figure above, any event will always go through two stages when it is triggered: [capture stage] and [bubbling stage].

In short, the capture stage is the transmission process [from father to son], and the bubbling stage is the transmission process [from son to father].

capture and bubble

After understanding what event flow is, let's look at how event flow affects event execution:

<body>
  <h3>事件流</h3>
  <p>事件流是事件在执行时的底层机制,主要体现在父子盒子之间事件的执行上。</p>
  <div class="outer">
    <div class="inner">
      <div class="child"></div>
    </div>
  </div>
  <script>
    // 获取嵌套的3个节点
    const outer = document.querySelector('.outer');
    const inner = document.querySelector('.inner');
    const child = document.querySelector('.child');
		
    // html 元素添加事件
    document.documentElement.addEventListener('click', function () {
      
      
      console.log('html...')
    })
		
    // body 元素添加事件
    document.body.addEventListener('click', function () {
      
      
      console.log('body...')
    })

    // 外层的盒子添加事件
    outer.addEventListener('click', function () {
      
      
      console.log('outer...')
    })
    
    // 中间的盒子添加事件
    outer.addEventListener('click', function () {
      
      
      console.log('inner...')
    })
    
    // 内层的盒子添加事件
    outer.addEventListener('click', function () {
      
      
      console.log('child...')
    })
  </script>
</body>

After executing the above code, we found that when the click event is triggered, the click events of its ancestor elements are also triggered one after another. 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 before reaching the current element, and then passed from the current element to the ancestors. The event encounters the same event during the flow process. The event will be triggered.

Another detail that we should pay attention to is the [execution order] in which events are 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 stage, we call it bubbling mode. It will execute the child box event first and then 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 execute the parent box event first and then execute the child box event.

<body>
  <h3>事件流</h3>
  <p>事件流是事件在执行时的底层机制,主要体现在父子盒子之间事件的执行上。</p>
  <div class="outer">
    <div class="inner"></div>
  </div>
  <script>
    // 获取嵌套的3个节点
    const outer = document.querySelector('.outer')
    const inner = document.querySelector('.inner')

    // 外层的盒子
    outer.addEventListener('click', function () {
      
      
      console.log('outer...')
    }, true) // true 表示在捕获阶段执行事件
    
    // 中间的盒子
    outer.addEventListener('click', function () {
      
      
      console.log('inner...')
    }, true)
  </script>
</body>

in conclusion:

  1. addEventListenerThe third parameter determines whether the event is triggered in the capture phase or the bubbling phase.
  2. addEventListenerThe third parameter is, truewhich indicates the capture phase trigger, falsewhich indicates the bubbling phase trigger. The default value isfalse
  3. Event flow will only have an effect if the 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 did not support capture)

Stop bubbling

Preventing bubbling means blocking the flow of events to ensure that events are only executed on the current element and no longer affect its corresponding ancestor elements.

<body>
  <h3>阻止冒泡</h3>
  <p>阻止冒泡是指阻断事件的流动,保证事件只在当前元素被执行,而不再去影响到其对应的祖先元素。</p>
  <div class="outer">
    <div class="inner">
      <div class="child"></div>
    </div>
  </div>
  <script>
    // 获取嵌套的3个节点
    const outer = document.querySelector('.outer')
    const inner = document.querySelector('.inner')
    const child = document.querySelector('.child')

    // 外层的盒子
    outer.addEventListener('click', function () {
      
      
      console.log('outer...')
    })

    // 中间的盒子
    inner.addEventListener('click', function (ev) {
      
      
      console.log('inner...')

      // 阻止事件冒泡
      ev.stopPropagation()
    })

    // 内层的盒子
    child.addEventListener('click', function (ev) {
      
      
      console.log('child...')

      // 借助事件对象,阻止事件向上冒泡
      ev.stopPropagation()
    })
  </script>
</body>

Conclusion: The method in the event object ev.stopPropagationis specifically used to prevent events 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 and skill that uses the characteristics of event streams to solve some practical development needs. Its main function is to improve program efficiency.

A large number of event monitoring is relatively performance-intensive, as shown in the following code

<script>
  // 假设页面中有 10000 个 button 元素
  const buttons = document.querySelectorAll('table button');

  for(let i = 0; i <= buttons.length; i++) {
      
      
    // 为 10000 个 button 元素添加了事件
    buttons.addEventListener('click', function () {
      
      
      // 省略具体执行逻辑...
    })
  }
</script>

Using the characteristics of the event stream, 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, then the event of the parent element will be triggered. And execute, it is this feature that is used to optimize the above code, as shown in the following code:

<script>
  // 假设页面中有 10000 个 button 元素
  let buttons = document.querySelectorAll('table button');
  
  // 假设上述的 10000 个 buttom 元素共同的祖先元素是 table
  let parents = document.querySelector('table');
  parents.addEventListener('click', function () {
      
      
    console.log('点击任意子元素都会触发事件...');
  })
</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 external link image transfer failed. The source site may have an anti-leeching mechanism. It is recommended to save the image and upload it directly.

targetThe attribute or attribute in the event object srcElementrepresents the element that actually triggered the event, which is a node of element type.

<script>
  // 假设页面中有 10000 个 button 元素
  const buttons = document.querySelectorAll('table button')
  
  // 假设上述的 10000 个 buttom 元素共同的祖先元素是 table
  const parents = document.querySelector('table')
  parents.addEventListener('click', function (ev) {
      
      
    // console.log(ev.target);
    // 只有 button 元素才会真正去执行逻辑
    if(ev.target.tagName === 'BUTTON') {
      
      
      // 执行的逻辑
    }
  })
</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 triggered when external resources (such as images, external CSS and JavaScript, etc.) are loaded.

Sometimes you need to wait for all page resources to be processed to do something

Event name: load

All resources on the monitoring page have been loaded:

window.addEventListener('load', function() {
    
    
    // xxxxx
})

element scroll event

Events that are continuously triggered when the scroll bar is scrolling

window.addEventListener('scroll', function() {
    
    
    // xxxxx
})

page size event

Events will be triggered 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, padding, and border set by the element itself.

offsetWidth和offsetHeight

What is obtained is a numerical value, which is convenient for calculation.

Note: What is obtained is the visible width and height. If the box is hidden, the obtained result is 0.

inch incident

Events will be triggered 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, padding, and border set by the element itself.

offsetWidth和offsetHeight

What is obtained is a numerical value, which is convenient for calculation.

Note: What is obtained is the visible width and height. If the box is hidden, the obtained result is 0.

Guess you like

Origin blog.csdn.net/upgrade_bro/article/details/133462834