Hoofdstuk 5 van 11

Vue 3 v-on: events afhandelen met @click, $event en modifiers

geverifieerd op 7 september 2026 · 6 min

Kort antwoord

v-on:click, of de shorthand @click, voert code uit zodra het event optreedt. Geef de naam van een functie door om het native event te ontvangen, of roep haar aan met haar argumenten plus $event als je beide nodig hebt. De modifiers .prevent, .stop, .once, .enter en .esc vervangen de terugkerende code voor eventafhandeling.

Aan het einde van dit hoofdstuk, kun je reageren op kliks, op hover en op toetsaanslagen, argumenten meegeven aan je handlers, het native event ophalen en met de modifiers minder code schrijven.

Voorlopig toont de applicatie alleen. Ze reageert nergens op. De directive v-on hangt een event listener aan een element en voert code uit zodra het event optreedt. Dit hoofdstuk behandelt alles wat je er dagelijks mee doet: een klik, een hover, een toets, met of zonder argument, en de modifiers die je besparen om preventDefault() met de hand te schrijven.

Het winkelmandje

Voeg een teller en een knop toe:

src/App.vue
<script setup>
import { ref } from 'vue'

const product = ref('T-Shirt')
const image = ref('/images/t-shirt-bleu.svg')
const inventory = ref(100)
const cart = ref(0)
const details = ref(['60 % coton', '30 % laine', '10 % polyester'])
const variants = ref([
  { id: 2234, color: 'Bleu', image: '/images/t-shirt-bleu.svg' },
  { id: 2235, color: 'Rouge', image: '/images/t-shirt-rouge.svg' }
])
</script>

<template>
  <div class="product-display">
    <div class="cart">Panier ({{ cart }})</div>
    …
    <button class="button">Ajouter au panier</button>
  </div>
</template>

Naar een klik luisteren

v-on: gevolgd door de naam van het event, met de uit te voeren code tussen aanhalingstekens:

src/App.vue
<button class="button" v-on:click="cart += 1">Ajouter au panier</button>

Klik: de teller loopt op. De naam van het event is die van het standaard-DOM, zonder prefix: click, submit, input, keyup, mouseover.

Een functie aanroepen

Voor een triviale bewerking volstaat een inline-expressie. Zodra de logica langer is dan één regel, schrijf je een functie:

src/App.vue
<script setup>
function addToCart() {
  cart.value += 1
}
</script>

<template>
  <button class="button" v-on:click="addToCart">Ajouter au panier</button>
</template>

Let op de .value in het script: we werken met de ref, niet met de uitgepakte waarde. In de template schrijf je altijd {{ cart }}, zonder .value.

Met of zonder haakjes?

@click="addToCart" geeft de functie zelf door: Vue roept haar aan met het native event als eerste argument. @click="addToCart()" roept haar aan zonder argument. Hier werken beide. De klassieke fout duikt op zodra de functie een waarde verwacht: @click="updateImage(variant.image)" is correct, maar zonder de haakjes zou je het event doorgeven in plaats van het pad naar de afbeelding.

Het apenstaartje als shorthand

Net zoals v-bind zijn : heeft, heeft v-on zijn @:

src/App.vue
<button class="button" @click="addToCart">Ajouter au panier</button>

Dit is de schrijfwijze die je in de hele documentatie en in de rest van deze tutorial tegenkomt.

Een argument meegeven

Laat de afbeelding veranderen zodra je over een kleur zweeft. De functie krijgt het pad van de afbeelding van de variant onder de muis:

src/App.vue
<script setup>
function updateImage(variantImage) {
  image.value = variantImage
}
</script>

<template>
  <div
    v-for="variant in variants"
    :key="variant.id"
    @mouseover="updateImage(variant.image)"
  >
    {{ variant.color }}
  </div>
</template>

Zweef over “Rouge”: de afbeelding wordt rood. Twee mechanismen komen hier samen, de lus uit hoofdstuk 4 en de attribuutbinding uit hoofdstuk 2.

Het native event ophalen

Zonder argument krijgt de functie het DOM-event. Geef je zelf argumenten mee, vraag het dan expliciet op met $event:

html
<button @click="voir">Sans argument</button>
<button @click="voirAvec('bleu', $event)">Avec arguments</button>
javascript
function voir(event) {
  console.log(event.target)
}

function voirAvec(couleur, event) {
  console.log(couleur, event.target)
}

Het object dat je krijgt, is het native event van de browser, zonder omhulsel: event.target, event.key en event.preventDefault() werken net als in pure JavaScript.

De event-modifiers

Vue biedt achtervoegsels die je het terugkerende afhandelingswerk besparen:

html
<form @submit.prevent="envoyer">…</form>   <!-- event.preventDefault() -->
<div @click.stop="…">…</div>               <!-- event.stopPropagation() -->
<div @click.self="…">…</div>               <!-- seulement si la cible est cet élément -->
<button @click.once="…">…</button>         <!-- une seule fois -->
<input @keyup.enter="valider">             <!-- seulement la touche Entrée -->

De volledige lijst, met wat elke modifier vervangt:

Modifier JavaScript-equivalent Typisch gebruik
.prevent event.preventDefault() een formulier dat de pagina niet mag herladen
.stop event.stopPropagation() een knop in een klikbare kaart: de klik gaat niet door naar de kaart
.self if (event.target !== event.currentTarget) return een modaal venster sluiten bij een klik op de achtergrond, niet op de inhoud
.once addEventListener(…, { once: true }) een knop “Bestellen” die niet twee keer mag versturen
.capture addEventListener(…, { capture: true }) het event onderscheppen vóór de kinderen
.passive addEventListener(…, { passive: true }) scrollen en aanraken op mobiel, om het renderen niet te blokkeren

Modifiers ketenen zich aan elkaar en worden van links naar rechts gelezen: @click.stop.prevent stopt eerst de propagatie en annuleert dan het standaardgedrag. Die volgorde telt bij .self: @click.self.prevent annuleert het standaardgedrag alleen voor kliks op het element zelf, @click.prevent.self voor alle kliks, kinderen inbegrepen.

@submit.prevent komt in hoofdstuk 10 van pas om te voorkomen dat de pagina herlaadt wanneer het formulier wordt verstuurd.

Toets- en muismodifiers

Bij toetsenbordevents filtert een modifier op de toets. Vue accepteert elke toetsnaam die KeyboardEvent.key blootgeeft, geschreven in kebab-case, plus een paar aliassen:

html
<input @keyup.enter="valider">
<input @keyup.esc="annuler">
<input @keydown.tab="suivant">
<input @keyup.page-down="pageSuivante">   <!-- KeyboardEvent.key === 'PageDown' -->
<input @keydown.ctrl.enter="envoyer">     <!-- Ctrl + Entrée -->

De beschikbare aliassen: .enter, .tab, .delete (Delete en Backspace), .esc, .space, .up, .down, .left, .right. De systeemtoetsen .ctrl, .alt, .shift en .meta combineren met de andere. En .exact eist dat geen enkele andere systeemtoets ingedrukt is:

html
<button @click.ctrl="ouvrir">…</button>        <!-- Ctrl + clic, même si Shift est aussi enfoncé -->
<button @click.ctrl.exact="ouvrir">…</button>  <!-- Ctrl + clic, et rien d'autre -->
<button @click.exact="ouvrir">…</button>       <!-- clic sans aucune touche système -->

Voor de muis filteren .left, .right en .middle op de knop: @click.right.prevent="menuContextuel" vervangt het menu van de browser door het jouwe.

Meerdere handlers op hetzelfde event

Eén event kan meerdere functies starten, gescheiden door komma’s. Elke functie wordt dan mét haakjes aangeroepen:

html
<button @click="addToCart(), trackClick('ajout-panier')">Ajouter au panier</button>

Voorbij twee aanroepen is dit niet meer leesbaar: schrijf dan één functie die de andere aanroept.

Samenvatting

  • v-on:click of @click: een inline-expressie voor een triviale bewerking, anders een functie.
  • Zonder haakjes krijgt de functie het native event; met argumenten geeft $event het er extra bij.
  • .prevent, .stop, .self en .once vervangen terugkerende code; de toetsmodifiers filteren het toetsenbord; .exact zet de combinaties vast.
  • In het script pas je de state aan via .value; in de template niet.
In de Options API

De functies staan in de optie methods en bereiken de state via this: methods: { addToCart() { this.cart += 1 } }. De template zelf verandert niet.

De events uit dit hoofdstuk komen van het DOM. Om een kindcomponent zijn ouder te laten waarschuwen, biedt Vue eigen events met emit: dat is het onderwerp van hoofdstuk 9, uitgewerkt in de complete gids over Vue emit.

OefeningVoeg een knop “Uit het mandje halen” toe die de teller verlaagt zonder ooit onder nul te gaan. Vervang daarna de hover door een klik op de kleuren en vergelijk hoe dat aanvoelt.

Veelgemaakte fouten

.value vergeten in een functie In het script doet cart += 1 niets zinnigs op een ref: schrijf cart.value += 1.
Haakjes vergeten bij een argument @click="updateImage" geeft het native event door in plaats van de verwachte waarde. Met een argument roep je de functie aan: @click="updateImage(variant.image)".
Het event willen ophalen terwijl je al een argument meegeeft Dan moet je er expliciet om vragen met $event: @click="faire('bleu', $event)".
Modifiers in de verkeerde volgorde ketenen @click.prevent.self blokkeert het standaardgedrag van alle kliks, @click.self.prevent alleen van de kliks waarvan het element zelf het doelwit is. De volgorde lees je van links naar rechts.
.passive met .prevent gebruiken .passive belooft de browser dat je preventDefault() niet aanroept; samen met .prevent negeert de browser er één van beide en toont hij een waarschuwing.
Nieuwsbrief

Nieuwe tests, tutorials en projecten, per e-mail.

Reproduceerbare tests, geversioneerde code, gedateerde resultaten. Nooit spam.