In Vue, you can listen for events using the v-on
directive or the shorthand @
. You can listen for any DOM event; for example, you can use @click
for click events. This link contains a list of all native DOM events.
Define Events
Of course, you can also listen for custom events that you have defined in your child component:
<script setup lang="ts">
import { ref } from 'vue'
const counter = ref(0)
const emit = defineEmits<{
(event: 'update:counter', counter: number): void
}>()
const increment = () => {
counter.value++
emit('update:counter', counter.value)
}
</script>
<template>
<div>
<span>Counter: {{ counter }}</span>
<button @click="increment">Increment</button>
</div>
</template>
Handle Events
Let's look at the different ways to handle such events in Vue.
Without arguments
If your event does not have any arguments, I prefer this syntax:
<script setup lang="ts">
import Child from './Child.vue'
const onUpdateCounter = (counter: number) => {
console.log('onUpdateCounter', counter)
}
</script>
<template>
<Child @update:counter="onUpdateCounter" />
</template>
Access custom event object
If you want to access the custom event object in your event handler, you can use the following syntax:
<script lang="ts" setup>
import type { Counter } from '...'
const counters: Counter[] = [
// ...
]
function onUpdateCounter(counter: Counter) {
// ...
}
</script>
<template>
<ul>
<li v-for="counter of counter" :key="counter.id">
<Child @update:counter="() => onUpdateCounter(counter)" />
</li>
</ul>
</template>
Access custom & native event object
Sometimes, you need access to your custom event object and the native event object. In this case, you can use the following syntax:
<script lang="ts" setup>
import type { Counter } from '...'
const counters: Counter[] = [
// ...
]
function onUpdateCounter(event: Event, counter: Counter) {
// ...
}
</script>
<template>
<ul>
<li v-for="counter of counter" :key="counter.id">
<Child @update:counter="($event) => onUpdateCounter($event, counter)" />
</li>
</ul>
</template>
Further Reading
Lachlan Miller wrote an excellent in-depth article about event handling, which you can find here. It is definitely worth a read!
If you liked this Vue tip, follow me on BlueSky to get notified about new tips, blog posts, and more. Alternatively (or additionally), you can subscribe to my weekly Vue & Nuxt newsletter :
Nuxt Tip: Detecting Server vs. Client-Side Code Execution
Vue Tip: Use Your Composables Synchronously