Props, événements et v-model sur un composant
Ce que tu vas apprendre
- Passer des données d'un parent à son enfant avec les props.
- Remonter une information de l'enfant vers le parent avec un événement.
- Utiliser
v-modelsur ton propre composant avecdefineModel().
Les props : du parent vers l'enfant
Une prop est une donnée qu'un composant reçoit de son parent. L'enfant la déclare avec defineProps().
<script setup lang="ts">
defineProps<{
titre: string
minutes?: number
}>()
</script>
<template>
<article>
<h3>{{ titre }}</h3>
<p v-if="minutes">{{ minutes }} min</p>
</article>
</template>
Le parent les passe comme des attributs :
<template>
<CarteRecette titre="Crêpes" :minutes="20" />
</template>
Un texte fixe s'écrit tel quel (titre="Crêpes"). Pour une valeur JavaScript, on utilise v-bind : :minutes="20". Le ? dans le type signifie que la prop est facultative.
Dans le template, les props s'utilisent directement. Dans le script, defineProps() renvoie un objet si tu le stockes : const props = defineProps<...>().
Une valeur par défaut
Avec la déstructuration, une prop facultative reçoit sa valeur par défaut comme n'importe quelle variable :
const { titre, minutes = 30 } = defineProps<{
titre: string
minutes?: number
}>()
À partir de Vue 3.5, ces variables restent réactives. Avant la 3.5, elles étaient de simples constantes qui ne se mettaient jamais à jour.
Le flux est à sens unique
Les données descendent du parent vers l'enfant, jamais l'inverse. Une prop est en lecture seule : props.titre = 'autre' provoque un avertissement.
Les événements : de l'enfant vers le parent
Un composant déclare ses événements avec defineEmits() et les déclenche avec emit().
<script setup lang="ts">
const emit = defineEmits<{
(e: 'choisir', id: number): void
}>()
</script>
<template>
<button @click="emit('choisir', 42)">Ajouter aux favoris</button>
</template>
Le parent écoute avec @ :
<script setup lang="ts">
function noter(id: number) {
console.log('Favori :', id)
}
</script>
<template>
<BoutonFavori @choisir="noter" />
</template>
Les arguments de emit après le nom arrivent dans le même ordre dans la fonction du parent.
Le v-model sur un composant
Que se passe-t-il si tu écris <ChampTitre v-model="titre" /> ? Il faut une prop pour recevoir la valeur et un événement pour la renvoyer. Depuis Vue 3.4, la macro defineModel() fait les deux d'un coup.
<script setup>
const titre = defineModel()
</script>
<template>
<input v-model="titre" />
</template>
titre se comporte comme un ref. Quand l'enfant le modifie, le parent est prévenu et sa propre variable change.
<script setup>
import { ref } from 'vue'
import ChampTitre from './components/ChampTitre.vue'
const titre = ref('Tarte aux pommes')
</script>
<template>
<ChampTitre v-model="titre" />
<p>{{ titre }}</p>
</template>
Plusieurs modèles et options
Tu peux donner un nom au modèle, et ajouter des options comme required ou default :
const titre = defineModel('titre', { required: true })
const note = defineModel('note', { default: 0 })
Le parent écrit alors v-model:titre="..." et v-model:note="...". Un composant peut ainsi exposer plusieurs valeurs liées.
Quel outil choisir ?
| Besoin | Outil |
|---|---|
| Donner une donnée à l'enfant | Une prop |
| Prévenir le parent d'une action | Un événement |
| Un champ que l'enfant peut modifier | defineModel() |
À retenir
defineProps()déclare les données reçues du parent ; elles sont en lecture seule.- Les données descendent par les props, les informations remontent par les événements.
defineEmits()déclare les événements,emit('nom', valeur)les déclenche,@nomles écoute.defineModel()crée une prop et son événement pour utiliserv-modelsur un composant.- Avec
defineModel('nom'), le parent écritv-model:nom.
Pour aller plus loin
Sources officielles
Ensuite
La réactivité
Déclarer un état avec ref et reactive, calculer des valeurs dérivées avec computed et lier un champ de formulaire avec v-model.
Slots, watch et cycle de vie
Laisser le parent fournir du contenu avec les slots, réagir aux changements avec watch et agir au bon moment avec onMounted.
- Projet
- Lignes de code
- Niveau
- 4e étage
- Appartement
- Vue
- Pièce
- 4/7
- Plan n°
- vue/04.props-et-evenements