#事件委托

<!DOCTYPE html>
<html>
  <head>
    <title>事件委托示例</title>
  </head>
  <body>
    <ul id="parent-list">
      <li>列表项 1</li>
      <li>列表项 2</li>
      <li>列表项 3</li>
      <li>列表项 4</li>
    </ul>

    <script>
      const parentList = document.getElementById('parent-list')

      parentList.addEventListener('click', function (event) {
        if (event.target.tagName === 'LI') {
          console.log('你点击了列表项:', event.target.innerText)
        }
      })
    </script>
  </body>
</html>

在这个例子中,我们给父元素 ul 添加了一个点击事件监听器,在点击列表项时,判断点击的元素是否为 li 标签,如果是,则输出被点击的列表项的内容。这样无需为每一个列表项都添加点击事件监听器,只需要在父元素上监听事件,然后根据事件目标来执行相应的操作。

而这时访问目标 dom 就需要区分了,区别在于,e.currentTarget 会始终保持不变,而 e.target 会根据事件的冒泡路径而变化。举个例子,如果你给一个父元素绑定了点击事件,而点击的是这个父元素内的一个子元素,那么 e.currentTarget 就是父元素,e.target 就是子元素。

#事件捕获与事件冒泡

<!DOCTYPE html>
<html>
<head>
  <title>事件冒泡与事件捕获</title>
</head>
<body>

<div id="outer" style="border:1px solid black; padding:10px;">
  <div id="inner" style="border:1px solid red; padding:10px;">
    Click me
  </div>
</div>

<script>
  document.getElementById('outer').addEventListener('click', function() {
    console.log('父元素 - 事件冒泡');
  }, true);

  document.getElementById('inner').addEventListener('click', function() {
    console.log('子元素 - 事件冒泡');
  });

  document.getElementById('outer').addEventListener('click', function() {
    console.log('父元素 - 事件捕获');
  }, false);
</script>

</body>
</html>

在这个例子中,当点击"Click me"按钮时,会分别触发父元素和子元素上的事件处理程序。事件冒泡中先输出子元素的信息再输出父元素的信息,而事件捕获中先输出父元素的信息再输出子元素的信息。通过这种方式可以清楚地展示事件冒泡和事件捕获的不同表现方式。