Vue 3 中事件修饰符 prevent stop capture

FreeGuideOnline 最新 2026-07-07

什么是 Vue 事件修饰符

在 Vue 3 中,事件修饰符是附加在 v-on 指令(或 @ 简写)后面的特殊后缀,用于直接在模板中控制事件行为,无需在方法里写额外逻辑。它们让代码更简洁、更符合声明式思维。

常用修饰符有:

  • .prevent —— 阻止默认行为
  • .stop —— 阻止事件冒泡
  • .capture —— 使用捕获模式监听

修饰符可以串联使用,例如 @click.prevent.stop

准备工作

教程基于 Vue 3 单文件组件(SFC)演示。确保你已搭建好 Vue 3 开发环境(如 Vite 或 Vue CLI)。以下示例可直接在 <template><script setup> 中使用。

.prevent 修饰符

@event.prevent 等价于在事件处理函数中调用 event.preventDefault(),用于阻止元素的默认行为。

典型场景

  • 阻止 <a> 标签的跳转
  • 阻止表单提交时页面刷新
  • 阻止 <form> 的默认提交行为

代码示例

<template>
  <div>
    <!-- 链接只执行方法不会跳转 -->
    <a href="https://example.com" @click.prevent="handleClick">
      点击不会跳转
    </a>

    <!-- 表单提交不刷新页面 -->
    <form @submit.prevent="onSubmit">
      <input type="text" v-model="username" />
      <button type="submit">提交</button>
    </form>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const username = ref('')

const handleClick = () => {
  console.log('链接被点击,但未跳转')
}

const onSubmit = () => {
  console.log('表单数据:', username.value)
  // 可在此执行异步提交,页面不会刷新
}
</script>

修饰符串联

如果需要同时阻止默认行为和事件冒泡,可以写成:

<a href="#" @click.prevent.stop="doSomething">阻止默认且停止冒泡</a>

顺序不影响效果,但习惯上先写行为修饰符。

.stop 修饰符

@event.stop 等价于 event.stopPropagation(),用于阻止事件向父元素冒泡。

典型场景

  • 点击内部按钮时不触发外层容器的点击事件
  • 下拉菜单内部点击时不关闭菜单

代码示例

<template>
  <div @click="outerClick" class="outer-box">
    外层点击我会触发
    <button @click.stop="innerClick" class="inner-btn">
      内部按钮不会冒泡到外层
    </button>
  </div>
</template>

<script setup>
const outerClick = () => {
  console.log('外层被点击')
}
const innerClick = () => {
  console.log('内部按钮被点击')
}
</script>

<style scoped>
.outer-box {
  padding: 20px;
  background: #e2e8f0;
  border-radius: 8px;
}
.inner-btn {
  margin-top: 10px;
}
</style>

点击内部按钮时,只会输出“内部按钮被点击”,外层的 outerClick 不会触发。

关键注意点

  • .stop 只阻止事件向上冒泡,不影响当前元素的其他监听器。
  • 如果父元素也有 .stop,不会影响当前元素的冒泡阻止。

.capture 修饰符

浏览器事件流分三个阶段:捕获阶段、目标阶段、冒泡阶段。默认事件监听在冒泡阶段触发,添加 .capture 后会在捕获阶段触发。

实际作用

  • 让父元素的事件优先于子元素的冒泡事件触发
  • 适合需要在事件到达目标元素之前拦截的场景

执行顺序示例

<template>
  <div @click.capture="captureParent" class="capture-box">
捕获阶段先触发
    <button @click="childClick">子按钮</button>
  </div>
</template>

<script setup>
const captureParent = () => {
  console.log('父元素捕获阶段触发')
}
const childClick = () => {
  console.log('子按钮冒泡阶段触发')
}
</script>

点击子按钮时,控制台输出顺序为:

  1. 父元素捕获阶段触发
  2. 子按钮冒泡阶段触发

如果去掉 .capture,默认冒泡模式下,父的事件在子之后触发。

多个捕获监听器

如果多个祖先元素都使用 .capture,则从最外层向目标元素依次触发捕获事件。

修饰符的组合与技巧

1. .capture.stop

阻止捕获阶段继续向下传递(少见但实用):

<div @click.capture.stop="stopCapture">...</div>

2. .self

虽然不是 prevent/stop/capture,但常配合使用。@event.self 只当 event.target 是元素自身时才触发,类似“忽略子元素冒泡上来的事件”。

<div @click.self="onlySelf">只有点我本身才触发</div>

3. 修饰符顺序无影响

@click.prevent.stop@click.stop.prevent 效果相同,都会既阻止默认行为又阻止冒泡。

常见问题

Q:能在方法内调用 event.preventDefault() 吗? 可以,但使用 .prevent 修饰符更简洁,且模板中能清晰表明意图。

Q:动态事件能否使用修饰符? 修饰符只能在模板中使用。如果动态绑定事件,需要在处理函数内手动调用 preventDefaultstopPropagation

Q:Vue 3 删除了哪些修饰符? .native 已被移除,组件默认会透传所有监听器,不再需要 .native。其他修饰符保持与 Vue 2 一致。

总结

修饰符 效果 等价原生代码
.prevent 阻止默认行为 event.preventDefault()
.stop 阻止事件冒泡 event.stopPropagation()
.capture 捕获阶段触发监听 addEventListener(..., true)

掌握这三个修饰符,能让你在处理表单、链接、嵌套交互等场景时代码更简洁。建议在实际项目中根据需求自由组合,并优先使用修饰符而非在方法里写事件控制代码。