事件的 捕获模式(Capture Phase) 是 DOM 事件流中的一个阶段,与 冒泡模式(Bubble Phase) 共同构成完整的事件传播流程。以下是详细解析:
1. 事件流的三个阶段
当 DOM 事件触发时(如点击元素),事件会经历三个阶段:
- 捕获阶段(Capture Phase)  - 从 window→ 目标元素的 父级链(自上而下)
- 默认情况下,事件监听器 不会在此阶段触发
 
- 从 
- 目标阶段(Target Phase)  - 到达实际触发事件的元素
 
- 冒泡阶段(Bubble Phase)  - 从目标元素 → window(自下而上)
- 大多数事件监听器在此阶段触发
 
- 从目标元素 → 
2. 捕获模式的核心特点
(1)触发顺序与冒泡相反
<div id="grand">
  <div id="parent">
    <button id="child">点击</button>
  </div>
</div>捕获模式 事件传播顺序:
- 捕获阶段:window→#grand→#parent(自上而下)
- 目标阶段:#child
- 冒泡阶段:#child→#parent→#grand(自下而上)
(2)需要显式启用
默认情况下,事件监听器在 冒泡阶段 触发。要启用捕获阶段监听,需明确指定:
// 原生 JS
element.addEventListener('click', handler, true); // 第三个参数 true 表示捕获阶段
// Vue 中的等效写法
<div @click.capture="handler"></div>3. Vue 中的捕获模式
通过 .capture 修饰符实现:
<div @click.capture="handleCapture">
  <button @click="handleClick">点击</button>
</div>执行顺序:
- 父元素的 handleCapture(捕获阶段)
- 子元素的 handleClick(目标阶段 + 冒泡阶段)
4. 典型应用场景
(1)优先拦截事件
<div @click.capture="checkPermission">
  <!-- 只有权限验证通过后,子元素事件才会执行 -->
  <button @click="submitData">提交</button>
</div>(2)避免冒泡被阻止
如果子元素调用了 event.stopPropagation(),冒泡阶段的事件会被阻止,但 捕获阶段的事件仍会执行:
// 子组件
methods: {
  handleClick() {
    this.$emit('click');
    event.stopPropagation(); // 阻止冒泡,但不影响捕获阶段
  }
}(3)性能优化
对大型列表使用事件委托时,捕获阶段可更早处理事件:
<ul @click.capture="handleItemClick">
  <li v-for="item in 1000" :key="item.id">{{ item.text }}</li>
</ul>5. 对比捕获与冒泡
| 特性 | 捕获阶段 | 冒泡阶段 | 
|---|---|---|
| 方向 | 顶层 → 目标元素(自上而下) | 目标元素 → 顶层(自下而上) | 
| 默认触发 | 需显式启用 | 是 | 
| Vue 语法 | `@event.capture` | @event | 
| 阻止传播的影响 | stopPropagation()不影响 | 会阻止后续冒泡 | 
6. 完整事件流示例
<div @click.capture="log('祖父捕获')">
  <div @click="log('父冒泡')" @click.capture="log('父捕获')">
    <button @click="log('目标')">点击</button>
  </div>
</div>输出顺序:
- 祖父捕获(捕获阶段)
- 父捕获(捕获阶段)
- 目标(目标阶段)
- 父冒泡(冒泡阶段)
7. 注意事项
- 谨慎使用捕获:可能打乱预期的事件顺序
- 避免过度拦截:在捕获阶段阻止传播会影响所有子元素
- 组件自定义事件:Vue 的 $emit事件 没有捕获阶段(仅限原生 DOM 事件)
理解捕获模式能帮助你更精细地控制事件流,尤其在需要 提前拦截事件 或 处理动态组件 时非常有用。
 我的书签
 我的书签
                                 添加书签
 添加书签 移除书签
 移除书签