LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

事件流与事件委托:当点击按钮时,浏览器里发生了什么?

zhenglin
2026年4月2日 9:4 本文热度 69

你点了一个按钮,但它可能不是“它”自己响应的。今天我们就来扒一扒浏览器里那场“谁该负责”的点击风波——事件流。从捕获到冒泡,从目标阶段到事件委托,让你彻底弄懂点一下按钮,背后的整个江湖。

前言

想象一下,你点了一个按钮。这个按钮在一个卡片里,卡片在一个列表里,列表在一个页面里。那么问题来了:是按钮自己“听到”了点击,还是卡片先听到,还是页面先听到?

浏览器其实有一套严格的“传话”机制:事件流。它规定了事件从哪来,到哪去,谁先响应。今天我们就来当一回“事件侦探”,追踪一次点击的完整旅程。


一、事件流三阶段:从外到内,再从内到外

当一个事件(比如点击)发生时,它会在DOM树里走一个完整的“U型”路线:

  1. 捕获阶段:事件从window往下走,经过祖先节点,一直到目标元素的父节点。这个阶段像“下楼梯”。

  2. 目标阶段:事件到达目标元素(你点的那个按钮)。这个阶段像“踩到地雷”。

  3. 冒泡阶段:事件从目标元素往上走,经过父节点、祖先节点,一直到window。这个阶段像“上楼梯”。

用代码验证一下:

<div id="parent">

  <button id="child">点我</button>

</div>

const parent = document.getElementById('parent');

const child = document.getElementById('child');


parent.addEventListener('click', () => console.log('parent 捕获'), true);

parent.addEventListener('click', () => console.log('parent 冒泡'));

child.addEventListener('click', () => console.log('child 捕获'), true);

child.addEventListener('click', () => console.log('child 冒泡'));


// 点击按钮,输出顺序:

// parent 捕获

// child 捕获

// child 冒泡

// parent 冒泡

addEventListener的第三个参数useCapturetrue表示在捕获阶段触发,false(默认)表示在冒泡阶段触发。

二、事件代理:把监听器交给“外包公司”

假如你有一个列表,里面有一百个按钮。给每个按钮都加一个点击事件,不仅代码繁琐,而且内存占用高。这时候,事件委托(又叫事件代理)就派上用场了。

原理:利用事件冒泡,把监听器加在父元素上,然后通过event.target判断具体是哪个子元素被点击。

<ul id="list">

  <li>选项1</li>

  <li>选项2</li>

  <li>选项3</li>

</ul>

const list = document.getElementById('list');

list.addEventListener('click', (e) => {

  // e.target 是实际被点击的元素

  if (e.target.tagName === 'LI') {

    console.log('你点了:', e.target.textContent);

  }

});

这样,不管以后动态添加多少<li>,都不用再单独绑定事件了。这就是事件委托的威力——用一个监听器管理所有子元素。


三、阻止传播:中途截胡

有时候,你不想让事件继续往上冒泡,可以用stopPropagation()

child.addEventListener('click', (e) => {

  e.stopPropagation(); // 事件不再向上冒泡

  console.log('点到按钮了');

});

如果既想阻止冒泡,又不想影响当前元素的其他同类型监听器,可以用stopImmediatePropagation()

注意:不是所有事件都冒泡。比如focusblurscroll不冒泡,但focusinfocusout冒泡。


四、阻止默认行为:让浏览器别“自动执行”

有些事件有默认行为,比如点击<a>会跳转,点击表单提交按钮会刷新页面。你可以用preventDefault()阻止它。

document.querySelector('a').addEventListener('click', (e) => {

  e.preventDefault(); // 不会跳转

  console.log('链接被点了,但不跳转');

});

五、实战:事件委托实现todo列表的删除

我们来升级昨天的待办列表,用事件委托管理删除按钮。

<div id="todo-app">

  <input id="todo-input" type="text" placeholder="输入待办">

  <button id="add-btn">添加</button>

  <ul id="todo-list"></ul>

</div>

const input = document.getElementById('todo-input');

const addBtn = document.getElementById('add-btn');

const list = document.getElementById('todo-list');


function addTodo() {

  const text = input.value.trim();

  if (!text) return;

  

  const li = document.createElement('li');

  li.innerHTML = `${text} <button class="delete-btn">删除</button>`;

  list.appendChild(li);

  input.value = '';

}


// 事件委托:监听整个列表

list.addEventListener('click', (e) => {

  if (e.target.classList.contains('delete-btn')) {

    const li = e.target.closest('li'); // 找到按钮所在的li

    li.remove();

  }

});


addBtn.addEventListener('click', addTodo);

input.addEventListener('keypress', (e) => {

  if (e.key === 'Enter') addTodo();

});

这里用e.target.closest('li')而不是直接e.target.parentNode,因为删除按钮可能在<li>内部的任意层级,closest能向上找到最近的匹配元素,更健壮。


六、常见坑与最佳实践

1. 混淆 target 和 currentTarget

  • e.target:实际触发事件的元素(你点的是哪个)

  • e.currentTarget:绑定了监听器的元素(监听器加在谁身上)

在事件委托中,currentTarget是父元素,target是子元素。不要搞混。


2. 阻止冒泡要谨慎

如果你用了第三方组件,随便stopPropagation可能影响别人的监听器。除非确有必要,否则别轻易阻止冒泡。


3. 事件委托的局限

如果事件本身不冒泡(如focus),或者你需要在捕获阶段做特殊处理,事件委托就派不上用场。但绝大多数点击、输入事件都冒泡。


4. 性能考虑

委托给父元素时,父元素不宜过于靠上(比如document),否则事件触发频率太高,判断条件过多。最好委托给最近的、包含所有子元素的祖先。


七、总结:事件流的“传话”逻辑

    • 事件流分三阶段:捕获(从上到下)→ 目标 → 冒泡(从下到上)

    • 事件委托:利用冒泡,把监听器加在父元素上,通过target判断具体子元素。减少监听器数量,动态元素也适用。

    • 阻止传播stopPropagation让事件不再往上冒泡。

    • 阻止默认行为preventDefault让浏览器的默认动作失效。

    掌握了事件流,你就掌握了交互的底层逻辑。明天我们将继续深入,聊聊自定义事件——让你能像浏览器一样“派发”事件,让代码之间优雅通信。


    参考文章:原文链接

    该文章在 2026/4/2 9:04:23 编辑过
    关键字查询
    相关文章
    正在查询...
    点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
    点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
    点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
    点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
    Copyright 2010-2026 ClickSun All Rights Reserved