Vue 父拦截子点击

285 阅读1分钟

有这样一个结构:

<!-- 父组件 -->
<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() 实现对子组件点击事件的有效拦截和控制,常用于“父拦截子点击”场景。