Rozdział 5 z 11

Vue 3 v-on: obsługa zdarzeń przez @click, $event i modyfikatory

zweryfikowano 7 września 2026 · 6 min

Szybka odpowiedź

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 koniec tego rozdziału, będziesz umieć reagować na kliknięcia, najechanie kursorem i klawisze, przekazywać argumenty do swoich procedur obsługi, sięgać po natywne zdarzenie i używać modyfikatorów, żeby pisać mniej kodu.

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:

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>

Nasłuchiwanie kliknięcia

v-on:, po nim nazwa zdarzenia, a w cudzysłowie kod do wykonania:

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

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

Z nawiasami czy bez?

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

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

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>

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:

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

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

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

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:

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

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:

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

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:

html
<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:click albo @click: wyrażenie w atrybucie przy trywialnej operacji, poza tym funkcja.
  • Bez nawiasów funkcja dostaje natywne zdarzenie; przy argumentach $event przekazuje je dodatkowo.
  • .prevent, .stop, .self i .once zastępują powtarzalny kod; modyfikatory klawiszy filtrują klawiaturę; .exact blokuje kombinacje.
  • W skrypcie stan zmienia się przez .value; w szablonie bez niego.
W Options API

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.

ĆwiczenieDodaj przycisk „Usuń z koszyka”, który zmniejsza licznik i nigdy nie schodzi poniżej zera. Potem zamień najechanie kursorem na kliknięcie w kolory i porównaj wrażenia.

Częste błędy

Pominięte .value w funkcji W skrypcie cart += 1 nie robi nic sensownego na referencji: napisz cart.value += 1.
Brak nawiasów przy argumencie @click="updateImage" przekazuje natywne zdarzenie zamiast oczekiwanej wartości. Przy argumencie wywołaj funkcję: @click="updateImage(variant.image)".
Dostęp do zdarzenia, gdy przekazujesz już argument Trzeba o nie poprosić wprost przez $event: @click="faire('bleu', $event)".
Zła kolejność modyfikatorów w łańcuchu @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.
Łączenie .passive z .prevent .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.
Newsletter

Nowe testy, poradniki i projekty, e-mailem.

Powtarzalne testy, wersjonowany kod, datowane wyniki. Nigdy spamu.