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()ouref()) - 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>
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');
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');
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 ?
- ✅ Débutants Vue
- ✅ Composants simples
- ✅ Migration depuis Vue 2
- ✅ Équipes sans TypeScript
- ✅ Projets complexes
- ✅ Logique réutilisable (composables)
- ✅ TypeScript
- ✅ Vue 3 idiomatic
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 -->
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>