Commentaires
Maintenant que nous avons appris à gérer des données avec Vue, il serait intéressant de les utiliser pour les afficher correctement dans notre body HTML. Actuellement, nous avons vu la syntaxe moustache, qui permet d'afficher une variable. Mais c'est rarement suffisant : comment faire pour afficher un contenu de manière conditionnelle, selon la valeur d'une donnée ? Comment boucler sur des tableaux de données ? Mettre du style conditionnel ? Toutes ces questions relatent en réalité d'un même sujet : le templating.
Vue utilise une syntaxe de template permettant de lier le DOM rendu à nos données.

La première des choses à apprendre est bien évidemment d'afficher une donnée. On l'a vu, pour ça, il nous faut utiliser la syntaxe moustache, soit 2 accolades ouvrantes/fermantes :
{{ maDonnee }}

Arthur, l'apprenti développeurTout simplement !
Hé oui, tout simplement. Mais c'est loin d'être suffisant comme expliqué juste au dessus. Et pour répondre à tous nos besoins, nous devrons utiliser... des directives !

Les directives avec Vue


J'en ai parlé rapidement dans la partie précédente. Ce sont des attributs spéciaux qu'on met dans notre HTML, dans notre template, qui contiennent une expression Javascript que Vue peut lire, interpréter et exécuter de sorte que le rendu soit réactif quand l'expression change ;)
Autrement dit, si ce que je mets dans ma directive change, l'affichage change de manière réactive ! Chaque directive démarre par v-, comme v-cloak.

Il existe plusieurs directives. La première que nous allons voir est la directive conditionnelle : v-if.

v-if, v-else, v-else-if


Cette directive s'utilise quand on veut afficher du contenu uniquement si une condition est respectée. Reprenons nos articles (nos posts). Si l'API ne nous en retourne aucune, il serait bon d'afficher un message...

{"language":"text/html","content":"<body>\n <main id=\"app\" v-cloak>\n <p v-if=\"posts.length < 1\"\n class=\"max-w-7xl mx-auto border-l-4 border-yellow-400 bg-yellow-50 p-4 text-sm text-yellow-700\">\n Aucun article à afficher.\n </p>\n\n </main>\n\n <script type=\"module\">\n import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'\n createApp({\n data() {\n return {\n loading: true,\n posts: []\n }\n },\n beforeCreate() {\n this.loading = true;\n },\n created() {\n this.posts = [] // On simule que l'API ne retourne rien\n },\n mounted() {\n this.loading = false\n }\n }).mount('#app')\n </script>\n</body>","filename":"index.html"}

Ici, le span ne va s'afficher QUE si la condition posts.length < 1 est respectée. Si on inspecte le code HTML de la page dans notre navigateur et que la condition n'est pas respectée, on ne verra même pas notre p !

Évidemment, de la même manière que v-if, nous avons v-else et v-else-if, qui, je l'imagine, te parle assez aisément. Un petit exemple :

{"language":"text/html","content":"<body>\n <main id=\"app\" v-cloak>\n <div v-if=\"loading\">Chargement en cours...</div>\n <p v-if=\"posts.length < 1\"\n class=\"max-w-7xl mx-auto border-l-4 border-yellow-400 bg-yellow-50 p-4 text-sm text-yellow-700\">\n Aucun article à afficher.\n </p>\n <div v-else class=\"max-w-7xl mx-auto grid gap-4 grid-cols-3\">\n <!-- Mes article -->\n </div>\n\n </main>\n\n <script type=\"module\">\n import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'\n createApp({\n data() {\n return {\n loading: true,\n posts: []\n }\n },\n beforeCreate() {\n this.loading = true;\n },\n created() {\n this.posts = [] // On simule que l'API ne retourne rien\n },\n mounted() {\n this.loading = false\n }\n }).mount('#app')\n </script>\n</body>","filename":"index.html"}

À savoir que tu peux regrouper plusieurs éléments HTML qui doivent agir en fonction d'une même expression grâce à la balise template comme suit :

{"language":"text/html","content":"<template v-if=\"ma condition\">\n\t<h1></h1>\n\t<span></span>\n\t<p></p>\n\t...\n</template>","filename":""}

Tu peux bien évidemment une autre balise que template, l'avantage de cette balise c'est qu'elle est désignée pour faire ce genre de choses dans la documentation du W3C.

v-show


v-show est semblable à v-if sauf qu'au lieu de ne pas afficher l'élément dans le HTML, il sera simplement à display:none. À utiliser dans le cas où le contenu va souvent être amené à être affiché/non affiché etc. Un exemple simple est celui d'un dropdown, d'un toggle, d'une fenêtre modale...

v-bind


v-bind est l'une des directives les plus intéressantes. Elle permet de remplacer la valeur d'un attribut existant en HTML (exemple : alt, href, src...) ou personnalisé par une donnée de Vue ! Hyper utile pour remplacer l'attribut src des images, l'attribut href des liens, des aria-attributes pour l'accessibilité... Elle permet aussi de faire quelques petites choses en plus que nous verrons plus tard. Elle n'est pas forcément simple à comprendre, mais nous verrons un exemple concret à la fin de cette partie avec nos articles. Ce qu'il faut retenir, c'est qu'avec les attributs HTML, on ne peut pas utiliser la syntaxe moustache pour remplacer leur contenu, il faut utiliser v-bind comme suit :
{"language":"text/html","content":"<main id=\"app\">\n <img v-bind:src=\"image\" alt=\"\" />\n</main>\n\n<script type=\"module\">\n import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'\n createApp({\n data() {\n return {\n image: 'monimage.jpg',\n }\n },\n }).mount('#app')\n\n</script>","filename":"index.html"}

Arthur, l'apprenti développeurEt donc je ne peux pas faire <img src="{{ image }}" ... /> ?
En effet, tu n'auras pas la possibilité de le faire. Il faut utiliser v-bind qui s'utilise en précisant le nom de l'attribut (v-bind:ATTRIBUT) puis sa valeur (résultat d'une expression Javascript valide, v-bind:ATTRIBUT="expression JS")

v-for


La directive v-for permet de faire une boucle. Elle s'utilise de la même manière que la boucle for(... of ...) en Javascript classique. On utilise cette directive directement sur la balise où on veut boucler. C'est cette directive qui nous manquait pour pouvoir compléter notre exemple avec les articles !
On peut donc enfin terminer notre code.

{"language":"text/html","content":"<!DOCTYPE html>\n<html lang=\"fr\">\n\n<head>\n <meta charset=\"utf-8\">\n <title>Mes premiers pas avec Vue 3</title>\n <script src=\"https://cdn.tailwindcss.com\"></script>\n <style>\n [v-cloak] {\n display: none;\n }\n </style>\n</head>\n\n<body>\n <main id=\"app\" v-cloak>\n <div v-if=\"loading\">Chargement en cours...</div>\n \n <p v-if=\"posts.length < 1\" class=\"max-w-7xl mx-auto border-l-4 border-yellow-400 bg-yellow-50 p-4 text-sm text-yellow-700\">\n Aucun article à afficher.\n </p>\n <div v-else class=\"max-w-7xl mx-auto grid gap-4 grid-cols-3\">\n <article v-for=\"post of posts\" class=\"shadow px-4 pb-8 pt-2 rounded\" v-bind:key=\"post.id\">\n <a v-bind:href=\"`http://monsite.com/${post.id}`\" class=\"mt-4 block\">\n <h2 class=\"text-xl font-semibold text-gray-900\">{{ post.title }}</h2>\n <p class=\"mt-3 text-base text-gray-500\">{{ post.body }}</p>\n </a>\n </article>\n </div>\n </main>\n\n <script type=\"module\">\n import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'\n createApp({\n data() {\n return {\n loading: true,\n posts: []\n }\n },\n beforeCreate() {\n this.loading = true;\n },\n created() {\n fetch('https://jsonplaceholder.typicode.com/posts')\n .then((response) => response.json())\n .then((json) => { this.posts = json });\n },\n mounted() {\n this.loading = false\n }\n }).mount('#app')\n\n </script>\n</body>\n\n</html>","filename":"index.html"}

Arthur, l'apprenti développeurÇa marche ! Par contre, je vois que tu as utilisé v-bind:key. Qu'est-ce que c'est ?
L'attribut key est essentiel quand on fait une boucle. Cet attribut doit contenir une valeur qui permet d'identifier de manière unique l'élément qu'on est en train de manipuler dans la boucle. Généralement, ce sera un id. Ça permet à Vue de mieux gérer des cas particuliers et ça nous permet d'assurer le bon fonctionnement des boucles. Ici, c'est facile car nos articles ont un id donné par l'API. Mais parfois, ce n'est pas le cas. Nous avons donc une syntaxe alternative :
{"language":"text/html","content":"<li v-for=\"(tutorial, key) of tutorials\" :key=\"key\">\n\t...\n</li>","filename":""}

Évidemment, j'ai utilisé la balise <li> mais j'aurais pu utiliser n'importe laquelle. Ce qui est important, c'est le (tutorial, key). En fait, à chaque tour de boucle on va avoir un incrémentateur qu'on a appelé "key". C'est à dire que key va prendre la valeur 1, 2, 3... Ce chiffre sera unique et identifiera chacun de nos tutoriels, on peut donc s'en servir dans l'attribut du même nom. C'est un peu comme le classique "i" de for(let i = 0; ...; i++).

Pendant que je suis dans la réécriture de v-for, sache que tu peux aussi écrire v-for avec "in" plutôt que "off" :
{"language":"text/html","content":"<article v-for=\"post in posts\" class=\"shadow px-4 pb-8 pt-2 rounded\" v-bind:key=\"post.id\">","filename":"index.html"}


Et encore autre chose, d'essentiel : il existe une syntaxe raccourcie. Tu peux éviter d'écrire v-bind en entier et laisser uniquement les deux points (:). Comme suit :
{"language":"text/html","content":"<main id=\"app\" v-cloak>\n <div v-if=\"loading\">Chargement en cours...</div>\n \n <p v-if=\"posts.length < 1\" class=\"max-w-7xl mx-auto border-l-4 border-yellow-400 bg-yellow-50 p-4 text-sm text-yellow-700\">\n Aucun article à afficher.\n </p>\n <div v-else class=\"max-w-7xl mx-auto grid gap-4 grid-cols-3\">\n <article v-for=\"post in posts\" class=\"shadow px-4 pb-8 pt-2 rounded\" :key=\"post.id\">\n <a :href=\"`http://monsite.com/${post.id}`\" class=\"mt-4 block\">\n <h2 class=\"text-xl font-semibold text-gray-900\">{{ post.title }}</h2>\n <p class=\"mt-3 text-base text-gray-500\">{{ post.body }}</p>\n </a>\n </article>\n </div>\n</main>","filename":"index.html"}


Arthur, l'apprenti développeurTout est compris merci ! Mais, il n'y a que ça comme directives ?
Non, bien sûr que non. Il y en a d'autres. Nous les verrons plus tard dans la suite de ce cours. D'ailleurs, la partie juste après permettra d'en découvrir une autre.

Arthur, l'apprenti développeurAh ? Laquelle et que va-t-on faire ?
Nous allons voir la directive v-on qui permet de gérer des évènements. Nous allons pour ça améliorer notre projet en cours afin de pouvoir faire un système de "À consulter plus tard" sur nos articles : si on clique "Ajouter" sur un article, il est ajouté à notre liste d'articles à consulter plus tard. Évidemment, ce ne sera que la partie front, donc il n'y aura pas de persistence si tu recharges la page.

Arthur, l'apprenti développeurOk ça a l'air chouette ! Je suis content de voir que ce qu'on fait est très concret. Je te suis ! J'ai terminé cette partie
Demander de l'assistance