1. Qu'est-ce que Vue 3 ?

Vue.js est un framework JavaScript progressif créé par Evan You en 2014 et dont la version 3 est sortie en septembre 2020. L'adjectif progressif signifie qu'on peut l'adopter progressivement : d'un simple script CDN sur une page existante jusqu'à une SPA (Single-Page Application) complète avec Vue Router et Pinia.

Vue 3 repose sur trois piliers : un système de réactivité basé sur les Proxy ES6, un Virtual DOM efficace, et une API de composition puissante introduite dans cette version.

Comparaison React / Angular / Vue

Critère React Angular Vue 3
Type Bibliothèque UI Framework complet Framework progressif
Courbe d'apprentissage Modérée Élevée Faible
Templates JSX HTML enrichi HTML enrichi
Taille bundle ~40 Ko ~130 Ko ~34 Ko

Le pattern MVVM

Vue suit le pattern MVVM (Model-View-ViewModel) :

  • Model : les données (état réactif — data() ou ref())
  • View : le template HTML affiché dans le navigateur
  • ViewModel : Vue lui-même — il synchronise automatiquement Model ↔ View

Virtual DOM

Vue maintient en mémoire une représentation légère du DOM appelée Virtual DOM. À chaque changement d'état, Vue calcule la différence (diff) entre l'ancien et le nouveau Virtual DOM, puis applique uniquement les modifications nécessaires au vrai DOM. Résultat : des mises à jour ultra-rapides sans re-rendu complet de la page.

// Sans Virtual DOM (manipulation DOM directe — lent)
document.getElementById('count').textContent = compteur;

// Avec Vue (Virtual DOM — rapide et déclaratif)
// Vue s'occupe de tout : on déclare QUOI afficher, pas COMMENT
<p>{{ compteur }}</p>
✅ Vue 3 est le framework le plus accessible pour débuter tout en étant suffisamment puissant pour des applications de production.

2. Installation : CDN vs Vite

Option A — CDN (démarrage instantané)

La façon la plus rapide : un simple tag <script>. Idéal pour apprendre, tester ou enrichir une page HTML existante.

<!DOCTYPE html>
<html lang="fr">
<head>
  <title>Mon appli Vue</title>
</head>
<body>
  <div id="app">
    <h1>{{ message }}</h1>
  </div>

  <!-- Vue 3 via CDN -->
  <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
  <script>
    const { createApp } = Vue;

    createApp({
      data() {
        return {
          message: 'Bonjour Vue 3 !'
        };
      }
    }).mount('#app');
  </script>
</body>
</html>
💡 Vue.global.js expose un objet global Vue. On destructure ce dont on a besoin : const { createApp, ref, computed } = Vue;

Option B — Vite (projet professionnel)

Pour un vrai projet avec composants .vue, routing, tests et build optimisé :

# Créer un projet Vue 3 avec Vite
npm create vue@latest mon-projet
cd mon-projet
npm install
npm run dev

Vite offre un démarrage en < 300 ms et le Hot Module Replacement (HMR) instantané.

createApp() et mount()

createApp(options) crée une instance d'application Vue. .mount(selector) relie cette instance à un élément du DOM. Tout ce qui est à l'intérieur de cet élément devient le template Vue.

import { createApp } from 'vue'; // Avec Vite
// — ou —
const { createApp } = Vue; // Avec CDN

const app = createApp({
  data() {
    return { titre: 'Mon App' };
  }
});

// Montage sur l'élément #app
app.mount('#app');

// On peut aussi chaîner directement :
createApp({ data() { return { n: 0 }; } }).mount('#app');
⚠️ Un seul mount() par createApp(). Pour plusieurs apps indépendantes sur la même page, créer plusieurs instances createApp().

3. Options API vs Composition API

Vue 3 propose deux façons d'écrire la logique d'un composant. Elles coexistent et sont interopérables.

Options API

Approche classique (Vue 2). La logique est organisée en options : data, methods, computed, watch, etc.

createApp({
  // État réactif
  data() {
    return {
      compteur: 0,
      nom: 'Alice'
    };
  },

  // Méthodes
  methods: {
    incrementer() {
      this.compteur++;
    },
    saluer() {
      return `Bonjour ${this.nom}`;
    }
  },

  // Propriétés calculées
  computed: {
    compteurDouble() {
      return this.compteur * 2;
    }
  },

  // Observateurs
  watch: {
    compteur(nouvelleVal) {
      console.log('Compteur changé :', nouvelleVal);
    }
  }
}).mount('#app');
✅ Options API est excellente pour débuter : la structure imposée guide le développeur.

Composition API

Introduite dans Vue 3. La logique est regroupée par fonctionnalité plutôt que par type. On utilise la fonction setup().

const { createApp, ref, computed, watch } = Vue;

createApp({
  setup() {
    // État réactif avec ref()
    const compteur = ref(0);
    const nom = ref('Alice');

    // Méthode (simple fonction)
    function incrementer() {
      compteur.value++;
    }

    // Propriété calculée
    const compteurDouble = computed(() => compteur.value * 2);

    // Observateur
    watch(compteur, (nouvelleVal) => {
      console.log('Compteur changé :', nouvelleVal);
    });

    // TOUT doit être retourné pour être accessible dans le template
    return { compteur, nom, incrementer, compteurDouble };
  }
}).mount('#app');

Quand utiliser laquelle ?

Options API
  • ✅ Débutants Vue
  • ✅ Composants simples
  • ✅ Migration depuis Vue 2
  • ✅ Équipes sans TypeScript
Composition API
  • ✅ Projets complexes
  • ✅ Logique réutilisable (composables)
  • ✅ TypeScript
  • ✅ Vue 3 idiomatic
💡 Dans cette formation, nous utilisons les deux. Les modules V01–V02 montrent l'Options API, V03+ bascule sur la Composition API.

4. Template syntax : interpolation et attributs dynamiques

Le template Vue est du HTML enrichi de syntaxes spéciales que Vue compile en rendu optimisé.

Interpolation de texte {{ }}

Les double accolades {{ }} affichent la valeur d'une expression JavaScript :

<!-- Variables -->
<p>Bonjour {{ prenom }} {{ nom }} !</p>

<!-- Expressions JS (simples) -->
<p>Total : {{ prix * quantite }} €</p>
<p>{{ estConnecte ? 'Connecté' : 'Déconnecté' }}</p>
<p>{{ texte.toUpperCase() }}</p>

<!-- NE PAS faire : pas de déclarations, boucles ou if -->
<!-- <p>{{ let x = 1 }}</p> ← ERREUR -->
⚠️ Les accolades ne fonctionnent que dans le contenu textuel, pas dans les attributs HTML.

v-html — rendu HTML brut

Pour injecter du HTML, utiliser la directive v-html (avec précaution — risque XSS avec données utilisateurs) :

<div v-html="contenuHtml"></div>

<!-- Dans data() : -->
<!-- contenuHtml: '<strong>Texte en gras</strong>' -->

Attributs dynamiques avec v-bind (:)

Pour lier un attribut HTML à une expression JavaScript, on utilise v-bind: ou son raccourci : :

<!-- Forme longue -->
<img v-bind:src="urlImage" v-bind:alt="descriptionImage">

<!-- Forme courte (recommandée) -->
<img :src="urlImage" :alt="descriptionImage">
<a :href="lienUrl" :target="ouvrirNouvelOnglet ? '_blank' : '_self'">Lien</a>
<button :disabled="chargement">Envoyer</button>
<div :class="classeDynamique" :style="{ color: couleur }"></div>

<!-- Lier plusieurs attributs d'un coup -->
<img v-bind="{ src: urlImage, alt: 'Photo', width: 300 }">

Exemple complet

<div id="app">
  <h1>{{ titre }}</h1>
  <img :src="avatar" :alt="'Photo de ' + utilisateur">
  <p>Score : {{ score * 10 }} points</p>
  <a :href="profilUrl">{{ utilisateur }}</a>
</div>

<script>
const { createApp } = Vue;
createApp({
  data() {
    return {
      titre: 'Profil joueur',
      utilisateur: 'GameMaster',
      avatar: 'https://picsum.photos/80',
      score: 42,
      profilUrl: '/profil/gamemaster'
    };
  }
}).mount('#app');
</script>
{{ }} pour le texte, : pour les attributs. Retenir cette règle évite 90% des erreurs de débutants.

5. Directives essentielles : v-bind, v-on, v-model

Les directives sont des attributs spéciaux préfixés par v- qui appliquent un comportement réactif à un élément DOM.

v-bind — liaison de données → DOM

<!-- Raccourci : -->
<button :class="{ actif: estActif, desactive: !estActif }">Cliquez</button>
<input :type="typeInput" :placeholder="indicateur" :maxlength="limite">
<div :style="{ backgroundColor: couleur, fontSize: taille + 'px' }"></div>

v-on — écouter les événements DOM → données

<!-- Forme longue -->
<button v-on:click="compteur++">+1</button>

<!-- Raccourci @ (recommandé) -->
<button @click="incrementer">+1</button>
<button @click="ajouter(5)">+5</button>
<input @keyup.enter="envoyer">
<form @submit.prevent="soumettreFormulaire">...</form>

<!-- Accéder à l'événement natif -->
<button @click="gererClic($event)">Clic</button>

v-model — liaison bidirectionnelle

v-model combine :value + @input en un seul attribut. C'est la magie de Vue pour les formulaires.

<!-- Ces deux formes sont équivalentes : -->
<input :value="nom" @input="nom = $event.target.value">
<input v-model="nom"> <!-- ← beaucoup plus concis ! -->

<!-- Exemples variés -->
<input v-model="prenom" placeholder="Votre prénom">
<textarea v-model="message"></textarea>
<input type="checkbox" v-model="acceptCGU">
<input type="range" v-model="volume">
<select v-model="pays">
  <option value="fr">France</option>
  <option value="be">Belgique</option>
</select>

Exemple synthèse — App complète

<div id="app">
  <input v-model="prenom" placeholder="Votre prénom">
  <p>Bonjour {{ prenom || 'inconnu' }} !</p>
  <button @click="compteur++">Clics : {{ compteur }}</button>
  <p :style="{ color: compteur > 5 ? '#42b883' : '#f85149' }">
    {{ compteur > 5 ? '🎉 Super !' : 'Continue...' }}
  </p>
</div>

<script>
const { createApp } = Vue;
createApp({
  data() {
    return {
      prenom: '',
      compteur: 0
    };
  }
}).mount('#app');
</script>
✅ Mémo rapide : v-bind / : → données vers HTML | v-on / @ → HTML vers données | v-model → les deux en même temps.
📝 Exercices V01 ▶ Mini-projet 🧠 QCM V01 Suivant → V02