Gabarits et directives
Cours · Vue : construire une application web (école d'ingénieur), chapitre 2 · école d'ingénieur, informatique · le début du chapitre, la suite sur Adloun
La fiche du chapitre précédent ne montrait qu'un livre, et l'interpolation ne savait qu'insérer du texte. Le catalogue de la Librairie demande davantage : répéter une carte pour chaque livre, n'afficher le badge « Nouveauté » que pour les nouveautés, griser un livre épuisé et désactiver son bouton, réagir au clic sur un rayon. Au livre JavaScript, chacune de ces tâches demandait une boucle qui créait des éléments, des classList.toggle et des addEventListener. Dans un gabarit Vue, elles s'écrivent avec des directives, des attributs spéciaux qui commencent par v-.
Objectifs du chapitre
- Lier un attribut à une expression avec
v-bind(abrégé:) et prévoir le résultat pour chaque type de valeur. - Afficher sous condition avec
v-if,v-else-if,v-else, et choisir entrev-ifetv-show. - Répéter un élément avec
v-foret expliquer le rôle de la clé:key. - Écouter un événement avec
v-on(abrégé@) et ses modificateurs. - Lier des classes et des styles ; connaître
v-html,v-textetv-cloak.
Les rendus et les affichages de ce chapitre ont été produits dans Chromium, avec Vue 3.5.43, en simulant clics et frappes avec l'outil Playwright. Les pages chargent toutes Vue puis app.js, comme au chapitre 1 ; on n'en montre désormais que le contenu du <body>.
2.1 Les directives
Une directive est un attribut du gabarit dont le nom commence par v- et dont la valeur est une expression JavaScript, évaluée avec les données de l'application. Sa forme complète est v-nom:argument.modificateur="expression" : l'argument précise la cible (quel attribut, quel événement), les modificateurs ajustent le comportement.
Quand une donnée réactive utilisée dans l'expression change, Vue réapplique la directive. Les plus fréquentes ont une forme abrégée : :src pour v-bind:src, @click pour v-on:click. Comme l'interpolation, une directive ne contient qu'une expression ; la seule exception est v-for, qui a sa propre syntaxe.
2.2 Lier un attribut : v-bind
L'interpolation ne fonctionne que dans le texte : écrire <img src="{{ livre.image }}"> ne fait rien d'utile, le navigateur cherche une image dont le nom est littéralement {{ livre.image }}. Pour qu'un attribut dépende des données, on le préfixe par v-bind:, ou simplement par deux-points.
<div id="app">
<a :href="'livre.html?isbn=' + livre.isbn" :title="livre.titre">Voir la fiche</a>
<img :src="livre.image" :alt="'Couverture de ' + livre.titre" width="60" height="80">
<button type="button" :disabled="livre.stock === 0">Ajouter</button>
<input type="text" v-bind="champ">
</div>
const { createApp } = Vue;
createApp({
setup() {
const livre = {
isbn: "9782956300045",
titre: "Physique générale",
image: "../librairie/images/physique.svg",
stock: 0,
};
// v-bind sans argument : chaque propriété devient un attribut.
const champ = { type: "number", min: 1, max: 5, value: 1, "aria-label": "Quantité" };
return { livre, champ };
},
}).mount("#app");
Le HTML produit par Vue :
<a href="livre.html?isbn=9782956300045" title="Physique générale">Voir la fiche</a><img src="../librairie/images/physique.svg" alt="Couverture de Physique générale" width="60" height="80"><button type="button" disabled="">Ajouter</button><input type="number" min="1" max="5" aria-label="Quantité" value="1">

L'expression de :href concatène une chaîne et l'ISBN ; celle de :disabled est une comparaison. La dernière ligne utilise v-bind sans argument : chaque propriété de l'objet devient un attribut. C'est pratique pour transmettre d'un coup un lot d'attributs préparé dans setup.
Que devient un attribut quand l'expression vaut false, null ou une chaîne vide ? La page suivante lie la même valeur à :disabled (un attribut booléen du HTML, dont seule la présence compte) et à :title (un attribut ordinaire) :
<ul id="app">
<li v-for="v in valeurs" :key="String(v)">
<button type="button" :disabled="v" :title="v">{{ JSON.stringify(v) ?? "undefined" }}</button>
</li>
</ul>
const { createApp } = Vue;
createApp({
setup() {
return { valeurs: [true, false, null, undefined, "", 0, "non"] };
},
}).mount("#app");
Pour chaque valeur, le bouton produit :
true <button type="button" disabled="" title="true">
false <button type="button" title="false">
null <button type="button">
undefined <button type="button">
"" <button type="button" disabled="" title="">
0 <button type="button" title="0">
"non" <button type="button" disabled="" title="non">
nulletundefinedretirent l'attribut.- Pour un attribut booléen comme
disabled,checkedouhidden, Vue applique les règles du HTML :falseretire l'attribut, toute autre valeur le met, y compris la chaîne vide (dans<button disabled>, l'attribut vaut justement""). Le nombre 0, lui, le retire, commefalse. - Pour un attribut ordinaire, la valeur est convertie en chaîne : la valeur
falsedonnetitle="false". Pour retirer un attribut ordinaire, on lienull.
Les attributs ARIA sont des attributs ordinaires : lier la valeur false à :aria-pressed produit l'attribut aria-pressed="false", ce qu'un lecteur d'écran attend d'un bouton bascule relâché ; pour retirer l'attribut, on lie null.
2.3 Afficher sous condition
2.3.1 v-if, v-else-if, v-else
<div id="app">
<p v-if="stock === 0">Épuisé</p>
<p v-else-if="stock < 5">Plus que {{ stock }} exemplaires</p>
<p v-else>En stock</p>
<button type="button" @click="details = !details">Détails</button>
<p id="avec-if" v-if="details">Résumé (v-if)</p>
<p id="avec-show" v-show="details">Résumé (v-show)</p>
</div>
const { createApp, ref } = Vue;
createApp({
setup() {
const stock = ref(3);
const details = ref(false);
return { stock, details };
},
}).mount("#app");
Les trois premiers paragraphes forment une chaîne : un seul est affiché, le premier dont la condition est vraie. Avec un stock de 3, puis 0, puis 8, le texte affiché est :
Plus que 3 exemplaires
Épuisé
En stock
v-else-if et v-else doivent suivre immédiatement un élément qui porte v-if ou v-else-if. Pour soumettre plusieurs éléments à la même condition sans ajouter d'élément englobant, on les place dans un <template v-if="…"> : la balise <template> n'apparaît pas dans la page, seul son contenu est rendu.
2.3.2 v-if ou v-show ?
Les deux derniers paragraphes de l'exemple dépendent de la même donnée, details, l'un avec v-if, l'autre avec v-show. Au chargement, après un clic sur « Détails », puis après un second clic :
La suite du cours est sur Adloun
Le chapitre en entier, formules et figures comprises, avec le tuteur, les fiches, les QCM et les exercices.
Lire la suite du coursEn accès libre, sans inscription.