事件监听

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 交互的基础,掌握以下几点:

  1. 简写优先@clickv-on:click 更常用
  2. 方法处理器:复杂逻辑放在 methods 中
  3. 参数传递:自定义参数和 $event 的配合使用
  4. 代码组织:保持模板简洁,逻辑集中在 methods