Cours Vue.js · Module 1: Vue et Vite

Single File Components - Les modules du système

6 min de lecture
Dans cette leçon5

Au NOVA LAB, chaque module du vaisseau est une unité autonome - il a sa propre alimentation, sa logique et son boîtier. De la même façon, un Single File Component de Vue réunit template, script et style dans un seul fichier.

Sur un site classique, l'apparence d'un panneau vit dans un fichier HTML, son comportement dans un fichier JavaScript et ses couleurs dans une feuille CSS. Pour corriger un seul indicateur, tu sautes d'un fichier à l'autre, et une règle CSS écrite pour un panneau peut repeindre un autre panneau par accident. Un Single File Component, SFC en abrégé, enferme tout le module dans un seul fichier avec l'extension .vue.

Anatomie d'un module .vue

Le navigateur ne sait pas ouvrir un tel fichier - le plugin Vue configuré dans le moteur Vite le compile en JavaScript et en CSS ordinaires. Démontons maintenant un panneau de survie. Les trois blocs de code ci-dessous se trouvent dans un seul fichier, l'un sous l'autre.

Les trois sections d'un module

1. <template> - L'interface utilisateur

  • Définit ce que voit l'astronaute
  • Utilise la syntaxe Vue (directives, interpolation)
  • Doit être clair - en situation de crise, pas le temps de chercher

La première section est le template : du HTML ordinaire enrichi de la syntaxe Vue, c'est-à-dire des moustaches et des attributs spéciaux précédés d'un deux-points ou d'une arobase :

1<template>
2  <!-- INTERFACE - ce que voit l'astronaute -->
3  <div class="life-support-panel">
4    <h1>{{ systemName }}</h1>
5    <p>Niveau d'oxygène : {{ oxygenLevel }}%</p>
6    <div class="status" :class="statusClass">{{ status }}</div>
7  </div>
8</template>

Les moustaches affichent le nom du système, le niveau d'oxygène et le statut, tandis que :class="statusClass" attache à l'élément une classe calculée dans le script - nous l'étudierons en détail dans la prochaine leçon. Les balises <div>, <h1> et <p> sont toujours le même HTML que tu connais depuis le premier monde.

2. <script setup> - La logique du système

  • Syntaxe moderne de la Composition API
  • Les variables, fonctions et imports du niveau supérieur sont disponibles tout de suite dans le template
  • Réactivité avec Vue

La deuxième section contient les données et la logique. En plus du ref() que tu connais déjà, on y trouve la fonction computed(), que l'on importe elle aussi depuis le paquet vue :

1<script setup>
2// LOGIQUE - comment fonctionne le système
3import { ref, computed } from 'vue'
4
5const systemName = ref('Système de survie')
6const oxygenLevel = ref(98.5)
7
8const status = computed(() =>
9  oxygenLevel.value > 90 ? 'OPTIMAL' : 'ALERTE'
10)
11
12const statusClass = computed(() =>
13  oxygenLevel.value > 90 ? 'status-ok' : 'status-warning'
14)
15</script>

La fonction computed() crée une valeur calculée. Tu lui passes une fonction fléchée, et Vue mémorise le résultat et le recalcule tout seul chaque fois que oxygenLevel change. Le niveau d'oxygène reste un conteneur ref ordinaire - status ne le modifie pas, il en découle seulement. Dans le script, tu lis le résultat avec status.value, et dans le template {{ status }} suffit.

3. <style scoped> - L'apparence du panneau

  • CSS propre au module
  • scoped isole les styles - un module ne casse pas l'autre
  • Fond sombre, accents lumineux - le standard spatial

La troisième section décrit l'apparence du panneau. L'attribut scoped fait en sorte que les règles écrites ici ne s'appliquent qu'à l'intérieur de ce composant :

1<style scoped>
2/* APPARENCE - à quoi ressemble le panneau */
3.life-support-panel {
4  background: #0a1628;
5  border: 2px solid #00ff88;
6  border-radius: 8px;
7  padding: 1.5rem;
8  color: #e0e0e0;
9}
10
11.status-ok { color: #00ff88; }
12.status-warning { color: #ffaa00; }
13</style>

Vue ajoute aux éléments du composant un attribut unique comme data-v-7ba5bd90 et le reporte dans les sélecteurs, donc une classe .status-ok d'un autre module n'entrera pas en collision avec celle-ci. Sans scoped, les mêmes règles s'appliqueraient à toute la page.

L'ordre des sections

Vue n'impose pas l'ordre des blocs. Le guide de style officiel recommande seulement qu'il soit cohérent dans tout le projet, avec <style> en dernier - c'est pourquoi l'assistant create-vue place <script setup> en haut, alors que beaucoup d'équipes commencent par <template>. Au NOVA LAB, nous écrivons dans l'ordre <template>, <script setup>, <style scoped> : d'abord ce que voit l'astronaute, ensuite le câblage, et le boîtier en dernier. Un fichier peut avoir au plus un <template> et un <script setup>, mais autant de blocs <style> que tu veux.

Une fonction derrière un bouton

Un module qui ne fait qu'afficher des relevés n'est qu'une moitié de système. Dans <script setup>, tu peux aussi déclarer une fonction ordinaire et l'attacher à un bouton dans le template avec l'attribut @click. Regarde-le sur le module de refroidissement du réacteur :

1<template>
2  <p>Température du réacteur : {{ reactorTemp }}°C</p>
3  <p>État : {{ coolingStatus }}</p>
4  <button @click="coolDown">Refroidir de 5°C</button>
5</template>
6
7<script setup>
8import { ref, computed } from 'vue'
9
10const reactorTemp = ref(95)
11
12const coolingStatus = computed(() => {
13  if (reactorTemp.value >= 90) return 'CRITIQUE'
14  if (reactorTemp.value >= 70) return 'SURCHAUFFE'
15  return 'NORMAL'
16})
17
18function coolDown() {
19  reactorTemp.value -= 5
20}
21</script>

Un clic lance coolDown, qui baisse la température via .value. Vue remarque le changement, computed recalcule l'état, et les deux paragraphes se rafraîchissent tout seuls. La fonction fléchée dans computed peut avoir des accolades et plusieurs instructions if - c'est le premier résultat correspondant qui est renvoyé. Nous démonterons la gestion des événements en détail dans la prochaine leçon.

<script setup> contre l'ancienne syntaxe

La Composition API a deux formes d'écriture. La plus ancienne exige d'exporter un objet avec une fonction setup(), qui doit à la fin renvoyer tout ce qu'utilise le template :

1<!-- NOUVEAU PROTOCOLE (recommandé) -->
2<script setup>
3import { ref } from 'vue'
4const pressure = ref(101.3)
5</script>
6
7<!-- ANCIEN PROTOCOLE (legacy) -->
8<script>
9import { ref } from 'vue'
10export default {
11  setup() {
12    const pressure = ref(101.3)
13    return { pressure }
14  }
15}
16</script>

<script setup> est du sucre syntaxique que le compilateur transforme justement en cette fonction setup(), donc les variables n'ont pas besoin d'un return manuel. L'ancienne forme n'a pas été supprimée, et tu la croiseras dans des projets plus anciens. Au NOVA LAB, nous utilisons exclusivement le nouveau protocole - il est plus court, plus rapide à l'exécution et fonctionne mieux avec TypeScript - et c'est ce que je te recommande dès ton premier fichier.

Dans l'éditeur ci-dessous, App.vue affiche trois cartes SystemCard. Ouvre le fichier components/SystemCard.vue et retrouve-y les trois sections. La carte reçoit ses données via defineProps - tu découvriras ce canal de communication à la Station de Communication.

Retiens ceci : un fichier .vue est un module de station complet - le template est le panneau, <script setup> le câblage, et <style scoped> le boîtier qui ne laisse pas les styles fuir vers les voisins.

Code de cette leçon : src/App.vue
1<template>
2  <div class="nova-lab">
3    <h1>Single File Components (SFC)</h1>
4
5    <section class="sfc-demo">
6      <h2>Structure d'un composant .vue</h2>
7      <div class="structure">
8        <div class="part template">
9          <h3>&lt;template&gt;</h3>
10          <p>Structure HTML du composant</p>
11        </div>
12        <div class="part script">
13          <h3>&lt;script setup&gt;</h3>
14          <p>Logique JavaScript/TypeScript</p>
15        </div>
16        <div class="part style">
17          <h3>&lt;style scoped&gt;</h3>
18          <p>Styles CSS uniquement pour ce composant</p>
19        </div>
20      </div>
21    </section>
22
23    <section class="example">
24      <h2>Exemple : Carte système</h2>
25      <SystemCard
26        name="Générateur d'oxygène Alpha"
27        status="operational"
28        :power="85"
29      />
30      <SystemCard
31        name="Recycleur d'eau Beta"
32        status="warning"
33        :power="45"
34      />
35      <SystemCard
36        name="Réacteur plasma"
37        status="critical"
38        :power="12"
39      />
40    </section>
41  </div>
42</template>
43
44<script setup>
45import SystemCard from './components/SystemCard.vue'
46</script>
47
48<style>
49.nova-lab {
50  min-height: 100vh;
51  background: #0a0e27;
52  color: #e0e0e0;
53  padding: 2rem;
54  font-family: system-ui, sans-serif;
55}
56
57h1 {
58  color: #00ff88;
59  text-align: center;
60}
61
62section {
63  background: rgba(26, 30, 55, 0.8);
64  border: 1px solid #00b4d8;
65  border-radius: 12px;
66  padding: 1.5rem;
67  margin: 1.5rem auto;
68  max-width: 800px;
69}
70
71h2 {
72  color: #00b4d8;
73  margin-top: 0;
74}
75
76.structure {
77  display: flex;
78  flex-direction: column;
79  gap: 1rem;
80}
81
82.part {
83  padding: 1rem;
84  border-radius: 8px;
85}
86
87.part h3 {
88  margin: 0 0 0.5rem 0;
89  font-family: monospace;
90}
91
92.part p {
93  margin: 0;
94  font-size: 0.9rem;
95}
96
97.template { background: rgba(0, 255, 136, 0.2); border-left: 4px solid #00ff88; }
98.script { background: rgba(0, 180, 216, 0.2); border-left: 4px solid #00b4d8; }
99.style { background: rgba(255, 170, 0, 0.2); border-left: 4px solid #ffaa00; }
100
101.example {
102  display: flex;
103  flex-direction: column;
104  gap: 1rem;
105}
106</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. 1. Qu'est-ce qu'un SFC (Single File Component) dans Vue.js ?

  2. 2. De quelles trois sections un fichier .vue est-il composé ?

  3. 3. Que fait l'attribut « scoped » dans la section <style scoped> ?

Tâches pratiques dans le jeu

  • Éditeur de code

    Complète un Single File Component avec une section template (titre h1), un script setup (variable ref) et un style scoped.

  • Tri vertical

    Ordonne les sections d'un fichier .vue dans l'ordre utilisé au NOVA LAB :

  • Clique dans l'ordre

    Ordonne la structure correcte d'une section script setup avec une variable réactive :

  • Éditeur de code

    Crée un composant de panneau système avec un template affichant des données, un script setup avec ref() et computed(), et un style scoped.