Wydarzenia komponentu
Ta strona zakłada, że przeczytałeś już Podstawy Komponentów. Przeczytaj to najpierw, jeśli dopiero zaczynasz pracę z komponentami.
Emitowanie i nasłuchiwanie wydarzeń
Komponent może emitować własne wydarzenia bezpośrednio w wyrażeniach szablonu (np. w obsłudze v-on
) używając wbudowanej metody $emit
:
template
<!-- MyComponent -->
<button @click="$emit('someEvent')">Wciśnij mnie</button>
Rodzic może następnie nasłuchiwać jej używając v-on
:
template
<MyComponent @some-event="callback" />
Modyfikator .once
jest również wspierany przy nasłuchiwaniu wydarzeń komponentu:
template
<MyComponent @some-event.once="callback" />
Podobnie jak komponenty i propsy, nazwy wydarzeń zapewniają automatyczną transformację wielkości liter. Zauważ, że wyemitowaliśmy wydarzenie w formacie camelCase, ale możemy go nasłuchiwać używając formatu kebab-case w komponencie rodzica. Tak jak w przypadku formatowania propsów, zalecamy używanie formatu kebab-case dla nasłuchiwania wydarzeń w szablonach.
TIP
W przeciwieństwie do natywnych wydarzeń DOM, emitowane wydarzenia komponentów nie bąbelkują. Możesz nasłuchiwać tylko wydarzeń emitowanych przez bezpośredni komponent potomny. Jeśli istnieje potrzeba komunikacji między komponentami rodzeństwa lub głęboko zagnieżdżonymi komponentami, użyj zewnętrznej magistrali wydarzeń lub rozwiązania do zarządzania stanem globalnym.
Argumenty Wydarzenia
Czasami przydatne jest emitowanie określonej wartości wraz z wydarzeniem. Na przykład, możemy chcieć, aby komponent <BlogPost>
był odpowiedzialny za to, o ile powiększyć tekst. W takich przypadkach możemy przekazać dodatkowe argumenty do $emit
, aby dostarczyć tę wartość:
template
<button @click="$emit('increaseBy', 1)">
Zwiększ o 1
</button>
Następnie, gdy nasłuchujemy wydarzenia w komponencie rodzica, możemy użyć funkcji strzałkowej w linii jako nasłuchiwacza, co pozwala nam uzyskać dostęp do argumentu wydarzenia:
template
<MyButton @increase-by="(n) => count += n" />
Lub, jeśli obsługa wydarzenia jest metodą:
template
<MyButton @increase-by="increaseCount" />
Wtedy wartość zostanie przekazana jako pierwszy parametr tej metody:
js
function increaseCount(n) {
count.value += n
}
TIP
Wszystkie dodatkowe argumenty przekazane do $emit()
po nazwie wydarzenia zostaną przekazane do nasłuchiwacza. Na przykład, przy $emit('foo', 1, 2, 3)
funkcja nasłuchująca otrzyma trzy argumenty.
Deklarowanie emitowanych zdarzeń
Komponent może jawnie zadeklarować zdarzenia, które będzie emitował, używając makra defineEmits()
:
vue
<script setup>
defineEmits(['inFocus', 'submit'])
</script>
Metoda $emit
, której używaliśmy w <template>
nie jest dostępna w sekcji <script setup>
komponentu, ale defineEmits()
zwraca równoważną funkcję, której możemy użyć zamiast niej:
vue
<script setup>
const emit = defineEmits(['inFocus', 'submit'])
function buttonClick() {
emit('submit')
}
</script>
Makro defineEmits()
nie może być używane wewnątrz funkcji, musi być umieszczone bezpośrednio w <script setup>
, jak w powyższym przykładzie.
Jeśli używasz bezpośrednio funkcji setup
zamiast <script setup>
, zdarzenia powinny być deklarowane przy użyciu opcji emits
, a funkcja emit
jest udostępniana w kontekście setup()
:
js
export default {
emits: ['inFocus', 'submit'],
setup(props, ctx) {
ctx.emit('submit')
}
}
Podobnie jak w przypadku innych właściwości kontekstu setup()
, emit
może być bezpiecznie destrukturyzowany:
js
export default {
emits: ['inFocus', 'submit'],
setup(props, { emit }) {
emit('submit')
}
}
Opcja emits
oraz makro defineEmits()
obsługują również składnię obiektową. Jeśli używasz TypeScript, możesz określić typy argumentów, co pozwala nam na walidację w czasie wykonywania zawartości emitowanych zdarzeń:
vue
<script setup lang="ts">
const emit = defineEmits({
submit(payload: { email: string, password: string }) {
// zwróć `true` lub `false` aby wskazać
// powodzenie / niepowodzenie walidacji
}
})
</script>
Jeśli używasz TypeScript z <script setup>
, możliwe jest również deklarowanie emitowanych zdarzeń przy użyciu czystych adnotacji typów:
vue
<script setup lang="ts">
const emit = defineEmits<{
(e: 'change', id: number): void
(e: 'update', value: string): void
}>()
</script>
Więcej szczegółów: Typowanie emiterów w komponencie
Mimo że jest to opcjonalne, zaleca się zdefiniowanie wszystkich emitowanych zdarzeń w celu lepszego udokumentowania sposobu działania komponentu. Pozwala to również Vue na wykluczenie znanych nasłuchujących z dziedziczonych atrybutów, unikając przypadków brzegowych spowodowanych zdarzeniami DOM ręcznie wywołanymi przez kod zewnętrzny.
TIP
Jeśli natywne zdarzenie (np. click
) jest zdefiniowane w opcji emits
, nasłuchujący będzie teraz reagował tylko na zdarzenia click
emitowane przez komponent i nie będzie już reagował na natywne zdarzenia click
.
Walidacja zdarzeń
Podobnie jak w przypadku walidacji właściwości (props), emitowane zdarzenie może być walidowane, jeśli jest zdefiniowane przy użyciu składni obiektowej zamiast składni tablicowej.
Aby dodać walidację, zdarzeniu przypisywana jest funkcja, która otrzymuje argumenty przekazane do wywołania emit
i zwraca wartość logiczną wskazującą, czy zdarzenie jest prawidłowe, czy nie.
vue
<script setup>
const emit = defineEmits({
// Brak walidacji
click: null,
// Walidacja zdarzenia submit
submit: ({ email, password }) => {
if (email && password) {
return true
} else {
console.warn('Nieprawidłowa zawartość zdarzenia submit!')
return false
}
}
})
function submitForm(email, password) {
emit('submit', { email, password })
}
</script>