JavaScript事件流

2023-12-26 18:53:23

JavaScript

事件流

事件完整执行过程中的流动路径。包含事件捕获和事件冒泡两个阶段
event

事件捕获

从 DOM 根元素开始执行对应事件。

addEventListener(type, listener, useCapture)。useCapture 默认为 false(冒泡阶段触发),useCapture 设置为 true(捕获阶段触发)

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>事件捕获</title>
    <style>
      .father {
        width: 200px;
        height: 200px;
        background-color: skyblue;
      }

      .son {
        width: 100px;
        height: 100px;
        background-color: orange;
      }
    </style>
  </head>
  <body>
    <div class="father">
      <div class="son"></div>
    </div>

    <script>
      const father = document.querySelector('.father')
      const son = document.querySelector('.son')

      father.addEventListener(
        'click',
        function () {
          console.log('father...')
        },
        // 捕获阶段触发
        true
      )
      son.addEventListener(
        'click',
        function () {
          console.log('son...')
        },
        true
      )
    </script>
  </body>
</html>

事件捕获

如上:点击 son 对应的 div,从外到里依次执行 father->son 对应的 click 事件回调函数

事件冒泡

当一个元素触发事件后,依次向上执行所有父级元素对应的同名事件。事件冒泡默认存在。

addEventListener(type, listener, useCapture)。useCapture 默认为 false(冒泡阶段触发),沿着 DOM 树向上冒泡的事件会触发事件回调函数。

...
  <body>
    <div class="father">
      <div class="son"></div>
    </div>

    <script>
      const father = document.querySelector('.father')
      const son = document.querySelector('.son')

      father.addEventListener('click', function () {
        console.log('father...')
      })
      son.addEventListener('click', function () {
        console.log('son...')
      })
    </script>
  </body>
</html>

事件冒泡

如上:点击 son 对应的 div,从里到外依次执行 son->father 对应的 click 事件回调函数

阻止事件冒泡

stopPropagation:阻止事件传播

事件冒泡默认存在,在某些场景,导致父级元素受到影响。
使用"事件对象.stopPropagation()"来阻止事件传播(阻止事件捕获和事件冒泡),把事件限制在当前元素内

...
  <body>
    <div class="father">
      <div class="son"></div>
    </div>

    <script>
      const father = document.querySelector('.father')
      const son = document.querySelector('.son')

      father.addEventListener('click', function () {
        console.log('father...')
      })
      son.addEventListener('click', function () {
        console.log('son...')
        // 阻止事件传播
        e.stopPropagation()
      })
    </script>
  </body>
</html>

阻止事件传播

如上:点击 son 对应的 div,只执行 son 的 click 事件的回调函数

事件委托

利用事件冒泡的特点,给父元素设置事件,当子元素触发事件时,冒泡到父元素,触发父元素的事件。

减少事件注册次数,提高程序性能。

...
<div class="tab-nav">
  <ul>
    <li><a class="active" href="#">精选</a></li>
    <li><a href="#">美食</a></li>
    <li><a href="#">百货</a></li>
    <li><a href="#">个护</a></li>
    <li><a href="#">预告</a></li>
  </ul>
</div>
<script>
  // 1、给tab栏绑定点击事件
  // const as = document.querySelectorAll('.tab-nav li a')
  // for (let i = 0; i < as.length; i++) {
  //   as[i].addEventListener('click', function () {
  //     document.querySelector('.tab-nav .active').classList.remove('active')
  //     document
  //       .querySelector(`.tab-nav li:nth-child(${i + 1}) a`)
  //       .classList.add('active')
  //   })
  // }

  // 2、利用事件委托的方式给父元素添加事件
  const ul = document.querySelector('.tab-nav ul')

  ul.addEventListener('click', function (e) {
    if (e.target.tagName === 'A') {
      document.querySelector('.tab-nav .active').classList.remove('active')
      e.target.classList.add('active')
    }
  })
</script>
...

第一种方式循环遍历 li 元素给每一个 li 注册事件;第二种利用事件委托给父元素 ul 添加事件,当点击 li 里面的 a 标签时冒泡到父元素,触发父元素的点击事件。(通过"事件对象.target.tagName"来获得触发事件的元素)

记录学习JavaScript遇到的一些难点(学习途径:B站黑马程序员JavaScript视频,MDN)

文章来源:https://blog.csdn.net/weixin_50695682/article/details/135205033
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。