有这样一个结构:
<!-- 父组件 -->
<template>
<div class="parent" @click="onParentClick">
<ChildComponent />
</div>
</template>
<script setup>
import ChildComponent from "./ChildComponent.vue"
const onParentClick = () => {
console.log('父组件被点击');
};
</script>
<!-- 子组件 ChildComponent.vue -->
<template>
<button class="child" @click="onChildClick">子组件</button>
</template>
<script setup>
const onChildClick = () => {
console.log('子组件被点击');
};
</script>
示例 1:只在父组件中使用 .capture
📌 @click.capture 用法
-
语法:
@事件名.capture="处理函数" -
含义:事件监听器在捕获阶段被调用(默认是在冒泡阶段)。
-
说明:
- DOM 事件流分为三个阶段:捕获阶段 → 目标阶段 → 冒泡阶段。
.capture修饰符让事件在“从根节点往目标元素传播”过程中被拦截处理。
<!-- 父组件 -->
<template>
<div class="parent" @click.capture="onParentClick">
<ChildComponent />
</div>
</template>
<script setup>
import ChildComponent from "./ChildComponent.vue"
const onParentClick = (e) => {
console.log('父组件(捕获阶段)监听到点击');
};
</script>
👉 父先执行,但子组件仍然会执行自己的点击事件。
示例 2:在父组件中加上 e.stopPropagation()(拦截)
📌 e.stopPropagation()
-
作用:阻止事件继续传播到下一个阶段(不会冒泡或再捕获到其他元素)。
-
结合
.capture使用:- 在捕获阶段就阻止了事件传播,所以子组件内部即使有点击事件,也不会触发。
<!-- 父组件 -->
<template>
<div class="parent" @click.capture="onParentClick">
<ChildComponent />
</div>
</template>
<script setup>
import ChildComponent from "./ChildComponent.vue"
const onParentClick = (e) => {
e.stopPropagation();
console.log('父组件阻止了事件传播');
};
</script>
👉 子组件的点击事件被拦截,不会执行!
示例 3:不使用 .capture,直接监听冒泡阶段 + 阻止
<!-- 父组件 -->
<template>
<div class="parent" @click="onParentClick">
<ChildComponent />
</div>
</template>
<script setup>
import ChildComponent from "./ChildComponent.vue"
const onParentClick = (e) => {
e.stopPropagation();
console.log('父组件在冒泡阶段阻止了事件');
};
</script>
👉 因为子组件先执行了,父组件虽然拦截,但来不及阻止子组件的事件触发。
总结
使用 @click.capture 可以在事件捕获阶段执行逻辑,并配合 e.stopPropagation() 实现对子组件点击事件的有效拦截和控制,常用于“父拦截子点击”场景。