Vue Events

Vue listens for DOM events using the v-on directive, most often written with its concise @ shorthand, so templates can respond to clicks, typing, and more.

Listening to Events with v-on

v-on binds a listener to a DOM event on the element it's attached to. The argument after the colon names the event, and the value is either an inline expression or the name of a method defined on the component. When the event fires, Vue runs whatever you gave it.

A basic click counter

<div id="app">
  <p>Count: {{ count }}</p>
  <button v-on:click="count++">Add one</button>
</div>

<script>
const app = Vue.createApp({
  data() {
    return { count: 0 }
  }
})
app.mount('#app')
</script>

The @ Shorthand

Because v-on: shows up constantly in real templates, Vue offers @ as a drop-in replacement. @click is identical in behavior to v-on:click, it's simply shorter to type and read. Almost every Vue codebase you'll encounter uses the shorthand exclusively.

Same counter, shorthand syntax

<div id="app">
  <p>Count: {{ count }}</p>
  <button @click="count++">Add one</button>
  <button @click="count = 0">Reset</button>
</div>

<script>
const app = Vue.createApp({
  data() {
    return { count: 0 }
  }
})
app.mount('#app')
</script>
  • @click - mouse clicks and taps
  • @input - fires on every keystroke in a text field
  • @submit - fires when a form is submitted
  • @keyup / @keydown - fires on keyboard events
  • @mouseover / @mouseleave - fires when the pointer enters or exits an element
  • @change - fires when a select, checkbox, or radio value is committed
Note: You'll see both v-on:click and @click in older tutorials and blog posts. They do exactly the same thing, so don't worry if you spot the longer form somewhere; just default to @ in your own code.

Passing the Event Object and Custom Arguments

When you call a method from an event binding, Vue automatically passes the native event object as the last argument if you don't specify any arguments yourself. If you do want to pass your own arguments alongside the event, use the special $event variable to refer to it explicitly inside the expression.

Passing a custom argument plus $event

<div id="app">
  <button
    v-for="item in items"
    :key="item"
    @click="logClick(item, $event)"
  >
    {{ item }}
  </button>
</div>

<script>
const app = Vue.createApp({
  data() {
    return { items: ['One', 'Two', 'Three'] }
  },
  methods: {
    logClick(item, event) {
      console.log('Clicked:', item, 'at', event.clientX, event.clientY)
    }
  }
})
app.mount('#app')
</script>
FormExampleWhen to use it
Method name only@click="save"handler needs just the native event, no extra data
Method call, no args@click="save()"handler takes no arguments at all
Method call with args@click="remove(item.id)"handler needs data from the loop or scope
Inline expression@click="count++"a tiny one-line state change, no method needed
Note: Keep inline expressions to trivial state updates. Anything involving a conditional, a loop, or more than one statement belongs in a method, both for readability and because Vue's template compiler is not meant to run arbitrary JavaScript logic.

Exercise: Vue Events

What is the shorthand for writing v-on:click="handler"?