Vue 3: Events mit v-on behandeln (@click, $event, Modifikatoren)
geprüft am 7 September 2026 · 6 Min.
v-on:click, oder das Kürzel @click, führt Code aus, sobald das Event eintritt. Übergib den Namen einer Funktion, um das native Event zu bekommen, oder ruf sie mit ihren Argumenten und $event auf, wenn du beides brauchst. Die Modifikatoren .prevent, .stop, .once, .enter oder .esc ersetzen den wiederkehrenden Code rund um Events.
Bisher zeigt die Anwendung nur an. Sie reagiert auf nichts. Die Direktive v-on hängt einen Event-Listener an ein Element und führt Code aus, sobald das Event eintritt. Dieses Kapitel deckt alles ab, was man damit täglich macht: einen Klick, ein Überfahren mit der Maus, eine Taste, mit oder ohne Argument, dazu die Modifikatoren, die dir das preventDefault() von Hand ersparen.
Der Warenkorb
Ergänze einen Zähler und einen Button:
<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>Auf einen Klick hören
v-on: gefolgt vom Namen des Events, mit dem auszuführenden Code in Anführungszeichen:
<button class="button" v-on:click="cart += 1">Ajouter au panier</button>Klick darauf: Der Zähler steigt. Der Name des Events ist der des Standard-DOM, ohne Präfix: click, submit, input, keyup, mouseover.
Eine Funktion aufrufen
Für eine triviale Operation reicht ein Ausdruck direkt im Template. Sobald die Logik über eine Zeile hinausgeht, schreib eine Funktion:
<script setup>
function addToCart() {
cart.value += 1
}
</script>
<template>
<button class="button" v-on:click="addToCart">Ajouter au panier</button>
</template>Achte auf das .value im Skript: Dort arbeiten wir mit der Ref, nicht mit dem ausgepackten Wert. Im Template schreibt man immer {{ cart }} ohne .value.
@click="addToCart" übergibt die Funktion selbst: Vue ruft sie mit dem nativen Event als erstem Argument auf. @click="addToCart()" ruft sie ohne Argument auf. Hier funktioniert beides. Der klassische Fehler passiert, wenn die Funktion einen Wert erwartet: @click="updateImage(variant.image)" ist richtig, aber ohne die Klammern käme das Event statt des Bildpfads an.
Das Kürzel mit dem At-Zeichen
So wie v-bind das : hat, hat v-on das @:
<button class="button" @click="addToCart">Ajouter au panier</button>Das ist die Schreibweise, die dir in der gesamten Dokumentation und im weiteren Verlauf dieses Tutorials begegnet.
Ein Argument übergeben
Lass uns das Bild wechseln, sobald der Mauszeiger über einer Farbe steht. Die Funktion bekommt den Bildpfad der überfahrenen Variante:
<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>Fahre über „Rouge“: Das Bild wird rot. Hier greifen zwei Mechanismen ineinander, die Schleife aus Kapitel 4 und die Attributbindung aus Kapitel 2.
Das native Event abholen
Ohne Argument bekommt die Funktion das DOM-Event. Mit Argumenten forderst du es ausdrücklich über $event an:
<button @click="voir">Sans argument</button>
<button @click="voirAvec('bleu', $event)">Avec arguments</button>function voir(event) {
console.log(event.target)
}
function voirAvec(couleur, event) {
console.log(couleur, event.target)
}Das übergebene Objekt ist das native Event des Browsers, ohne Hülle: event.target, event.key, event.preventDefault() funktionieren wie in reinem JavaScript.
Die Event-Modifikatoren
Vue kennt Suffixe, die dir den wiederkehrenden Code rund um Events ersparen:
<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 -->Die vollständige Liste, mit dem, was jeder Modifikator ersetzt:
| Modifikator | JavaScript-Entsprechung | Typischer Einsatz |
|---|---|---|
.prevent | event.preventDefault() | ein Formular, das die Seite nicht neu laden soll |
.stop | event.stopPropagation() | ein Button in einer klickbaren Karte: Der Klick steigt nicht bis zur Karte auf |
.self | if (event.target !== event.currentTarget) return | ein Modal beim Klick auf den Hintergrund schließen, nicht auf den Inhalt |
.once | addEventListener(…, { once: true }) | ein Button „Bestellen“, der nicht zweimal senden darf |
.capture | addEventListener(…, { capture: true }) | das Event vor den Kindelementen abfangen |
.passive | addEventListener(…, { passive: true }) | Scrollen und Touch auf dem Handy, um das Rendering nicht zu blockieren |
Die Modifikatoren lassen sich verketten und werden von links nach rechts gelesen: @click.stop.prevent stoppt die Weitergabe und hebt dann das Standardverhalten auf. Mit .self bekommt diese Reihenfolge Bedeutung: @click.self.prevent hebt das Standardverhalten nur für Klicks auf das Element selbst auf, @click.prevent.self für alle Klicks, Kindelemente eingeschlossen.
@submit.prevent kommt in Kapitel 10 zum Einsatz, um beim Absenden des Formulars das Neuladen der Seite zu verhindern.
Tasten- und Maus-Modifikatoren
Bei Tastatur-Events filtert ein Modifikator die Taste. Vue akzeptiert jeden Tastennamen, den KeyboardEvent.key liefert, in Kebab-Case geschrieben, dazu einige Aliase:
<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 -->Die verfügbaren Aliase: .enter, .tab, .delete (Entf und Rücktaste), .esc, .space, .up, .down, .left, .right. Die Systemtasten .ctrl, .alt, .shift und .meta lassen sich mit den anderen kombinieren. Und .exact verlangt, dass keine weitere Systemtaste gedrückt ist:
<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 -->Für die Maus filtern .left, .right und .middle die Taste: @click.right.prevent="menuContextuel" ersetzt das Menü des Browsers durch dein eigenes.
Mehrere Handler für dasselbe Event
Ein Event kann mehrere Funktionen auslösen, getrennt durch Kommas. Jede Funktion wird dann mit Klammern aufgerufen:
<button @click="addToCart(), trackClick('ajout-panier')">Ajouter au panier</button>Ab drei Aufrufen ist das nicht mehr lesbar: Schreib dann eine Funktion, die die anderen aufruft.
Zusammenfassung
v-on:clickoder@click: ein Ausdruck direkt im Template für eine triviale Operation, sonst eine Funktion.- Ohne Klammern bekommt die Funktion das native Event; mit Argumenten übergibt
$eventes zusätzlich. .prevent,.stop,.self,.onceersetzen den wiederkehrenden Code; die Tasten-Modifikatoren filtern die Tastatur;.exactlegt die Kombination fest.- Im Skript änderst du den State über
.value, im Template ohne.
Die Funktionen leben in der Option methods und greifen über this auf den State zu: methods: { addToCart() { this.cart += 1 } }. Das Template selbst ändert sich nicht.
Die Events dieses Kapitels kommen aus dem DOM. Damit eine Kindkomponente ihre Elternkomponente benachrichtigt, kennt Vue eigene Events mit emit: darum geht es in Kapitel 9, ausführlich im vollständigen Guide zu Vue emit.
Häufige Fehler
cart += 1 auf einer Ref nichts Sinnvolles: Schreib cart.value += 1.@click="updateImage" übergibt das native Event statt des erwarteten Werts. Mit einem Argument rufst du die Funktion auf: @click="updateImage(variant.image)".$event anfordern: @click="faire('bleu', $event)".@click.prevent.self unterdrückt das Standardverhalten bei allen Klicks, @click.self.prevent nur bei denen, deren Ziel das Element selbst ist. Die Reihenfolge wird von links nach rechts gelesen..passive verspricht dem Browser, preventDefault() nicht aufzurufen; zusammen mit .prevent ignoriert der Browser eines von beiden und gibt eine Warnung aus.