Rendu conditionnel
Introduction
Dans une application, on ne veut pas toujours afficher la même chose. Certains blocs doivent apparaître uniquement si une condition est remplie (ex. : afficher une erreur, montrer un menu, changer le message selon l'état d'un stock). Pour répondre à ce besoin, Vue met à disposition deux directives principales. :
- v-if-else pour la créer/supprimer des nœuds
- v-show pour afficher/masquer via CSS
v-if, v-else-if et v-else
v-if décide si un bloc doit être présent dans le DOM :
- Condition vraie : Vue crée et insère les nœuds (HTML, texte, écouteurs).
- Condition fausse : Aucun nœud dans le DOM. Si le bloc était affiché, Vue le démonte et supprime nœuds et écouteurs.
Exemple : messages de stock sur une fiche produit
<script setup>
import { ref } from 'vue';
// Quantité en stock.
const stock = ref(12);
// Seuil pour alerte.
const seuilFaible = 5;
const diminuerStock = () => { if (stock.value > 0) stock.value--; };
const reapprovisionner = () => { stock.value += 5; };
</script>
<template>
<p>Stock actuel : {{ stock }}</p>
<p v-if="stock === 0">Rupture de stock</p>
<p v-else-if="stock <= seuilFaible">Stock faible, pensez à commander rapidement</p>
<p v-else>Produit disponible</p>
<button type="button" @click="diminuerStock">Vendre 1</button>
<button type="button" @click="reapprovisionner">Réappro +5</button>
</template>
Lorsqu'on souhaite afficher plusieurs éléments en fonction d'une même condition sans ajouter de balise inutile dans le DOM, on peut utiliser la balise template comme conteneur virtuel. Elle ne génère aucun élément visible dans le rendu final, mais permet de regrouper logiquement plusieurs balises soumises à la même condition :
<script setup>
import { ref } from 'vue';
// Quantité en stock
const stock = ref(12);
// Seuil pour alerte
const seuilFaible = 5;
const diminuerStock = () => {
if (stock.value > 0) stock.value--;
};
const reapprovisionner = () => {
stock.value += 5;
};
</script>
<template>
<p>Stock actuel : {{ stock }}</p>
<template v-if="stock === 0">
<p>Rupture de stock</p>
<p>Le produit sera bientôt réapprovisionné.</p>
</template>
<template v-else-if="stock <= seuilFaible">
<p>Stock faible</p>
<p>Pensez à commander rapidement.</p>
</template>
<template v-else>
<p>Produit disponible</p>
<p>Livraison sous 48 h.</p>
</template>
<button type="button" @click="diminuerStock">Vendre 1</button>
<button type="button" @click="reapprovisionner">Réappro +5</button>
</template>
Si un bloc HTML doit être affiché et masqué fréquemment, le créer et le détruire à chaque bascule avec v-if peut consommer des ressources et faire perdre son état local ou le focus utilisateur. Dans ce cas, il est préférable d'utiliser v-show, qui se contente de modifier la visibilité sans retirer l'élément du DOM.
v-show
Avec la directive v-show, le nœud reste dans le DOM et Vue change simplement l'affichage en basculant la propriété CSS display. Le changement est immédiat et la saisie, le défilement et l'état interne sont conservés. Idéal pour une FAQ, des onglets, un menu déroulant ou une aide contextuelle.
Exemple : aide contextuelle
<script setup>
import { ref } from 'vue';
const afficherAide = ref(false);
const basculerAide = () => { afficherAide.value = !afficherAide.value; };
</script>
<template>
<button type="button" @click="basculerAide">Afficher/masquer l'aide</button>
<div v-show="afficherAide">
<p>Astuce : votre mot de passe doit contenir au moins 12 caractères.</p>
</div>
</template>
Transitions avec <transition>
Lorsqu'on utilise v-if ou v-show, les blocs apparaissent ou disparaissent immédiatement. Cela fonctionne, mais l'effet peut sembler brutal pour l'utilisateur. Vue propose la balise <transition> pour rendre ces changements plus fluides grâce à des animations CSS.
Pour activer cette transition, il suffit de placer le contenu conditionnel à l'intérieur de la balise <transition>, et on définit un attribut name qui servira de préfixe aux classes CSS générées automatiquement par Vue.
Exemple : afficher/masquer un message avec une transition
<script setup>
import { ref } from 'vue';
const visible = ref(false);
const basculer = () => { visible.value = !visible.value; };
</script>
<template>
<button type="button" @click="basculer">Afficher / Masquer</button>
<transition name="fondu">
<p v-if="visible">Message important</p>
</transition>
</template>
<style scoped>
.fondu-enter-from,
.fondu-leave-to {
opacity: 0;
}
.fondu-enter-to,
.fondu-leave-from {
opacity: 1;
}
.fondu-enter-active,
.fondu-leave-active {
transition: opacity 0.5s;
}
</style>
Les classes générées automatiquement par Vue
Lorsqu'un élément est affiché ou masqué à l'aide de la balise transition, Vue ajoute et retire automatiquement plusieurs classes CSS correspondant aux différentes étapes de l'animation. Ces classes permettent de gérer les effets d'entrée et de sortie uniquement avec du CSS, sans écrire de JavaScript supplémentaire.
Les classes CSS lors de la phase d'ajout au DOM :
- .nom-enter-active : appliquée pendant toute la durée de l'entrée, souvent utilisée pour définir la propriété transition.
- .nom-enter-from : état initial de l'élément lorsqu'il entre.
- .nom-enter-to : état final de l'élément une fois l'animation d'entrée terminée.
Les classes CSS lors de la phase de suppression du DOM :
- .nom-leave-active : appliquée pendant toute la durée de la sortie, souvent pour la propriété transition.
- .nom-leave-from : état initial de l'élément au moment où il commence à disparaître.
- .nom-leave-to : état final après la disparition complète.
Ici, nom correspond à la valeur donnée à l'attribut name de la balise <transition> (dans l'exemple ci-dessus, fondu).
Permettre l'accès aux classes CSS dans tous les composants
Dans l'exemple précédent, les classes CSS étant déclarées dans la balise <style> avec l'attribut scoped, elles ne sont accessibles que dans ce composant.
Pour les réutiliser partout, placer les classes de transition dans un fichier global src/assets/transitions.css puis l'importer une seule fois dans main.js à la suite des importations Javascript.
// main.js
import './assets/transitions.css'
Ce mécanisme de transition sera repris dans un chapitre dédié où nous verrons plus de possibilités (animations plus complexes, transitions sur des listes, etc.).
Exercices
Créer un nouveau projet Vue nommé vuejs05-rendu-conditionnel en suivant la procédure décrite dans le chapitre dédié. Tous les exercices de cette page peuvent être réalisés dans ce projet, directement les uns à la suite des autres dans le fichier App.vue.
Dans la partie template, créer une balise <h1> avec le texte suivant : "Vue.js 05 : Rendu conditionnel".
Exercice 01 : Valider un champ de code postal
Objectif : Mettre en place une validation simple côté Vue et gérer la soumission d'un <form>. Afficher un message d'erreur si le champ est vide ou si le code postal n'a pas exactement 4 chiffres. Déclencher la validation à l'événement submit du formulaire.
Instructions :
- Dans la partie <script>, importer la dépendance ref depuis Vue.
-
Créer deux constantes réactives :
- codePostal initialisée à une chaîne vide via ref().
- erreur initialisée à une chaîne vide via ref().
-
Créer une fonction validerFormulaire() qui :
- Réinitialise erreur à une chaîne vide.
- Si codePostal est vide, assigner à erreur "Veuillez entrer un code postal.".
- Sinon, si codePostal a une longueur différente de 4 ou contient autre chose que des chiffres (isNaN), assigner "Le code postal doit comporter 4 chiffres.".
- Dans la partie <template>, créer un sous-titre <h2> avec le texte "Exo 01".
- Créer un <form> contenant le champ et le bouton de soumission. Lier l'événement de soumission (submit) à la fonction de validation validerFormulaire() sur la balise <form>.
-
Dans le formulaire, ajouter une paire libellé/champ pour le code postal :
- Un <label> lié au champ via les attributs for/id et lui attribuer le texte : "Code postal".
- Un champ texte lié avec la directive v-model à la constante réactive codePostal et un placeholder (ex. : "1000").
- Sous le champ, afficher un paragraphe d'erreur à l'aide de la directive v-if si la valeur de la constante réactive erreur n'est pas vide. Le texte du paragraphe provient de la constante erreur.
- Ajouter un bouton de type submit avec le texte "Soumettre".
- Sous le formulaire, afficher un paragraphe de confirmation après une soumission valide en utilisant la directive v-if vérifiant que la constante réactive erreur est vide et afficher "Code postal [codePostal] a bien été envoyé".
-
Tester :
- Soumettre avec le champ vide.
- Soumettre avec une valeur non conforme.
- Soumettre avec une valeur valide.
Exercice 02 : Messages d'état avec v-if, v-else-if et v-else
Objectif : Afficher un message différent selon la valeur choisie dans une liste déroulante. Utiliser une chaîne de conditions avec v-if, v-else-if et v-else. Le cas d'usage correspond à un suivi de commande dans un tableau de bord.
Instructions :
- Dans la partie <script>, importer ref depuis Vue.
- Créer une constante réactive statut initialisée à une chaîne vide via ref().
- Dans la partie <template>, ajouter un sous-titre <h2> avec le texte "Exo 02".
- Créer une balise <label> avec le texte "Statut de la commande" et lier cette étiquette à une liste déroulante <select> via l'attribut for. Lier la liste déroulante à la constante réactive statut avec la directive v-model.
-
Dans la liste déroulante, créer plusieurs options :
- Première option : valeur vide pour l'attribut value et "— choisir —" en contenu textuel.
- Seconde option : "en-attente" pour l'attribut value et "En attente de paiement" en contenu textuel.
- Troisième option : "en-preparation" pour l'attribut value et "En préparation" en contenu textuel.
- Quatrième option : "expediee" pour l'attribut value et "Expédiée" en contenu textuel.
- Cinquième option : "livree" pour l'attribut value et "Livrée" en contenu textuel.
-
Sous la liste, créer un bloc de message.
Utiliser une chaîne de conditions avec
v-if, v-else-if et
v-else pour afficher exactement un message à la fois :
- Si la valeur de statut est "en-attente" : "Commande en attente de paiement".
- Sinon si la valeur est "en-preparation" : "Commande en préparation dans l'atelier".
- Sinon si la valeur est "expediee" : "Commande expédiée, en cours d'acheminement".
- Sinon si la valeur est "livree" : "Commande livrée, merci pour votre achat".
- Sinon (valeur vide) : "Aucun statut sélectionné".
-
Tester :
- Choisir chaque option et vérifier que le bon message apparaît.
- Laisser la valeur vide et vérifier que le message "Aucun statut sélectionné" s'affiche.
Exercice 03 : Panneau de filtres avec v-show et transition
Objectif : Créer un panneau de filtres qui s'affiche et se masque fréquemment sans perdre l'état interne. Utiliser v-show pour conserver le contenu dans le DOM et appliquer une transition fluide avec <transition>.
Instructions :
- Dans la partie <script>, importer la dépendance ref depuis Vue.
-
Créer quatre constantes réactives :
- afficherFiltres initialisée à false via ref() pour contrôler l'affichage du panneau.
- enStockUniquement initialisée à false via ref() pour un filtre de disponibilité.
- tri initialisée à la chaîne vide via ref() pour un critère de tri.
- Créer une fonction fléchée basculerFiltres() qui inverse la valeur de afficherFiltres.
- Dans la partie <template>, ajouter un sous-titre <h2> avec le texte "Exo 03".
- Ajouter un bouton "Filtres avancés" qui appelle la fonction basculerFiltres() au clic.
- Créer une balise <transition> (ouverture et fermeture) et définir l'attribut name à "panneau", qui servira de préfixe aux classes de transition générées par Vue.
- À l'intérieur de <transition>, créer un conteneur <div> pour les filtres et contrôler son affichage avec en fonction de la constante réactive afficherFiltres à l'aide de la directive v-show.
-
Dans le conteneur (la balise <div>) :
- Créer une balise label avec le texte "En stock uniquement"
- Dans la balise label, Créer une case à cocher checkbox liée à la constante réactive enStockUniquement à l'aide de la directive v-model. Cette constante sera ainsi mise à jour à chaque changement d'état de la case à cocher.
- Créer ne liste déroulante select liée à la constante réactive tri à l'aide de la directive v-model. Cette constante sera ainsi mise à jour à chaque changement d'option sélectionnée.
-
Dans la balise select, Créer trois balise option :
- Première option : valeur vide pour l'attribut value et "— choisir —" en contenu textuel.
- Seconde option : "prix-asc" pour l'attribut value et "Prix croissant" en contenu textuel.
- Troisième option : "prix-desc" pour l'attribut value et "Prix décroissant" en contenu textuel.
- Quatrième option : "nom-asc" pour l'attribut value et "Nom (A -> Z)" en contenu textuel.
-
Sous la balise de fermeture <transition>, afficher un résumé lisible de l'état des filtres avec des moustaches :
- Texte indiquant si "En stock uniquement" est activé ou non.
- Texte indiquant la valeur choisie pour "Tri" (affiche "aucun" pour la première option).
-
Dans la partie <style>, définir les classes CSS correspondant à la valeur de l'attribut
name configuré dans la balise <transition>.
Vue génère automatiquement des classes avec ce préfixe au moment où l'élément entre ou sort.
C'est grâce à ces classes que la transition peut être animée :
- Créer .panneau-enter-from et .panneau-leave-to pour démarrer caché avec opacity: 0 et une légère translation verticale via transform: translateY(6px).
- Créer .panneau-enter-to et .panneau-leave-from pour l'état visible avec opacity: 1 et transform: translateY(0).
- Définir .panneau-enter-active et .panneau-leave-active pour l'animation, en précisant transition sur l'opacité et la translation (ex. transition: opacity .3s, transform .3s).
-
Tester :
- Cliquer plusieurs fois sur "Filtres avancés" et vérifier que l'ouverture et la fermeture sont fluides.
- Modifier la valeur des filtres et vérifier que le paragraphe lié à la constante enStockUniquement ainsi que celui lié à la constante
- tri affichent les valeurs attendues.