Eventi dei componenti
Si assume che tu abbia già letto le Basi dei componenti. Leggi prima quello se sei nuovo al concetto di componente.
Emettere ed ascoltare eventi
Un componente può emettere eventi personalizzati direttamente nelle espressioni del template (ad esempio, in un listener v-on
) utilizzando il metodo integrato $emit
:
template
<!-- MyComponent -->
<button @click="$emit('someEvent')">cliccami</button>
Il genitore può poi ascoltarlo utilizzando v-on
:
template
<MyComponent @nome-evento="callback" />
Anche il modificatore .once
è supportato sui listener degli eventi del componente:
template
<MyComponent @nome-evento.once="callback" />
Come i componenti e le props, i nomi degli eventi forniscono una trasformazione automatica delle maiuscole e minuscole. Nota che abbiamo emesso un evento in stile camelCase, ma possiamo ascoltarlo usando un listener in stile kebab-case nel genitore. Come per la gestione delle maiuscole delle props, consigliamo di utilizzare listener degli eventi in stile kebab-case nei template.
TIP
A differenza degli eventi nativi del DOM, gli eventi emessi dai componenti non si propagano. Puoi ascoltare solo gli eventi emessi da un componente figlio diretto. Se c'è la necessità di comunicare tra componenti fratelli o profondamente nidificati, utilizza un event bus esterno o una soluzione di gestione dello stato globale.
Argomenti degli Eventi
A volte è utile emettere un valore specifico con un evento. Ad esempio, potremmo voler far sì che il componente <BlogPost>
sia responsabile di quanto ingrandire il testo. In questi casi, possiamo passare argomenti aggiuntivi a $emit
per fornire questo valore:
template
<button @click="$emit('increaseBy', 1)">
Aumenta di 1
</button>
Quindi, quando ascoltiamo l'evento nel genitore, possiamo utilizzare una arrow function come listener, che ci consente di accedere all'argomento dell'evento:
template
<MyButton @increase-by="(n) => count += n" />
Oppure, se l'handler dell'evento è un metodo:
template
<MyButton @increase-by="increaseCount" />
Allora il valore sarà passato come primo parametro di quel metodo:
js
function increaseCount(n) {
count.value += n
}
TIP
Tutti gli argomenti aggiuntivi passati a $emit()
dopo il nome dell'evento verranno inoltrati al listener. Ad esempio, con $emit('foo', 1, 2, 3)
la funzione del listener riceverà tre argomenti.
Dichiarare eventi emessi
Un componente può dichiarare esplicitamente gli eventi che emetterà utilizzando la macrodefineEmits()
:
vue
<script setup>
defineEmits(['inFocus', 'submit'])
</script>
Il metodo $emit
che abbiamo utilizzato nel <template>
non è accessibile nella sezione <script setup>
di un componente, ma defineEmits()
restituisce una funzione equivalente che possiamo utilizzare al suo posto:
vue
<script setup>
const emit = defineEmits(['inFocus', 'submit'])
function buttonClick() {
emit('submit')
}
</script>
La macro defineEmits()
non può essere utilizzata all'interno di una funzione, ma deve essere inserita direttamente all'interno di <script setup>
, come nell'esempio sopra.
Se stai utilizzando la funzione setup
esplicita invece di <script setup>
, gli eventi dovrebbero essere dichiarati utilizzando l'opzione emits
, e la funzione emit
è esposta nel contesto setup()
:
js
export default {
emits: ['inFocus', 'submit'],
setup(props, ctx) {
ctx.emit('submit')
}
}
Come con altre proprietà del contesto setup()
, emit
può essere tranquillamente destrutturato:
js
export default {
emits: ['inFocus', 'submit'],
setup(props, { emit }) {
emit('submit')
}
}
L'opzione emits
supporta anche una sintassi ad oggetto, che ci consente di eseguire la convalida a runtime del payload degli eventi emessi:
vue
<script setup>
const emit = defineEmits({
submit(payload) {
// restituisci `true` o `false` per indicare
// il superamento / fallimento della convalida
}
})
</script>
Se stai utilizzando TypeScript con <script setup>
, è anche possibile dichiarare eventi emessi utilizzando solo annotazioni di tipo:
vue
<script setup lang="ts">
const emit = defineEmits<{
(e: 'change', id: number): void
(e: 'update', value: string): void
}>()
</script>
Più dettagli: Tipizzare gli emits dei componenti
Anche se opzionali, è consigliabile definire tutti gli eventi emessi per documentare meglio come dovrebbe funzionare un componente. Inoltre, consente a Vue di escludere gli ascoltatori noti dagli attributi fallthrough, evitando casi limite causati dagli eventi del DOM inviati manualmente da codice di terze parti.
TIP
Se un evento nativo (ad esempio, click
) è definito nell'opzione emits
l'ascoltatore ascolterà solo gli eventi click
emessi dal componente e non risponderà più agli eventi click
nativi.
Convalida degli eventi
Analogamente alla convalida del tipo di prop, un evento emesso può essere convalidato se è definito con la sintassi dell'oggetto anziché con la sintassi dell'array.
Per aggiungere la convalida, all'evento viene assegnata una funzione che riceve gli argomenti passati alla chiamata di emit
e restituisce un valore booleano per indicare se l'evento è valido o meno.
vue
<script setup>
const emit = defineEmits({
// Nessuna validazione
click: null,
// Validazione sull'evento submit
submit: ({ email, password }) => {
if (email && password) {
return true
} else {
console.warn('Invalid submit event payload!')
return false
}
}
})
function submitForm(email, password) {
emit('submit', { email, password })
}
</script>