v-on是 Vue 中最常用的指令之一,用于监听 DOM 事件。它的简写形式@更是随处可见。看似简单的语法,实际使用中却有不少细节值得注意。
v-on 的完整写法和简写:
<!-- 完整写法 -->
<button v-on:click="handleClick">点击</button>
<!-- 简写(推荐) -->
<button @click="handleClick">点击</button>
两种写法完全等价,实际开发中简写更常见,代码更简洁。
当逻辑非常简单时,可以直接在模板中写 JavaScript 语句:
<div id="app">
<button @click="count += 1">计数:{{ count }}</button>
<button @click="message = '点击了'">改变消息</button>
<p>{{ message }}</p>
</div>
<script>
new Vue({
el: '#app',
data: {
count: 0,
message: '未点击'
}
})
</script>
内联语句适合简单的数据操作,比如计数器、切换布尔值。但要注意,复杂的业务逻辑不要写在模板里,会让代码难以维护。
更常见的做法是将事件处理逻辑放在 methods 中:
<div id="app">
<button @click="greet">打招呼</button>
<button @click="addToCart(product)">加入购物车</button>
</div>
<script>
new Vue({
el: '#app',
data: {
product: {
id: 1,
name: 'Vue 实战教程',
price: 99
}
},
methods: {
greet: function() {
alert('欢迎学习 Vue!')
},
addToCart: function(item) {
console.log('添加商品:', item.name)
// 这里可以调用 API、更新数据等
}
}
})
</script>
方法处理器的优势在于:
<div id="app">
<button @click="say('hello')">说 hello</button>
<button @click="say('goodbye')">说 goodbye</button>
<!-- 传递多个参数 -->
<button @click="add(10, 20)">计算 10 + 20</button>
</div>
<script>
new Vue({
el: '#app',
methods: {
say: function(word) {
alert(word)
},
add: function(a, b) {
alert(a + ' + ' + b + ' = ' + (a + b))
}
}
})
</script>
有时我们需要访问原生 DOM 事件对象,比如阻止默认行为、获取鼠标位置等。
方式一:不传参数时自动传入
<button @click="handleClick">点击</button>
<script>
methods: {
handleClick: function(event) {
// event 是原生 DOM 事件对象
console.log(event.target) // 触发事件的元素
event.preventDefault() // 阻止默认行为
}
}
</script>
方式二:使用 $event 显式传入
当需要同时传递自定义参数和事件对象时,使用 $event 变量:
<button @click="handle('按钮', $event)">点击</button>
<script>
methods: {
handle: function(message, event) {
console.log(message) // '按钮'
console.log(event.target) // 原生事件对象
}
}
</script>
<div id="app">
<div v-for="item in products" :key="item.id" class="product-item">
<span>{{ item.name }} - ¥{{ item.price }}</span>
<button @click="edit(item)">编辑</button>
<button @click="remove(item.id)">删除</button>
</div>
</div>
<script>
new Vue({
el: '#app',
data: {
products: [
{ id: 1, name: 'iPhone 15', price: 5999 },
{ id: 2, name: 'MacBook Pro', price: 12999 },
{ id: 3, name: 'AirPods Pro', price: 1899 }
]
},
methods: {
edit: function(item) {
console.log('编辑商品:', item.name)
// 打开编辑弹窗等操作
},
remove: function(id) {
if (confirm('确定删除?')) {
this.products = this.products.filter(item => item.id !== id)
}
}
}
})
</script>
<form @submit="handleSubmit">
<input type="text" v-model="username" placeholder="用户名">
<input type="password" v-model="password" placeholder="密码">
<button type="submit">登录</button>
</form>
<script>
methods: {
handleSubmit: function(event) {
event.preventDefault() // 阻止表单默认提交
// 验证数据
if (!this.username || !this.password) {
alert('请填写完整信息')
return
}
// 发送登录请求
console.log('登录:', this.username)
}
}
</script>
Vue 支持所有原生 DOM 事件,常用的有:
| 事件 | 触发时机 | 典型用途 |
|---|---|---|
click | 点击 | 按钮操作、导航 |
submit | 表单提交 | 登录、注册、搜索 |
input | 输入内容变化 | 实时搜索、表单验证 |
change | 值改变并失焦 | 下拉选择、复选框 |
focus | 获得焦点 | 表单提示、高亮 |
blur | 失去焦点 | 表单验证 |
keyup/keydown | 键盘按键 | 快捷键、搜索 |
mouseenter/mouseleave | 鼠标进入/离开 | 悬停效果 |
<!-- 各种事件示例 -->
<input @input="onInput" placeholder="实时搜索">
<select @change="onSelect">...</select>
<input @focus="onFocus" @blur="onBlur">
<div @mouseenter="showTooltip" @mouseleave="hideTooltip">
不要在模板中写复杂逻辑
<!-- ❌ 不推荐 -->
<button @click="items.filter(i => i.active).length > 0 ? process() : warn()">
处理
</button>
<!-- ✅ 推荐 -->
<button @click="handleProcess">处理</button>
复杂逻辑放在 methods 中,模板保持简洁。
methods 中的 this 自动绑定
Vue 自动将 methods 中的方法绑定到组件实例,所以你可以放心使用 this:
methods: {
handleClick: function() {
console.log(this.message) // 正确访问 data
this.sayHello() // 正确调用其他方法
}
}
不需要手动 .bind(this),Vue 已经帮你处理好了。
事件监听是 Vue 交互的基础,掌握以下几点:
@click 比 v-on:click 更常用$event 的配合使用