Skip to content
On this page

用户点击按钮、输入文字、移动鼠标……这些都是"事件"。Vue 用 v-on 指令来监听这些事件。

基本用法

v-on 用于绑定事件处理函数:

vue
<template>
  <button v-on:click="handleClick">点我</button>
</template>
<script>
export default {
  methods: {
    handleClick() {
      alert('按钮被点了!')
    }
  }
}
</script>

v-on:click="handleClick" 的意思是:当这个按钮被点击时,调用 handleClick 方法

简写

v-on: 太长,日常用 @ 简写:

vue
<button @click="handleClick">点我</button>     <!-- 等于 v-on:click -->
<input @input="handleInput">                   <!-- 等于 v-on:input -->
<form @submit="handleSubmit">                  <!-- 等于 v-on:submit -->

看到 @ 就理解为"当...事件发生时"。

给方法传参

vue
<template>
  <button @click="say('Hello')">打招呼</button>
  <button @click="say('再见')">说再见</button>
</template>
<script>
export default {
  methods: {
    say(msg) {
      alert(msg)
    }
  }
}
</script>

💡 Tip:需要事件对象怎么办? 如果你既要传参,又要拿到事件对象,用 $event

vue
<button @click="handle('参数', $event)">点我</button>

事件修饰符

很多事件需要加上"额外操作",比如阻止表单自动提交、防止事件冒泡。Vue 提供了修饰符,在事件后面加 .xxx 就行。 | 修饰符 | 作用 | 不用 Vue 你要写 | | .prevent | 阻止默认行为(如表单提交、a 标签跳转) | e.preventDefault() | | .stop | 阻止事件冒泡(点击子元素不会触发父元素) | e.stopPropagation() | | .once | 事件只触发一次 | 手动加标志位 | | .self | 只在事件源是自身时触发 | if (e.target === e.currentTarget) | | .capture | 在捕获阶段触发 | 第三个参数 true |

vue
<template>
  <!-- 表单提交时不会刷新页面 -->
  <form @submit.prevent="onSubmit">
    <input type="text">
    <button type="submit">提交</button>
  </form>
  <!-- 点击"点我"不会触发灰色区域的点击事件 -->
  <div @click="onOuterClick" style="background: gray; padding: 20px">
    <button @click.stop="onInnerClick">点我</button>
  </div>
</template>

按键修饰符

监听键盘事件时,可以指定按键:

vue
<!-- 只有按回车时触发 -->
<input @keyup.enter="onEnter">
<!-- 只有按 Esc 时触发 -->
<input @keyup.escape="onCancel">

支持的按键别名:.enter.tab.delete.esc.space.up.down.left.right 也可以直接用键码:@keyup.13(13 = 回车键码,不过用别名更直观)

组合键

vue
<!-- Ctrl + 回车 -->
<input @keyup.ctrl.enter="onCtrlEnter">
<!-- 精确匹配:只有 Ctrl 被按下(不能同时按其他键) -->
<button @click.ctrl.exact="onCtrlOnly">精确 Ctrl</button>

内联处理

简单逻辑可以直接写在模板里,不用定义方法:

vue
<template>
  <button @click="count++">点了 {{ count }}</button>
</template>
<script>
export default {
  data() {
    return { count: 0 }
  }
}
</script>

适合只有一行逻辑的简单操作。复杂的逻辑还是应该写到 methods 里。

实际例子:计数器

vue
<template>
  <div>
    <p>当前计数:{{ count }}</p>
    <button @click="count++">+1</button>
    <button @click="count--">-1</button>
    <button @click="count = 0">重置</button>
  </div>
</template>
<script>
export default {
  data() {
    return { count: 0 }
  }
}
</script>

新手常见问题

Q:@click="fn"@click="fn()" 有区别吗? A:有。@click="fn" 会把事件对象传给 fn;@click="fn()" 则什么都不传。如果不需要事件对象,两种写法效果一样。 Q:事件处理函数里怎么访问 data? A:用 this.xxx。Vue 自动把 data 里的数据挂到了 this 上。 下一步: 💡 Tip:Composition API 写法(Vue 3)

vue
<script setup>
import { ref } from 'vue'
const count = ref(0)
function handleClick() { count.value++ }
</script>

模板中的 @click 等写法完全不变。 详见: