JavaScript 词条目录
前端Wiki/JavaScript/进阶/事件

事件冒泡与委托

点击页面上的某个元素时,事件并不是只发生在它身上,而是像水泡一样从它开始逐层向外传播:li → ul → body → html,这个过程叫冒泡。所以给外层元素绑监听器,也能收到内层元素的事件。

事件委托正是利用冒泡的技巧:不给 100 个列表项各绑一个监听器,而是给父元素 ul 绑一个,在处理函数里用 e.target 判断真正点的是谁。好处是:监听器少、内存省;动态新增的子元素无需重新绑定就自动生效。

委托时的判断手段:e.target.tagName 看标签名、e.target.matches('.item') 匹配选择器、e.target.dataset.act 读取 data-act 自定义属性。需要阻止向上冒泡时调用 e.stopPropagation()。

本节要点事件沿 DOM 树向外冒泡;把监听器绑在父元素上、用 e.target 分发,就是事件委托;委托对动态新增的子元素同样有效。
HTML
<ul id="list">
  <li>苹果 <button data-act="del">删除</button></li>
  <li>香蕉 <button data-act="del">删除</button></li>
  <li>橘子 <button data-act="del">删除</button></li>
</ul>
<script>
  const list = document.getElementById('list');

  // 只绑一个监听器,管理所有 li(包括以后新增的)
  list.addEventListener('click', (e) => {
    if (e.target.dataset.act === 'del') {
      // 点的是删除按钮:删掉它所在的 li
      e.target.closest('li').remove();
      console.log('删除了一项,剩余:' + list.children.length);
    } else if (e.target.tagName === 'LI') {
      console.log('选中:' + e.target.firstChild.textContent);
    }
  });
</script>