Event Handling with v-on

+15 Mana ✨

Vue uses the v-on directive to listen to DOM events and execute JavaScript when they're triggered. This is how you make your applications interactive.

Basic Event Listening

Use v-on:event="handler" to listen to events:

vue
<script setup>
import { ref } from 'vue'

const count = ref(0)

function increment() {
  count.value++
}
</script>

<template>
  <p>Count: {{ count }}</p>
  <button v-on:click="increment">Click me</button>
</template>

Shorthand: @

The @ symbol is shorthand for v-on::

vue
<template>
  <!-- These are equivalent -->
  <button v-on:click="increment">Click</button>
  <button @click="increment">Click</button>
  
  <!-- @ is the standard convention -->
  <button @click="handleClick">Click</button>
  <input @input="handleInput" />
  <form @submit="handleSubmit">...</form>
</template>

Inline Handlers

For simple operations, use inline expressions:

vue
<script setup>
import { ref } from 'vue'

const count = ref(0)
const message = ref('')
</script>

<template>
  <!-- Inline expression -->
  <button @click="count++">Increment</button>
  <button @click="count--">Decrement</button>
  <button @click="count = 0">Reset</button>
  
  <!-- Inline function -->
  <button @click="() => count += 10">Add 10</button>
  
  <!-- Multiple statements -->
  <button @click="count++; message = 'Clicked!'">Click</button>
</template>

Method Handlers

For complex logic, use methods:

vue
<script setup>
import { ref } from 'vue'

const items = ref<string[]>([])

function addItem() {
  const item = `Item ${items.value.length + 1}`
  items.value.push(item)
}

function removeItem(index: number) {
  items.value.splice(index, 1)
}

function clearAll() {
  if (confirm('Remove all items?')) {
    items.value = []
  }
}
</script>

<template>
  <button @click="addItem">Add Item</button>
  <button @click="clearAll">Clear All</button>
  
  <ul>
    <li v-for="(item, index) in items" :key="index">
      {{ item }}
      <button @click="removeItem(index)">Remove</button>
    </li>
  </ul>
</template>

Accessing the Event Object

Vue passes the native DOM event to handlers:

vue
<script setup>
function handleClick(event: MouseEvent) {
  console.log('Button clicked!')
  console.log('Target:', event.target)
  console.log('Position:', event.clientX, event.clientY)
}

function handleInput(event: Event) {
  const target = event.target as HTMLInputElement
  console.log('Input value:', target.value)
}
</script>

<template>
  <button @click="handleClick">Click me</button>
  <input @input="handleInput" />
</template>

Passing Arguments AND the Event

Use $event to pass the event along with other arguments:

vue
<script setup>
function handleAction(action: string, event: MouseEvent) {
  console.log(`Action: ${action}`)
  console.log('Event:', event)
}

function handleItemClick(itemId: number, event: MouseEvent) {
  event.stopPropagation()
  console.log(`Clicked item ${itemId}`)
}
</script>

<template>
  <button @click="handleAction('save', $event)">Save</button>
  
  <div @click="console.log('Parent clicked')">
    <button @click="handleItemClick(42, $event)">Item 42</button>
  </div>
</template>

Common Events

vue
<template>
  <!-- Mouse events -->
  <button @click="onClick">Click</button>
  <button @dblclick="onDoubleClick">Double Click</button>
  <div @mouseenter="onMouseEnter">Hover me</div>
  <div @mouseleave="onMouseLeave">Hover me</div>
  
  <!-- Keyboard events -->
  <input @keydown="onKeyDown" />
  <input @keyup="onKeyUp" />
  <input @keypress="onKeyPress" />
  
  <!-- Form events -->
  <input @input="onInput" />
  <input @change="onChange" />
  <input @focus="onFocus" />
  <input @blur="onBlur" />
  <form @submit="onSubmit">...</form>
  
  <!-- Other events -->
  <div @scroll="onScroll">Scrollable content</div>
  <img @load="onImageLoad" />
  <img @error="onImageError" />
</template>
✓ Completed