文章目录
-
- 前言
- 示例代码结构概览
- [1. `.prevent`:阻止默认行为](#1.
.prevent:阻止默认行为) - [2. `.stop`:阻止事件冒泡](#2.
.stop:阻止事件冒泡) - [3. `.once`:事件只触发一次](#3.
.once:事件只触发一次) - [4. `.capture`:使用事件捕获模式](#4.
.capture:使用事件捕获模式) - [5. `.self`:仅当事件由自身触发时才响应](#5.
.self:仅当事件由自身触发时才响应) - [6. `.passive`:立即执行默认行为,不等待回调](#6.
.passive:立即执行默认行为,不等待回调) - 完整代码
- 总结:事件修饰符速查表
- 结语
前言
在 Vue.js 开发中,事件处理是构建交互式用户界面的核心。除了基础的事件绑定(如 @click="handler"),Vue 还提供了一套强大的事件修饰符(Event Modifiers) ,让我们能以声明式的方式更优雅地控制事件行为,而无需在方法内部编写繁琐的 DOM 操作逻辑(如 event.preventDefault() 或 event.stopPropagation())。
本文将结合一个完整的示例,深入讲解 Vue 中六大常用事件修饰符:.prevent、.stop、.once、.capture、.self 和 .passive,帮助你全面掌握它们的使用场景与原理。
示例代码结构概览
我们先来看一下示例的整体结构:
html
<div id="root">
<h2>欢迎来到{{name}}学习</h2>
<!-- 各种事件修饰符的使用示例 -->
<a href="http://baidu.com" @click.prevent="showInfo">...</a>
<div @click="showInfo"><button @click.stop="showInfo">...</button></div>
<button @click.once="showInfo">...</button>
<div @click.capture="showMsg(1)">...</div>
<div @click.self="showInfo"><button>...</button></div>
<ul @scroll="demo" class="list">...</ul>
<ul @wheel.passive="demo1" class="list">...</ul>
</div>
对应的 Vue 实例定义了 showInfo、showMsg 等方法用于演示效果。
1. .prevent:阻止默认行为
作用
阻止元素的默认行为 。常用于 <a> 标签、表单提交等场景。
示例分析
html
<a href="http://baidu.com" @click.prevent="showInfo">点我提示信息</a>
- 正常情况下,点击链接会跳转到百度。
- 加上
.prevent后,event.preventDefault()被自动调用,阻止跳转 ,只执行showInfo方法弹出提示。
✅ 等价于 :在方法中手动写
e.preventDefault()
2. .stop:阻止事件冒泡
作用
阻止事件向父级元素冒泡(Bubble)。
示例分析
html
<div class="demo1" @click="showInfo">
<button @click.stop="showInfo">点我提示信息</button>
</div>
- 点击按钮时:
- 按钮自身的
@click.stop触发showInfo; - 但由于
.stop的存在,事件不会冒泡到外层 div ,所以 div 的点击事件不会触发。
- 按钮自身的
- 若去掉
.stop,点击按钮会连续弹出两次提示(一次来自 button,一次来自 div)。
📌 应用场景:避免嵌套可点击区域时的重复触发。
3. .once:事件只触发一次
作用
让事件处理器仅执行一次,之后自动移除监听器。
示例分析
html
<button @click.once="showInfo">点我提示信息</button>
- 第一次点击:弹出"同学你好!"
- 第二次及以后点击:无反应,因为监听器已被移除。
⚠️ 注意:
.once是 Vue 的特殊修饰符,不是原生 DOM API,但效果类似addEventListener(..., { once: true })。
4. .capture:使用事件捕获模式
作用
在捕获阶段(而非默认的冒泡阶段)触发事件处理器。
事件流回顾
DOM 事件流分为三个阶段:
- 捕获阶段(从 window 到目标元素)
- 目标阶段
- 冒泡阶段(从目标元素回传到 window)
默认 Vue 事件监听处于冒泡阶段 。.capture 强制改为捕获阶段。
示例分析
html
<div class="box1" @click.capture="showMsg(1)">
div1
<div class="box2" @click="showMsg(2)">
div2
</div>
</div>
- 点击 inner div(div2)时:
- 先触发 外层 div1 的
@click.capture→ 弹出 "同学你好!1" - 再触发 内层 div2 的
@click→ 弹出 "同学你好!2"
- 先触发 外层 div1 的
🔁 若都用默认冒泡,则顺序相反:先 2,后 1。
5. .self:仅当事件由自身触发时才响应
作用
只有当 event.target 等于当前绑定元素本身时,才触发回调。
示例分析
html
<div class="demo1" @click.self="showInfo">
<button @click="showInfo">点我提示信息</button>
</div>
- 点击 button :
- button 的点击事件触发(弹窗);
- 但 div 的
@click.self不触发 ,因为event.target是 button,不是 div。
- 点击 div 的空白区域 (非 button):
- div 的
@click.self会触发 ,因为此时event.target === div。
- div 的
🎯 与
.stop区别:.self不阻止冒泡,只是过滤触发条件。
6. .passive:立即执行默认行为,不等待回调
作用
告诉浏览器:不要等待事件处理函数执行完,立即执行默认行为(如滚动、缩放)。
背景
某些事件(如 touchmove、wheel)如果处理函数耗时较长,会导致页面卡顿。使用 .passive 可提升滚动流畅度。
示例分析
html
<ul @wheel.passive="demo1" class="list">...</ul>
-
demo1方法包含一个耗时循环(打印 10000 次):jsdemo1(){ for(let i = 0; i < 10000; i++) console.log('#') console.log('累坏了') } -
由于
.passive,滚轮操作会立即生效(列表可流畅滚动),而不会被 JS 阻塞。 -
若去掉
.passive,滚动会明显卡顿,直到demo1执行完毕。
⚠️ 限制:不能与
.prevent同时使用,因为 passive 模式下无法取消默认行为。
完整代码
css
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>事件修饰符</title>
<!-- 引入Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
<style>
*{
margin-top: 20px;
}
.demo1{
height: 50px;
background-color: skyblue;
}
.box1{
padding:5px;
background-color: skyblue;
}
.box2{
padding: 5px;
background-color: orange;
}
.list{
width: 200px;
height: 200px;
background-color: peru;
overflow: auto;
}
li{
height: 100px;
}
</style>
</head>
<body>
<!-- Vue中的事件修饰符:
1.prevent:阻止默认事件(常用);
2.stop:阻止事件冒泡(常用);
3.once:事件只触发一次(常用);
4.capture:使用事件的捕获模式;
5.self:只有event.target是当前操作的元素时才触发事件;
6.passive:事件的默认行为立即执行,无需等待事件回调执行完毕; -->
<!-- 准备好一个容器 -->
<div id="root">
<h2>欢迎来到{{name}}学习</h2>
<!-- 阻止默认事件(常用) -->
<a href="http://baidu.com" @click.prevent="showInfo">点我提示信息</a>
<!-- 阻止事件冒泡 -->
<div class="demo1" @click="showInfo">
<button @click.stop="showInfo">点我提示信息</button>
</div>
<!-- 事件只触发一次 -->
<button @click.once="showInfo">点我提示信息</button>
<!-- 使用事件的捕获模式 -->
<div class="box1" @click.capture="showMsg(1)">
div1
<div class="box2" @click="showMsg(2)">
div2
</div>
</div>
<!-- 只有event.target是当前操作的元素时才触发事件 -->
<div class="demo1" @click.self="showInfo">
<button @click="showInfo">点我提示信息</button>
</div>
<!-- 事件的默认行为立即执行,无需等待事件回调执行完毕 -->
<ul @scroll="demo" class="list">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
<ul @wheel.passive="demo1" class="list">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
</div>
<script type="text/javascript">
Vue.config.productionTip = false // 阻止Vue在启动时产生生产提示
const vm = new Vue({
el:'#root',
data:{
name:'上高山'
},
methods:{
showInfo(e){
// e.preventDefault() // 阻止事件的默认行为,也可以通过@click.prevent来阻止,prevent就是一个事件修饰符
alert('同学你好!')
},
showMsg(msg){
alert('同学你好!' + msg)
},
demo(){
console.log('@')
},
demo1(){
for(let i = 0; i < 10000; i++){
console.log('#')
}
console.log('累坏了')
}
}
})
</script>
</body>
</html>

总结:事件修饰符速查表
| 修饰符 | 作用 | 常见场景 |
|---|---|---|
.prevent |
阻止默认行为 | 阻止链接跳转、表单提交 |
.stop |
阻止事件冒泡 | 嵌套点击区域防重复触发 |
.once |
事件只触发一次 | 初始化操作、一次性确认 |
.capture |
使用捕获阶段 | 需要先处理外层逻辑 |
.self |
仅自身触发才响应 | 精确控制事件源 |
.passive |
默认行为立即执行 | 优化滚动、触摸性能 |
💡 组合使用 :Vue 允许多个修饰符连用,如
@click.stop.prevent。
结语
Vue 的事件修饰符极大简化了 DOM 事件的控制逻辑,使代码更清晰、性能更优。掌握这些修饰符,不仅能写出更健壮的交互逻辑,还能避免常见的事件陷阱(如冒泡干扰、滚动卡顿等)。建议在实际项目中根据需求灵活选用,提升用户体验与开发效率。
🌟 最佳实践 :优先使用修饰符,而非在方法中手动调用
event.stopPropagation()或preventDefault()------ 这正是 Vue 声明式编程的魅力所在。