Vue 3 v-on: obsługa zdarzeń przez @click, $event i modyfikatory
zweryfikowano 7 września 2026 · 6 min
v-on:click, albo jego skrót @click, wykonuje kod, gdy zajdzie zdarzenie. Podaj nazwę funkcji, żeby dostać natywne zdarzenie, albo wywołaj ją z argumentami i $event, jeśli potrzebujesz obu rzeczy naraz. Modyfikatory .prevent, .stop, .once, .enter i .esc zastępują powtarzalny kod obsługi zdarzeń.
Na razie aplikacja tylko wyświetla. Nie reaguje na nic. Dyrektywa v-on podpina do elementu nasłuchiwanie zdarzenia i wykonuje kod, gdy ono zajdzie. Ten rozdział pokrywa wszystko, co robi się z nią na co dzień: kliknięcie, najechanie kursorem, klawisz, z argumentem albo bez, oraz modyfikatory, dzięki którym nie trzeba ręcznie pisać preventDefault().
Koszyk
Dodaj licznik i przycisk:
<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>Nasłuchiwanie kliknięcia
v-on:, po nim nazwa zdarzenia, a w cudzysłowie kod do wykonania:
<button class="button" v-on:click="cart += 1">Ajouter au panier</button>Kliknij: licznik rośnie. Nazwa zdarzenia jest ta sama co w standardowym DOM-ie, bez przedrostka: click, submit, input, keyup, mouseover.
Wywołanie funkcji
Wyrażenie zapisane w atrybucie wystarczy przy trywialnej operacji. Gdy tylko logika przekracza jedną linię, napisz funkcję:
<script setup>
function addToCart() {
cart.value += 1
}
</script>
<template>
<button class="button" v-on:click="addToCart">Ajouter au panier</button>
</template>Zwróć uwagę na .value w skrypcie: operujemy na referencji, a nie na rozpakowanej wartości. W szablonie zawsze pisze się {{ cart }}, bez .value.
@click="addToCart" przekazuje samą funkcję: Vue wywołuje ją z natywnym zdarzeniem jako pierwszym argumentem. @click="addToCart()" wywołuje ją bez argumentu. Tutaj działa jedno i drugie. Klasyczny błąd pojawia się, gdy funkcja oczekuje wartości: @click="updateImage(variant.image)" jest poprawne, ale pominięcie nawiasów przekazałoby zdarzenie zamiast ścieżki do obrazka.
Skrót z małpą
Tak jak v-bind ma :, tak v-on ma @:
<button class="button" @click="addToCart">Ajouter au panier</button>Ten zapis zobaczysz w całej dokumentacji i w dalszej części tego kursu.
Przekazywanie argumentu
Niech obrazek zmienia się po najechaniu na kolor. Funkcja dostaje ścieżkę do obrazka wskazanego wariantu:
<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>Najedź na „Rouge”: obrazek staje się czerwony. Łączą się tu dwa mechanizmy: pętla z rozdziału 4 i wiązanie atrybutu z rozdziału 2.
Dostęp do natywnego zdarzenia
Bez argumentu funkcja dostaje zdarzenie DOM. Przy argumentach trzeba poprosić o nie wprost przez $event:
<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)
}Otrzymany obiekt to natywne zdarzenie przeglądarki, bez żadnej otoczki: event.target, event.key i event.preventDefault() działają jak w czystym JavaScripcie.
Modyfikatory zdarzeń
Vue dodaje przyrostki, które oszczędzają powtarzalny kod obsługi zdarzeń:
<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 -->Pełna lista wraz z tym, co każdy modyfikator zastępuje:
| Modyfikator | Odpowiednik w JavaScripcie | Typowe zastosowanie |
|---|---|---|
.prevent | event.preventDefault() | formularz, który nie ma przeładowywać strony |
.stop | event.stopPropagation() | przycisk w klikalnej karcie: kliknięcie nie propaguje się do karty |
.self | if (event.target !== event.currentTarget) return | zamknięcie okna modalnego kliknięciem w tło, a nie w jego treść |
.once | addEventListener(…, { once: true }) | przycisk „Zamów”, który nie może wysłać dwa razy |
.capture | addEventListener(…, { capture: true }) | przechwycenie zdarzenia przed elementami potomnymi |
.passive | addEventListener(…, { passive: true }) | przewijanie i dotyk na urządzeniach mobilnych, żeby nie blokować renderowania |
Modyfikatory łączy się w łańcuch i czyta od lewej do prawej: @click.stop.prevent najpierw zatrzymuje propagację, a potem znosi domyślne zachowanie. Ta kolejność ma znaczenie przy .self: @click.self.prevent znosi domyślne zachowanie tylko dla kliknięć w sam element, a @click.prevent.self dla wszystkich kliknięć, razem z elementami potomnymi.
@submit.prevent przyda się w rozdziale 10, żeby strona nie przeładowywała się przy wysłaniu formularza.
Modyfikatory klawiszy i myszy
Przy zdarzeniach klawiatury modyfikator filtruje klawisz. Vue przyjmuje każdą nazwę klawisza udostępnianą przez KeyboardEvent.key, zapisaną w kebab-case, plus kilka aliasów:
<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 -->Dostępne aliasy: .enter, .tab, .delete (Delete i Backspace), .esc, .space, .up, .down, .left, .right. Klawisze systemowe .ctrl, .alt, .shift i .meta łączą się z pozostałymi. A .exact wymaga, żeby żaden inny klawisz systemowy nie był wciśnięty:
<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 -->Przy myszy .left, .right i .middle filtrują przycisk: @click.right.prevent="menuContextuel" zastępuje menu przeglądarki twoim własnym.
Kilka procedur obsługi jednego zdarzenia
Jedno zdarzenie może uruchomić kilka funkcji rozdzielonych przecinkami. Każdą wywołuje się wtedy z nawiasami:
<button @click="addToCart(), trackClick('ajout-panier')">Ajouter au panier</button>Powyżej dwóch wywołań przestaje to być czytelne: napisz funkcję, która wywoła pozostałe.
Podsumowanie
v-on:clickalbo@click: wyrażenie w atrybucie przy trywialnej operacji, poza tym funkcja.- Bez nawiasów funkcja dostaje natywne zdarzenie; przy argumentach
$eventprzekazuje je dodatkowo. .prevent,.stop,.selfi.oncezastępują powtarzalny kod; modyfikatory klawiszy filtrują klawiaturę;.exactblokuje kombinacje.- W skrypcie stan zmienia się przez
.value; w szablonie bez niego.
Funkcje mieszkają w opcji methods i sięgają po stan przez this: methods: { addToCart() { this.cart += 1 } }. Szablon natomiast się nie zmienia.
Zdarzenia z tego rozdziału pochodzą z DOM-u. Żeby komponent potomny dał znać rodzicowi, Vue oferuje zdarzenia własne z emit: to temat rozdziału 9, omówiony szczegółowo w pełnym przewodniku po Vue emit.
Częste błędy
cart += 1 nie robi nic sensownego na referencji: napisz cart.value += 1.@click="updateImage" przekazuje natywne zdarzenie zamiast oczekiwanej wartości. Przy argumencie wywołaj funkcję: @click="updateImage(variant.image)".$event: @click="faire('bleu', $event)".@click.prevent.self blokuje domyślne zachowanie wszystkich kliknięć, a @click.self.prevent tylko tych, których celem jest sam element. Kolejność czyta się od lewej do prawej..passive obiecuje przeglądarce, że preventDefault() nie zostanie wywołane; w połączeniu z .prevent przeglądarka ignoruje jeden z nich i wypisuje ostrzeżenie.