Kapitel 5 von 11

Vue 3: Events mit v-on behandeln (@click, $event, Modifikatoren)

geprüft am 7 September 2026 · 6 Min.

Schnelle Antwort

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.

Am Ende dieses Kapitels, reagierst du auf Klicks, auf den Mauszeiger und auf Tastendrücke, übergibst deinen Handlern Argumente, holst dir das native Event und schreibst mit den Modifikatoren weniger Code.

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:

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>

Auf einen Klick hören

v-on: gefolgt vom Namen des Events, mit dem auszuführenden Code in Anführungszeichen:

src/App.vue
<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:

src/App.vue
<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.

Mit oder ohne Klammern?

@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 @:

src/App.vue
<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:

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>

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:

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)
}

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:

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 -->

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:

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 -->

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:

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 -->

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:

html
<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:click oder @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 $event es zusätzlich.
  • .prevent, .stop, .self, .once ersetzen den wiederkehrenden Code; die Tasten-Modifikatoren filtern die Tastatur; .exact legt die Kombination fest.
  • Im Skript änderst du den State über .value, im Template ohne.
In der Options API

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.

ÜbungErgänze einen Button „Retirer du panier“, der den Zähler verringert, ohne je unter null zu fallen. Ersetze danach das Überfahren der Farben durch einen Klick und vergleiche, wie sich beides anfühlt.

Häufige Fehler

.value in einer Funktion vergessen Im Skript bewirkt cart += 1 auf einer Ref nichts Sinnvolles: Schreib cart.value += 1.
Fehlende Klammern bei einem Argument @click="updateImage" übergibt das native Event statt des erwarteten Werts. Mit einem Argument rufst du die Funktion auf: @click="updateImage(variant.image)".
Das Event holen, obwohl schon ein Argument übergeben wird Du musst es ausdrücklich mit $event anfordern: @click="faire('bleu', $event)".
Modifikatoren in der falschen Reihenfolge verketten @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 zusammen mit .prevent verwenden .passive verspricht dem Browser, preventDefault() nicht aufzurufen; zusammen mit .prevent ignoriert der Browser eines von beiden und gibt eine Warnung aus.
Newsletter

Neue Tests, Tutorials und Projekte, per E-Mail.

Reproduzierbare Tests, versionierter Code, datierte Ergebnisse. Niemals Spam.