Les composants
Ce que tu vas apprendre
- Créer un composant et l'utiliser sans
import. - Comment Nuxt nomme les composants rangés dans des sous-dossiers.
- Passer des données à un composant, et en recevoir.
- Charger un composant seulement quand il sert, ou seulement dans le navigateur.
Un composant, sans import
Sur ta page de recettes, chaque recette s'affiche dans une carte. Tu crées le fichier app/components/CarteRecette.vue, et tu l'utilises directement dans n'importe quelle page :
<template>
<CarteRecette titre="Crêpes" :duree="20" />
</template>
Avec Vue seul, il faudrait écrire import CarteRecette from '...'. Nuxt le fait pour toi, et n'inclut dans le site que les composants réellement utilisés.
Les sous-dossiers donnent le nom
Quand tu ranges un composant dans un sous-dossier, le nom du dossier devient le début du nom du composant :
| Fichier | Nom à utiliser |
|---|---|
app/components/CarteRecette.vue | <CarteRecette /> |
app/components/recette/Carte.vue | <RecetteCarte /> |
app/components/recette/Ingredients.vue | <RecetteIngredients /> |
Tu peux ainsi regrouper tous les composants d'une même partie du site, sans noms à rallonge dans les fichiers.
Passer des données : les props
Un composant reçoit des données de son parent par des props. Tu les déclares avec defineProps, et TypeScript vérifie que le parent envoie les bons types :
<script setup lang="ts">
const props = defineProps<{
titre: string
duree: number
vegetarien?: boolean // le ? rend la prop facultative
}>()
</script>
<template>
<article>
<h2>{{ titre }}</h2>
<p>{{ duree }} min <span v-if="vegetarien">· végétarien</span></p>
</article>
</template>
Dans le parent, :duree="20" (avec les deux-points) envoie le nombre 20. Sans les deux-points, duree="20" enverrait le texte « 20 ».
Remonter une information : les événements
Les props descendent du parent vers l'enfant. Pour prévenir le parent (un clic sur « Ajouter aux favoris »), l'enfant émet un événement :
<script setup lang="ts">
const emit = defineEmits<{ favori: [id: number] }>()
</script>
<template>
<button @click="emit('favori', 12)">Ajouter aux favoris</button>
</template>
<CarteRecette titre="Crêpes" :duree="20" @favori="ajouterFavori" />
Insérer du contenu : les slots
Un <slot /> laisse le parent glisser son propre contenu dans le composant. C'est le même mécanisme que pour les gabarits du chapitre précédent :
<template>
<div class="encadre">
<slot />
</div>
</template>
<Encadre>Astuce : laisse reposer la pâte une heure.</Encadre>
Charger à la demande
Certains composants sont lourds (une carte, un éditeur) et ne servent pas tout de suite. Ajoute le préfixe Lazy devant le nom : leur code n'est téléchargé que lorsqu'ils s'affichent.
<script setup lang="ts">
const afficherCommentaires = ref(false)
</script>
<template>
<button @click="afficherCommentaires = true">Voir les commentaires</button>
<LazyRecetteCommentaires v-if="afficherCommentaires" />
</template>
Seulement dans le navigateur
Par défaut, Nuxt affiche aussi tes composants sur le serveur. Un composant qui utilise window ou localStorage plante alors, car ces objets n'existent que dans le navigateur. Deux solutions :
- nommer le fichier avec
.client.vue(par exempleMinuteur.client.vue) : il ne s'affiche que dans le navigateur ; - entourer le composant de
<ClientOnly>dans le parent.
<ClientOnly>
<Minuteur />
</ClientOnly>
localStorage, donc le bouton favori est entouré de <ClientOnly>.À retenir
- Un fichier de
app/components/s'utilise sansimport; le sous-dossier préfixe le nom. definePropsreçoit les données du parent,defineEmitslui envoie des événements,<slot />accueille son contenu.Lazydevant un nom charge le composant à la demande..client.vueou<ClientOnly>pour un composant qui a besoin du navigateur.
Pour aller plus loin
Sources officielles
Ensuite
Pages et routage
Créer des pages, des adresses dynamiques comme /recettes/12, des liens sans rechargement et des gabarits communs.
Récupérer des données
Charger des données avec useFetch, gérer le chargement et les erreurs, et savoir quand utiliser $fetch.
- Projet
- Lignes de code
- Niveau
- Toit-terrasse
- Appartement
- Nuxt
- Pièce
- 4/8
- Plan n°
- nuxt/04.composants