Commentaires
Dans cette partie nous allons maintenant voir comment gérer les données de notre application ainsi que les crochets, c'est à dire les moments durant lesquels nous pouvons interagir dans le cycle de vie de Vue.

Le cycle de vie et les crochets


Arthur, l'apprenti développeurLe cycle de vie de Vue ? Qu'est-ce que c'est ?
Pour bien comprendre comment utiliser Vue, il faut comprendre ce qui se passe quand on fait Vue.createApp(). À chaque fois qu'on instancie Vue (ou un composant, on verra ça plus tard), de nombreuses étapes d'initialisation sont réalisées. On peut intervenir sur chacune d'elles via les crochets (hooks). Ces étapes constituent une partie du cycle de vie de Vue ; l'autre partie étant le moment où l'application se termine et se détruit.
Après avoir fait Vue.createApp({}).mount("#el"), voici par quelles étapes nous passons :

  1. Initialisation des évènements et du cycle de vie. À ce moment, on ne peut aucunement interagir avec le DOM ni même avec les données

  2. Initialisation de l'injection et de la réactivité. Là, on peut interagir avec nos données !

  3. Initialisation du DOM

  4. Initialisation de l'élément container. Son contenu est remplacé par le DOM généré à l'étape précédente


Et une fois que le composant n'est plus utilisé, il passe par 2 étapes :

  1. Préparation de la suppression

  2. Suppression du composant


Comme je l'ai dit, on peut agir sur chacune de ces étapes via les hooks. Très pratique pour charger des éléments par exemple avant de les afficher (ex : récupération des données d'une API)
Les hooks sont des méthodes qu'on met dans l'objet passé à createApp().

{"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</head>\n\n<body>\n <main id=\"app\">\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\t\t\t return {\n\t\t\t property: 'Example property.'\n\t\t\t }\n\t\t\t},\n\t\t\tbeforeCreate() {\n\t\t\t\tconsole.log(\"Je suis l'étape d'initilisation 1\")\n\t\t\t},\n\t\t\tcreated() {\n\t\t\t\tconsole.log(\"Je suis l'étape d'initilisation 2\")\n\t\t\t\tconsole.log(\"Je suis aussi le meilleur endroit pour consommer une API\")\n\t\t\t},\n\t\t\tbeforeMount() {\n\t\t\t\tconsole.log(\"Je suis l'étape d'initilisation 3. À éviter pour consommer une API\")\n\t\t\t},\n\t\t\tmounted() {\n\t\t\t\tconsole.log(\"Ca y est, le composant est totalement créé et apparait sur la page en tant que HTML\")\n\t\t\t},\n\t\t\tbeforeUnmount() {\n\t\t\t\tconsole.log(\"On ne se sert plus de moi... Je vais pouvoir me détruire. Ici, je peux vider de la mémoire en supprimant des données\")\n\t\t\t},\n\t\t\tunmounted() {\n\t\t\t\tconsole.log(\"Je suis détruit. Ici, je peux envoyer un message quelque part pour faire part de ma destruction\")\n\t\t\t}\n }).mount('#app')\n </script>\n</body>\n\n</html>","filename":"index.html"}

Il faut savoir que les composants ne sont pas détruits automatiquement. Il faut le faire manuellement avec unmount si on a besoin, mais c'est très rare.

Arthur, l'apprenti développeurSuper ça ! Mais pourrais-je avoir des exemples plus concrets ?
Tout à fait. On va manipuler les hooks plus en profondeur juste après. Mais avant, il nous faut voir comment gérer des données au sein de notre script. Il faut savoir que certains hooks cités ci-dessus ne sont parfois utilisés que très rarement. Les plus courant sont created() et mounted(). Nous les utiliserons juste après !

Les données


On peut évidemment stocker des données que notre application va gérer. Ces données seront réactives, c'est-à-dire que si elles sont amenées à changer de valeur durant l'exécution de notre application, leur affichage dans le DOM sera modifié en conséquence.
Les données se mettent dans une méthode data() qui retourne un objet contenant nos données. On peut utiliser n'importe quel type de données (booléen, string, objet, tableau...). Pour accéder à ces données au sein des méthodes qu'on définira dans createApp, il faut utiliser this.
Voici un exemple :

{"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</head>\n\n<body>\n <main id=\"app\">\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 category: 'Javascript',\n tutos: [\n {\n name: \"Les bases\",\n difficulty: 2,\n length: \"Long\"\n },\n {\n name: \"Les composants\",\n difficulty: 3,\n length: \"Long\"\n },\n ],\n number: 42,\n somethingBoolean: true,\n }\n },\n created() {\n console.log(this.category)\n console.log(this.number)\n }\n }).mount('#app')\n </script>\n</body>\n\n</html>","filename":"index.html"}

Dans la console, on a réussi à afficher category et number ! On aurait aussi pu afficher tout le reste, évidemment.


Bon. Définir des données c'est bien, mais s'en servir, c'est pas mal non plus ! La première des étapes, c'est d'afficher ces données pour l'utilisateur. Pour ça, on utilisera... des moustaches.

{"language":"text/html","content":"<body>\n <main id=\"app\">\n <h1>Quel est le meilleur framework JS ?</h1>\n <p>{{ bestFramework }} bien sûr ! </p>\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 bestFramework: 'Vue.JS',\n }\n },\n\n }).mount('#app')\n\n </script>\n</body>","filename":"index.html"}

Cette drôle de syntaxe avec des {{ }}, ce sont les fameuses moustaches. Pour afficher une donnée dans le body de notre page, il suffit de mettre le nom de la donnée entre ces moustaches. Et le tour est joué. Essaie pour voir !

Arthur, l'apprenti développeurEn effet, ça marche. C'est super cool ça ! Plus rapide que document.getElementById('app').textContent = bestFramework.
Tout à fait ! Là aussi est l'intérêt d'un framework : développer plus rapidement, tout en ayant des codes propres, et fiables.

Arthur, l'apprenti développeurJe comprends ! Par contre quelque chose m'embête... Quand je charge ma page dans la navigateur, parfois, il y a quelques micro-secondes durant lesquelles on voit {{ bestFramework }} et pas la valeur de la donnée...
En effet. Il y a un petit temps avec que l'étape de compilation soit entièrement terminée. Heureusement, nous avons une solution pour ça :v-cloak. C'est ce qu'on appelle une directive. v-cloak va cacher les moustaches durant la phase de compilation. Une fois terminée, seule la donnée sera affichée, comme souhaité. Je reviendrai sur les directives plus tard, mais tu peux utiliser celle-ci comme suit.

{"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 <style>\n [v-cloak] {\n display: none;\n }\n </style>\n</head>\n\n<body>\n <main id=\"app\" v-cloak>\n <h1>Quel est le meilleur framework JS ?</h1>\n <p>{{ bestFramework }} bien sûr ! </p>\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 bestFramework: 'Vue.JS',\n }\n },\n\n }).mount('#app')\n\n </script>\n</body>\n\n</html>","filename":"index.html"}

N'oublie pas d'ajouter le CSS, comme dans l'exemple !
Arthur, l'apprenti développeurC'est cool ça ! Et ça marche tout le temps ?
Tout le temps ! Mais attention, ce n'est utile que dans le cas où tu utilises Vue.JS sans étape de "build", ce qui est notre cas actuellement vu qu'on utilise un CDN. Mais lorsque, dans les futurs cours, nous utiliserons un builder, ce ne sera plus utile du tout.

Bon, je t'avais promis un exemple un peu plus concret avec les crochets. En voici un, un peu plus complexe, qui consomme une API et affiche les données reçues.
{"language":"text/html","content":"<body>\n <main id=\"app\" v-cloak>\n {{ posts }}\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>","filename":"index.html"}

Ici, on utilise beforeCreate pour initialiser loading à true. Puis dans le created, on récupère des données en consommant une API. Enfin, dans le mounted, on peut remettre notre loading à false. Ici, je ne tire pas profit de ce loading, mais on peut imaginer afficher un loader durant le temps de récupération de l'API !
Comme règle d'or : les appels API se font quasi exclusivement depuis created quand tu veux que les données récupérées de l'API s'affichent au moment du chargement de la page.

Arthur, l'apprenti développeurJe vois, c'est intéressant. Je commence à mieux comprendre l'intérêt des hooks ! Par contre... La page m'affiche le contenu récupéré de manière brute..? C'est voulu ?
C'est pas très joli, on est d'accord. L'idéal serait de lister les posts récupérés depuis l'API sous forme de jolies cartes HTML. Mais pour ça... Il faut qu'on voie les méthodes de templating.

Arthur, l'apprenti développeurOk, je te suis ! J'ai terminé cette partie
Demander de l'assistance