Cours Vue.js · Module 1: Vue et Vite
Ton premier système Vue - le panneau de statut de mission
Dans cette leçon8
Dans la leçon précédente, tu as démonté un module .vue en trois sections et tu as vu comment le template, la logique et le style tiennent dans un seul fichier. Le panneau de survie assemblé là-bas souffrait pourtant d'un défaut sérieux : il était mort. Il affichait une mesure et rien de plus - aucun bouton, aucune réaction, aucun changement au fil du temps.
Au Centre de Contrôle du NOVA LAB, un panneau pareil ne vaut guère mieux qu'une plaque vissée à côté de la porte. L'officier de quart doit pouvoir appuyer sur un bouton, faire avancer la phase de la mission, voir la distance vers Mars fondre, et repérer dans la même seconde l'instant où l'inscription verte vire au jaune. Aujourd'hui tu vas construire ton premier panneau capable de tout cela : le panneau de statut de la mission MARS ONE.
En chemin tu vas rencontrer quatre outils, et ce sont eux le véritable sujet de la leçon : la fonction ref(), l'interpolation {{ }}, la gestion des événements avec @click et les classes dynamiques avec :class. Chacun d'eux t'apparaîtra d'abord comme un manque qui fait mal, et seulement ensuite comme une solution.
Un panneau incapable de changer
Commençons par la version la plus simple imaginable du panneau - celle qu'on pourrait écrire en HTML pur, sans le moindre framework. Le nom de la mission et le nombre de jours restants sont inscrits directement dans les balises.
1<template>
2 <h1>MARS ONE - Premiere Colonie</h1>
3 <p>Jours restants : 180</p>
4</template>Ce code est correct et s'affichera sans le moindre reproche. Le problème n'arrive que le lendemain matin : la télémétrie annonce 179 jours, et le seul moyen de mettre le panneau à jour consiste à ouvrir le fichier, corriger le nombre et redéployer le système. La valeur est collée à la balise. Vue n'a rien à faire ici, parce qu'il ignore que le nombre 180 signifie quoi que ce soit de plus qu'un fragment de texte.
Pour que quelque chose puisse changer tout seul, la valeur doit d'abord déménager du template vers la section <script setup> et recevoir un gardien qui remarquera chacune de ses modifications.
ref() - une valeur sous surveillance du système
Vue met à ta disposition la fonction ref. Tu la fais venir avec l'instruction import depuis le paquet vue, puis tu l'appelles en lui donnant une valeur initiale. En retour tu reçois un conteneur : un récipient unique dans lequel ta valeur est installée et que Vue garde sous surveillance. Le nom vient du mot anglais reference, car ce n'est pas le nombre lui-même, mais un renvoi vers l'endroit où ce nombre habite.
Cette seule propriété - être observé - fait toute la différence. Quand tu remplaces le contenu du conteneur, Vue le sait, retrouve tous les endroits du template qui s'en servent et rafraîchit exactement ceux-là. Pas la page entière, pas le panneau entier, seulement ces fragments. C'est ce que nous appelons la réactivité, et c'est elle qui fait vivre Vue.
1<script setup>
2import { ref } from 'vue'
3
4const missionName = ref('MARS ONE - Premiere Colonie')
5const daysRemaining = ref(180)
6</script>Les valeurs sont identiques à celles d'il y a un instant, cela n'a pas changé. Ce qui a changé, c'est l'endroit où elles habitent et le fait que Vue soit désormais au courant de leur existence. Observe bien la forme de cette ligne, car tu l'écriras encore des centaines de fois : d'abord le mot const, puis le nom de la variable, puis le signe =, et tout à la fin l'appel de ref() avec la valeur initiale entre parenthèses. Quatre parties, toujours dans cet ordre - const counter = ref(0) a exactement la même allure.
Le mot const devant une valeur censée changer ressemble à une erreur, mais n'en est pas une. const interdit le remplacement du conteneur lui-même, et c'est une très bonne chose : si tu glissais autre chose sous ce nom, Vue perdrait la liaison avec le template. Le contenu du conteneur, lui, se change autant que tu veux, et c'est précisément ce que tu vas faire dans un instant.
Une mise au point tout de suite, car ref() se voit souvent confondue avec des outils qui n'ont rien à voir. Cette fonction sert exclusivement à créer des données réactives. Elle n'a aucun rapport avec le routage entre les écrans de la station - ce travail revient à Vue Router, que tu as croisé dans le tableau de l'écosystème de la première leçon. Elle ne stylise pas les composants - l'apparence est décrite par la section <style scoped> de la leçon précédente. Et elle ne sert pas non plus à importer des fichiers : les fichiers et les paquets, tu les fais venir avec l'instruction import, exactement comme tu viens d'y faire venir ref depuis le paquet vue.
L'interpolation - la valeur arrive à l'écran
Les données sont déjà dans le script, mais le template ne les voit toujours pas. Le pont entre les deux sections s'appelle l'interpolation : une double accolade, que le monde de Vue surnomme les moustaches. Tu y inscris le nom d'une variable et Vue insère à cet endroit sa valeur courante, en veillant à la réinsérer après chaque changement.
1<template>
2 <h1>{{ missionName }}</h1>
3 <p>Jours restants : {{ daysRemaining }}</p>
4</template>Le même nom de mission, le même nombre à l'écran, mais c'est Vue qui les gère à présent. Remarque ce que tu n'as pas eu à changer : les balises <h1> et <p> sont restées du HTML ordinaire, la mention "Jours restants" reste du texte ordinaire, et les moustaches ont pris exactement la place où siégeait auparavant le nombre saisi à la main. Vue ne te retire pas le HTML, il y ajoute seulement des emplacements où glisser une valeur.
À l'intérieur des moustaches tu peux placer non seulement un nom de variable, mais toute expression JavaScript qui renvoie quelque chose : une opération arithmétique, un appel de méthode, une condition. En revanche tu n'y feras pas tenir d'instructions de contrôle du genre if, ni de boucles - ce n'est pas l'endroit de la logique, seulement celui de son résultat.
Retiens dès maintenant une limite, car nous y reviendrons au moment de colorer le panneau : les moustaches fonctionnent dans le contenu textuel d'un élément, pas dans la valeur d'un attribut. L'écriture class="{{ statusClass }}" ne substituera aucune valeur, parce que les attributs empruntent dans Vue un chemin complètement différent.
.value - une seule règle, deux mondes
Puisque ref() renvoie un conteneur et non la valeur elle-même, comment atteindre l'intérieur ? Par la propriété .value. Et c'est ici qu'apparaît la seule règle de Vue que les débutants oublient le plus souvent.
Dans la section <script setup> tu travailles sur le conteneur, donc tu écris .value systématiquement. Dans le template, Vue déballe le conteneur à ta place, donc tu n'écris .value jamais. C'est pour cela que {{ daysRemaining }} a suffi dans le bloc ci-dessus : l'écriture {{ daysRemaining.value }} serait une faute dans un template.
1<script setup>
2import { ref } from 'vue'
3
4const daysRemaining = ref(180)
5
6// le conteneur entier, pas le nombre
7console.log(daysRemaining)
8
9// la valeur rangee a l'interieur du conteneur
10console.log(daysRemaining.value)
11
12// remplacement de la valeur dans le conteneur
13daysRemaining.value = 179
14</script>Le premier console.log affiche l'objet enveloppe ; sa forme exacte dépend de la version de Vue, alors ne t'attache pas à ce que tu verras - l'important est que ce n'est pas un nombre. Le deuxième affiche 180, c'est-à-dire le contenu du conteneur. La ligne la plus intéressante est la dernière : elle remplace la valeur dans le conteneur, et non le conteneur lui-même. La variable daysRemaining désigne toujours le même objet, la liaison avec le template tient sans broncher, et le nombre affiché change pourtant tout seul.
@click - le panneau se met à réagir
Le panneau affiche déjà des données, mais l'officier n'a rien sur quoi cliquer. Il te faut un bouton qui déclenche ton code lorsqu'on l'enfonce - le navigateur appelle cet enfoncement un événement click.
Vue se branche sur les événements avec la directive v-on. Tu écris v-on:click et, après le signe égal, tu donnes le nom de la fonction que Vue doit appeler. Cette écriture est si fréquente qu'elle a reçu un raccourci sous forme d'arobase : @click signifie exactement la même chose que v-on:click. Au NOVA LAB nous utilisons uniquement la forme courte et c'est celle que je te recommande - elle est plus brève, et dans un template dense on voit tout de suite à quel endroit il se passe quelque chose.
Le nom de la fonction se donne sans parenthèses. L'écriture @click="advanceDay" veut dire : voici la fonction, appelle-la quand quelqu'un clique. La fonction elle-même n'est que du JavaScript tout à fait ordinaire, écrit dans <script setup> à côté des variables, et la règle de la section précédente y reste valable : tu lis et tu écris à travers .value. Nous emploierons en plus la fonction intégrée Math.max, qui renvoie la plus grande des valeurs qu'on lui donne - grâce à elle le compte à rebours s'arrêtera à zéro au lieu de descendre en dessous.
1<template>
2 <p>Jours restants : {{ daysRemaining }}</p>
3 <button @click="advanceDay">Jour de mission suivant</button>
4</template>
5
6<script setup>
7import { ref } from 'vue'
8
9const daysRemaining = ref(180)
10
11function advanceDay() {
12 daysRemaining.value = Math.max(0, daysRemaining.value - 1)
13}
14</script>Clique sur le bouton : le compteur baisse d'une unité et continuera de baisser jusqu'à zéro, où il s'immobilisera. Le plus important est pourtant ce qui ne figure pas dans ce code. Il n'y a pas une seule ligne qui irait chercher le paragraphe dans le document pour y remplacer le texte. Il n'y a aucun rafraîchissement du panneau. La fonction advanceDay s'occupe uniquement des données, et le redessin de l'écran est l'affaire de Vue, qui a remarqué tout seul le changement dans le conteneur. Le template n'a pas bougé non plus : {{ daysRemaining }} s'écrit exactement comme à l'époque où le nombre restait figé.
Les écritures d'événements qui ne fonctionneront pas
Un seul chemin mène au bouton dans Vue, et il vaut la peine de comprendre pourquoi les autres sont des impasses.
L'attribut HTML ordinaire onclick="advanceDay()" a l'air familier et constitue techniquement du HTML valide - sauf que c'est le navigateur qui le traite, et non Vue. Le navigateur cherchera la fonction advanceDay parmi les fonctions globales, alors que la tienne vit à l'intérieur du composant et n'existe pas du tout à l'extérieur. Résultat : le clic ne produit rien et une erreur de nom inconnu atterrit dans la console.
L'écriture v-event:click="advanceDay" sonne raisonnable, mais la directive v-event n'existe tout simplement pas dans Vue. La liste des directives est fermée et, à l'intérieur, les événements sont le domaine exclusif de v-on.
L'écriture bind:click="advanceDay" mélange deux outils distincts. Vue possède bien v-bind avec son raccourci en forme de deux-points, mais il sert à lier des attributs et des propriétés, jamais des événements. Retiens ce partage, car il revient dans tous les templates : l'arobase pour les événements, les deux-points pour les attributs.
Une expression à la place d'une fonction
Tous les clics ne méritent pas leur propre fonction. Quand la réaction entière tient en une seule opération, tu peux l'écrire directement dans le template, car @click accepte non seulement un nom de fonction mais aussi une expression JavaScript. La même convention que dans les moustaches s'y applique, donc .value disparaît : tu écris le nom de la variable comme s'il s'agissait d'un nombre ordinaire.
Regarde cela sur le deuxième panneau de la station, le compteur d'énergie, où deux boutons déplacent le niveau de cinq points et un troisième rétablit l'état de départ.
1<template>
2 <p>Energie : {{ energyLevel }}%</p>
3
4 <button @click="energyLevel -= 5">- 5</button>
5 <button @click="energyLevel += 5">+ 5</button>
6 <button @click="resetEnergy">Reset</button>
7</template>
8
9<script setup>
10import { ref } from 'vue'
11
12const energyLevel = ref(50)
13
14function resetEnergy() {
15 energyLevel.value = 50
16}
17</script>Les trois boutons agissent sur le même conteneur energyLevel et les trois rafraîchissent le même paragraphe - cela ne change pas d'une écriture à l'autre. La seule différence tient à l'endroit où habite l'instruction : dans le template pour les deux premiers boutons, dans une fonction pour le troisième.
Laquelle choisir ? Ma recommandation est simple : l'expression dans le template uniquement quand il s'agit d'une opération courte, lisible d'un seul coup d'œil. Tout ce qui comporte une condition, deux étapes ou un nom digne d'être retenu, déplace-le dans une fonction et accroche-la à @click par son nom. Le template doit montrer ce qui se passe, pas cacher la logique de la mission entre les balises.
:class - une classe qui dépend de l'état
Reste le dernier outil du quatuor d'aujourd'hui. Le panneau annonce le statut de la station par une inscription, mais au Centre de Contrôle c'est la couleur qui compte : le vert veut dire calme, le jaune veut dire vérifie. Un attribut class="ok" ordinaire est figé exactement comme l'était tout à l'heure le nombre 180, et il est tout aussi incapable de changer.
Pour les attributs, Vue dispose de la directive v-bind, dont le raccourci est un deux-points posé devant le nom de l'attribut. L'écriture :class dit à Vue : ce qui se trouve à droite n'est pas du texte, c'est une expression JavaScript ; évalue-la et pose le résultat comme classe de l'élément. La version la plus simple consiste à donner le nom d'une variable où tu conserves le nom de la classe.
1<template>
2 <span :class="statusClass">{{ statusLabel }}</span>
3</template>
4
5<script setup>
6import { ref } from 'vue'
7
8const statusClass = ref('ok')
9const statusLabel = ref('TOUS SYSTEMES OK')
10</script>Cela fonctionne, mais le montage a un point faible : deux conteneurs décrivent un seul état et rien ne veille à ce qu'ils restent d'accord. Il suffit que tu changes la classe quelque part en oubliant l'inscription pour que le panneau affiche une alerte en vert. Mieux vaut ne garder qu'une seule vérité, une simple valeur booléenne, et en déduire à la fois la classe et l'inscription. L'opérateur ternaire y suffit, cette écriture bien connue de JavaScript : la condition, un point d'interrogation, la valeur si vrai, deux-points, la valeur si faux.
1<template>
2 <span :class="systemsOk ? 'ok' : 'alerte'">
3 {{ systemsOk ? 'TOUS SYSTEMES OK' : 'ALERTE' }}
4 </span>
5</template>
6
7<script setup>
8import { ref } from 'vue'
9
10const systemsOk = ref(true)
11</script>Un seul conteneur, deux endroits qui s'en servent, et un ensemble toujours cohérent. Remarque que la même expression conditionnelle se tient une fois derrière les deux-points d'un attribut et une fois à l'intérieur des moustaches : c'est la même syntaxe JavaScript employée à deux endroits différents du template. Et rien n'a changé dans la balise <span> elle-même : c'est toujours un élément ordinaire, sauf que sa classe est désormais décidée par l'état de la mission.
Que ne fait pas :class ? Il ne crée aucun style. Il fournit uniquement un nom de classe, et l'apparence reste décrite par du CSS ordinaire - chez nous dans la section <style scoped>, exactement la même que dans la leçon précédente.
1<style scoped>
2.ok { color: #00ff88; }
3.alerte { color: #ffd60a; }
4</style>Deux règles, aucune magie, et voilà tout le secret des classes dynamiques. La directive bascule le nom, le CSS transforme le nom en couleur. Quand la variable systemsOk prendra la valeur faux, Vue retirera de la balise la classe ok, y posera alerte, et le navigateur repeindra l'inscription en jaune. Les règles de la feuille de style, elles, resteront intactes.
Une annonce pour finir : :class accepte aussi une écriture en objet, par exemple :class="{ alerte: !systemsOk }", qui ajoute la classe uniquement lorsque la condition est vraie. Nous y reviendrons au chapitre des directives, quand le panneau aura plus de deux états.
Les écritures de classes qui ne fonctionneront pas
Trois maladresses reviennent régulièrement à cet endroit.
L'écriture class="{{ statusClass }}" est une tentative d'utiliser les moustaches dans un attribut. L'interpolation ne prend en charge que le contenu textuel d'un élément, donc Vue n'évaluera rien ici et ne substituera pas la valeur de la variable. La classe ok n'atteindra jamais l'élément et la couleur n'apparaîtra pas.
L'écriture css-class="statusClass" n'existe ni en HTML ni dans Vue. Le navigateur la traitera comme un attribut inconnu et l'élément restera sans la moindre classe.
L'écriture style:class="statusClass" mélange deux choses. Vue possède certes :style, mais celui-ci pose des styles écrits directement sur l'élément, pas des noms de classes - et style:class n'existe pas du tout. Une classe passe toujours par :class.
Le panneau complet
Tu disposes maintenant des quatre outils, il est donc temps d'en assembler le panneau de statut de mission, celui qui est réellement accroché au Centre de Contrôle. Il affiche le nom de la mission, la phase courante, la distance vers Mars, les jours restants et le statut de la station, et son bouton fait avancer la mission à la phase suivante.
Une nouveauté s'y ajoute, mais elle vient d'en dehors du monde de Vue : un simple tableau JavaScript avec les noms des phases, plus un conteneur qui garde l'indice de la phase courante. Remarque que le tableau phases n'est pas enveloppé dans ref : son contenu ne change jamais, il n'y a donc rien à surveiller. La réactivité a un coût et dans l'espace on n'emporte pas de charge inutile - pose des conteneurs uniquement sur les valeurs qui changent réellement et doivent rafraîchir l'écran. L'opérateur modulo % fait revenir le compteur au début après la dernière phase ; c'est un confort de démonstration, pour pouvoir cliquer en boucle, et non la description d'une vraie mission.
1<template>
2 <div class="mission-status">
3 <header>
4 <h1>{{ missionName }}</h1>
5 <span class="phase">{{ currentPhase }}</span>
6 </header>
7
8 <div class="metrics">
9 <div class="metric">
10 <label>Distance vers Mars</label>
11 <span>{{ distanceToMars }} millions de km</span>
12 </div>
13 <div class="metric">
14 <label>Temps restant</label>
15 <span>{{ daysRemaining }} jours</span>
16 </div>
17 <div class="metric">
18 <label>Statut de la station</label>
19 <span :class="systemsOk ? 'ok' : 'alerte'">
20 {{ systemsOk ? 'TOUS SYSTEMES OK' : 'ALERTE' }}
21 </span>
22 </div>
23 </div>
24
25 <button @click="nextPhase">Phase de mission suivante</button>
26 </div>
27</template>
28
29<script setup>
30import { ref } from 'vue'
31
32const phases = ['Preparation', 'Decollage', 'Vol', 'Orbite de Mars', 'Base Nova']
33
34const missionName = ref('MARS ONE - Premiere Colonie')
35const currentPhase = ref(phases[0])
36const phaseIndex = ref(0)
37const distanceToMars = ref(225)
38const daysRemaining = ref(180)
39const systemsOk = ref(true)
40
41function nextPhase() {
42 phaseIndex.value = (phaseIndex.value + 1) % phases.length
43 currentPhase.value = phases[phaseIndex.value]
44
45 distanceToMars.value = Math.max(0, distanceToMars.value - 45)
46 daysRemaining.value = Math.max(0, daysRemaining.value - 36)
47}
48</script>Clique quelques fois sur le bouton : l'étiquette de phase parcourt les étapes successives, la distance et le compte à rebours diminuent, et tous deux s'arrêtent à zéro. Tout cela sans une seule ligne de code qui toucherait au document. Regarde encore une fois le template : à part les moustaches, un deux-points et une arobase, c'est du HTML ordinaire, le même que tu écris depuis le premier monde. Cela n'a pas changé et ne changera pas : Vue ne remplace pas le HTML, il le branche seulement sur des données.
Le nombre d'endroits où tu décris l'état de la mission n'a pas changé non plus. Il y en a exactement un : la section <script setup>. Le template se contente de montrer cet état, la fonction se contente de le modifier, et Vue veille à ce que l'écran soit toujours d'accord avec les données. Ce partage des rôles t'accompagnera dans tout le monde NOVA LAB, et dans la prochaine leçon tu verras comment on relie de tels modules en une seule application de mission.
Retiens ceci : ref() crée le conteneur, les moustaches le montrent, l'arobase réagit à l'astronaute et les deux-points peignent le panneau selon l'état - voilà le jeu d'outils complet de ton premier système vivant.
Code de cette leçon : src/App.vue
1<template>
2 <div class="nova-lab">
3 <h1>Ton premier composant</h1>
4
5 <section class="intro">
6 <p>
7 Les composants sont les briques de base des applications Vue.
8 Chaque composant est une unité autonome avec son propre template, sa logique et ses styles.
9 </p>
10 </section>
11
12 <section class="demo">
13 <h2>Panneau de contrôle de mission</h2>
14
15 <div class="control-panel">
16 <div class="crew-input">
17 <label>Nom de l'équipage :</label>
18 <input v-model="crewName" placeholder="Saisis un nom..." />
19 </div>
20
21 <div class="mission-date">
22 <label>Date de lancement :</label>
23 <input type="date" v-model="launchDate" />
24 </div>
25
26 <div class="destination">
27 <label>Cible de la mission :</label>
28 <select v-model="destination">
29 <option value="">Sélectionne...</option>
30 <option value="mars">Mars</option>
31 <option value="moon">Lune</option>
32 <option value="europa">Europe (Jupiter)</option>
33 </select>
34 </div>
35 </div>
36
37 <div class="mission-summary" v-if="crewName && launchDate && destination">
38 <h3>Résumé de la mission</h3>
39 <p><strong>Équipage :</strong> {{ crewName }}</p>
40 <p><strong>Date de lancement :</strong> {{ formattedDate }}</p>
41 <p><strong>Cible :</strong> {{ destinationName }}</p>
42 <button @click="launchMission" class="launch-btn">
43 Démarrer la mission !
44 </button>
45 </div>
46 </section>
47 </div>
48</template>
49
50<script setup>
51import { ref, computed } from 'vue'
52
53const crewName = ref('')
54const launchDate = ref('')
55const destination = ref('')
56
57const formattedDate = computed(() => {
58 if (!launchDate.value) return ''
59 return new Date(launchDate.value).toLocaleDateString('fr-FR', {
60 year: 'numeric',
61 month: 'long',
62 day: 'numeric'
63 })
64})
65
66const destinationNames = {
67 mars: 'Mars - La planète rouge',
68 moon: 'Lune - Base Artemis',
69 europa: 'Europe - Lune de Jupiter'
70}
71
72const destinationName = computed(() => destinationNames[destination.value] || '')
73
74function launchMission() {
75 alert(`Mission "${crewName.value}" démarrée !\nCible : ${destinationName.value}\nLancement : ${formattedDate.value}`)
76}
77</script>
78
79<style>
80.nova-lab {
81 min-height: 100vh;
82 background: #0a0e27;
83 color: #e0e0e0;
84 padding: 2rem;
85 font-family: system-ui, sans-serif;
86}
87
88h1 {
89 color: #00ff88;
90 text-align: center;
91}
92
93section {
94 background: rgba(26, 30, 55, 0.8);
95 border: 1px solid #00b4d8;
96 border-radius: 12px;
97 padding: 1.5rem;
98 margin: 1.5rem auto;
99 max-width: 600px;
100}
101
102h2 {
103 color: #00b4d8;
104 margin-top: 0;
105}
106
107.control-panel {
108 display: flex;
109 flex-direction: column;
110 gap: 1rem;
111}
112
113.control-panel label {
114 display: block;
115 color: #00ff88;
116 margin-bottom: 0.25rem;
117 font-size: 0.9rem;
118}
119
120.control-panel input,
121.control-panel select {
122 width: 100%;
123 padding: 0.75rem;
124 background: #1a1e37;
125 border: 2px solid #00b4d8;
126 border-radius: 8px;
127 color: #fff;
128 font-size: 1rem;
129}
130
131.control-panel input:focus,
132.control-panel select:focus {
133 outline: none;
134 border-color: #00ff88;
135}
136
137.mission-summary {
138 margin-top: 1.5rem;
139 padding: 1rem;
140 background: rgba(0, 255, 136, 0.1);
141 border-radius: 8px;
142 border: 1px solid #00ff88;
143}
144
145.mission-summary h3 {
146 color: #00ff88;
147 margin-top: 0;
148}
149
150.launch-btn {
151 width: 100%;
152 padding: 1rem;
153 margin-top: 1rem;
154 background: linear-gradient(135deg, #00b4d8, #00ff88);
155 border: none;
156 border-radius: 8px;
157 color: #0a0e27;
158 font-size: 1.1rem;
159 font-weight: bold;
160 cursor: pointer;
161 transition: transform 0.2s, box-shadow 0.2s;
162}
163
164.launch-btn:hover {
165 transform: translateY(-2px);
166 box-shadow: 0 4px 20px rgba(0, 255, 136, 0.4);
167}
168</style>Tu as repéré une erreur dans cette leçon ?
Teste tes connaissances
Réponds aux questions de cette leçon. Choisis une réponse pour voir tout de suite si elle est correcte.
1. À quoi sert la fonction ref() dans Vue 3 ?
2. Comment gère-t-on un événement de clic sur un bouton dans un template Vue ?
3. Comment assigne-t-on dynamiquement une classe CSS dans Vue ?
Tâches pratiques dans le jeu
- Éditeur de code
Complète le composant avec ref() pour le nom de la mission et le nombre de jours. Affiche-les dans le template à l'aide de {{ }}.
- Tri horizontal
Ordonne la syntaxe de création d'une variable réactive avec ref() :
- Éditeur de code
Crée un compteur avec des boutons + et - en utilisant @click et ref(). Affiche la valeur actuelle.