Gestion des évènements
Cette page suppose que vous avez déjà lu les principes fondamentaux des composants. Lisez-les d'abord si vous débutez avec les composants.
Émettre et écouter des évènements
Un composant peut émettre des évènements personnalisés directement à partir du template (par exemple, dans un gestionnaire d'évènement v-on
) à l'aide de la méthode native $emit
:
template
<!-- MyComponent -->
<button @click="$emit('someEvent')">click me</button>
Le composant parent peut alors l'écouter en utilisant v-on
:
template
<MyComponent @some-event="callback" />
Le modificateur .once
est également pris en charge sur les écouteurs d'évènements de composants :
template
<MyComponent @some-event.once="callback" />
Comme les composants et les props, les noms d'évènements fournissent une transformation de casse automatique. Notez que nous avons émis un évènement camelCase
, mais que nous pouvons l'écouter à l'aide d'un écouteur kebab-case
dans le parent. Comme pour la casse des props, nous vous recommandons d'utiliser des noms d'écouteurs d'évènement au format kebab-case
dans les templates.
TIP
Contrairement aux évènements DOM natifs, les évènements émis par les composants ne se propagent pas au delà de leur parent direct. Vous ne pouvez écouter que les évènements émis par un composant enfant direct. S'il est nécessaire de communiquer entre des composants frères ou profondément imbriqués, utilisez un bus d'évènements externe ou une solution de gestion d'état global.
Arguments d'évènement
Il est parfois utile d'émettre une valeur spécifique avec un évènement. Par exemple, nous pouvons vouloir que le composant <BlogPost>
soit en charge d'agrandir plus ou moins le texte. Dans ces cas, nous pouvons passer des arguments supplémentaires à $emit
pour fournir cette valeur :
template
<button @click="$emit('increaseBy', 1)">
Increase by 1
</button>
Ensuite, lorsque nous écoutons l'évènement dans le composant parent, nous pouvons utiliser une fonction flèchée comme écouteur, ce qui nous permet d'accéder à l'argument de l'évènement :
template
<MyButton @increase-by="(n) => count += n" />
Ou, si le gestionnaire d'évènements est une méthode :
template
<MyButton @increase-by="increaseCount" />
Ensuite, la valeur sera transmise comme premier paramètre de cette méthode :
js
function increaseCount(n) {
count.value += n
}
TIP
Tous les arguments supplémentaires passés à $emit()
après le nom de l'évènement seront transmis à l'écouteur. Par exemple, avec $emit('foo', 1, 2, 3)
la fonction d'écoute recevra trois arguments.
Déclaration des évènements émis
Les évènements émis peuvent être explicitement déclarés sur le composant via la macro defineEmits()
:
vue
<script setup>
defineEmits(['inFocus', 'submit'])
</script>
La méthode $emit
que nous avons utilisée dans le <template>
n'est pas accessible dans la section <script setup>
d'un composant, mais defineEmits()
renvoie une fonction équivalente que nous pouvons utiliser à la place :
vue
<script setup>
const emit = defineEmits(['inFocus', 'submit'])
function buttonClick() {
emit('submit')
}
</script>
La macro defineEmits()
ne peut pas être utilisée dans une fonction, elle doit être placée directement dans <script setup>
, comme dans l'exemple ci-dessus.
Si vous utilisez une fonction setup
explicite au lieu de <script setup>
, les évènements doivent être déclarés à l'aide de l'option emits
, et la fonction emit
est exposée dans le contexte de setup()
:
js
export default {
emits: ['inFocus', 'submit'],
setup(props, ctx) {
ctx.emit('submit')
}
}
Comme pour les autres propriétés du contexte de setup()
, emit
peut être déstructurée en toute sécurité :
js
export default {
emits: ['inFocus', 'submit'],
setup(props, { emit }) {
emit('submit')
}
}
L'option emits
prend également en charge une syntaxe avec objet, ce qui nous permet d'effectuer une validation à l'exécution du contenu des évènements émis :
vue
<script setup>
const emit = defineEmits({
submit(payload) {
// renvoie `true` ou `false` pour indiquer
// que la validation a réussi/échoué
}
})
</script>
Si vous utilisez TypeScript avec <script setup>
, il est également possible de déclarer des évènements émis à l'aide d'annotations de type :
vue
<script setup lang="ts">
const emit = defineEmits<{
(e: 'change', id: number): void
(e: 'update', value: string): void
}>()
</script>
Plus de détails : Typer les données émises par les composants
Bien que facultatif, il est recommandé de définir tous les évènements émis afin de mieux documenter le fonctionnement d'un composant. Cela permet également à Vue d'exclure les écouteurs connus des attributs implicitement déclarés (fallthrough attributes), évitant ainsi les problèmes liés aux cas à la marge causés par des évènements DOM envoyés manuellement par du code tiers.
TIP
Si un évènement natif (par exemple, click
) est défini dans l'option emits
, l'écouteur n'écoutera alors que les évènements click
émis par le composant et ne réagira plus aux évènements click
natifs.
Validation des évènements
Semblable à la validation de type de prop, un évènement émis peut être validé s'il est défini avec la syntaxe utilisant un objet au lieu d'un tableau.
Pour ajouter une validation, l'évènement se voit attribuer une fonction qui reçoit les arguments passés à l'appel de emit
et renvoie un booléen pour indiquer si l'évènement est valide ou non.
vue
<script setup>
const emit = defineEmits({
// Pas de validation
click: null,
// Validation de l'évènement soumis
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>