Vue-Js
Junior
Quiz-Vuejs-Junior
Composition-Api
Ref
Reactive
Computed
Watchers
Pinia
Lifecycle-Hooks
Questions-Entretien-Vuejs-Junior
Qcm-Vuejs-Junior
Vue-3
Front-End
📝
Entretien Vue Junior : Composition API et Pinia
20 questions Vue.js niveau junior : Composition API, ref, reactive, computed, watchers, Pinia store, lifecycle hooks et props/emits avancés pour entretien.
Banque de révision : les 30 questions corrigées
Voici l'intégralité des 30 questions de « Entretien Vue Junior : Composition API et Pinia », chacune avec sa bonne réponse et son explication. Le quiz interactif ci-dessus en tire une sélection aléatoire à chaque tentative — utilisez cette liste complète pour réviser.
Explication :
ref() crée une référence réactive pour tout type (primitif ou objet), accessible via .value dans le script. reactive() ne fonctionne qu'avec des objets (pas de primitives) et est accessible directement sans .value. Les refs sont "déballées" automatiquement dans le template.
Préférez
ref() par défaut. reactive() a des limitations (pas de remplacement d'objet entier, pas de destructuring).
Explication :
Un composable est une fonction (par convention préfixée
use) qui utilise la Composition API pour encapsuler et réutiliser de la logique réactive entre composants. Exemple : useFetch(), useLocalStorage(), useMouse().
Les composables remplacent les mixins de Vue 2. Contrairement aux mixins, ils sont explicites, typables, et évitent les conflits de noms.
Explication :
Vue 3 utilise les Proxies JavaScript pour la réactivité (contre
Object.defineProperty dans Vue 2). Cela permet de détecter l'ajout/suppression de propriétés et les changements d'index de tableau, limitations de Vue 2.
Grâce aux Proxies,
reactive() détecte maintenant array[0] = newValue et obj.newProp = value, ce qui était impossible avec Vue 2.
Explication :
computed() retourne une valeur calculée (comme une propriété dérivée), utilisée dans le template. watchEffect() exécute une fonction avec effets de bord (appels API, logs, manipulation DOM) quand ses dépendances changent, sans retourner de valeur.
Utilisez
computed() pour des valeurs à afficher. Utilisez watchEffect() pour synchroniser avec le localStorage, logger, ou faire des appels API automatiques.
Explication :
On crée un composable
useDebounce(ref, delay) qui utilise watch() et setTimeout/clearTimeout. Ou on utilise une bibliothèque comme VueUse qui fournit useDebounceFn() et refDebounced().
VueUse est la bibliothèque incontournable de composables pour Vue.js.
refDebounced(maRef, 500) fait tout le travail pour vous.
Explication :
Par défaut,
watch() ne surveille que les changements de référence. Avec { deep: true }, il surveille récursivement toutes les propriétés imbriquées. Attention : peut être coûteux pour de grands objets.
Pour surveiller une propriété spécifique d'un objet réactif, utilisez un getter :
watch(() => obj.prop.nested, callback). C'est plus efficace que deep: true.
Explication :
provide() (dans un ancêtre) et inject() (dans un descendant) permettent de partager des données sans les passer explicitement via des props à chaque niveau. Idéal pour les thèmes, la locale, les configurations.
Pour rendre une valeur fournie réactive, passez une ref ou un computed à
provide(). Ou utilisez provide(key, () => reactiveValue).
Explication :
Avec
<script setup lang="ts">, on peut typer les props : const props = defineProps<{ titre: string; count?: number }>(). On peut aussi utiliser une interface séparée : interface Props { titre: string } defineProps<Props>().
Pour des valeurs par défaut avec TypeScript :
withDefaults(defineProps<Props>(), { count: 0 }).
Explication :
Une directive s'enregistre avec
app.directive("focus", { mounted(el) { el.focus() } }). Les hooks de directive (created, mounted, updated, unmounted) reçoivent l'élément, le binding et le vnode. Utilisable via v-focus.
Les directives sont à utiliser pour de la manipulation DOM bas niveau. Pour de la logique métier, préférez les composants ou les composables.
Explication :
<Suspense> est un composant intégré qui gère l'état de chargement des composants asynchrones. #default contient le(s) composant(s) asynchrone(s), #fallback est affiché pendant le chargement. <Suspense> est encore expérimental dans Vue 3. Il est principalement utilisé avec defineAsyncComponent() et les composants avec async setup().
Explication :
Optimisations clés : 1) Toujours fournir un
:key unique et stable (pas l'index). 2) Ne pas combiner v-if et v-for sur le même élément. 3) Utiliser un computed pour filtrer/trier plutôt que des méthodes. 4) Pour les très longues listes, utiliser la virtualisation (vue-virtual-scroller).
Le
:key permet à Vue de réutiliser les éléments existants et d'éviter de recréer le DOM inutilement.
Explication :
defineAsyncComponent() permet de charger un composant uniquement quand il est nécessaire. On peut configurer un composant de chargement, un composant d'erreur, et un délai.
Pour le lazy loading de routes, utilisez directement
component: () => import("./Page.vue") dans la configuration de Vue Router.
Explication :
VueUse est la bibliothèque incontournable de composables Vue.js. Elle fournit des fonctions prêtes à l'emploi pour : la souris (
useMouse), le stockage (useLocalStorage), les requêtes (useFetch), le debounce, le dark mode, etc.
Avant de créer un composable, vérifiez si VueUse ne l'a pas déjà.
npm install @vueuse/core.
Explication :
<Transition> anime un élément unique (entrée/sortie). <TransitionGroup> anime les listes. Vue applique automatiquement les classes (v-enter-from, v-enter-active, v-leave-to) selon le timing.
Nommez vos transitions pour les cibler en CSS :
<Transition name="fade"> → classes .fade-enter-active.
Explication :
Structure recommandée :
src/ → features/ (par domaine métier), shared/ (composants UI génériques), composables/ (logique réutilisable), stores/ (Pinia), router/ (routes), api/ (appels HTTP).
Chaque dossier
feature peut contenir ses propres composants, composables, tests et types, comme un mini-module.
Explication :
<KeepAlive> enveloppe des composants dynamiques et les garde en mémoire (cache) quand ils ne sont pas affichés. L'état est préservé, le composant n'est pas détruit/reconstruit. Idéal pour les onglets.
Avec Vue Router :
<RouterView v-slot="{ Component }"><KeepAlive><component :is="Component" /></KeepAlive></RouterView>.
Explication :
Vitest (recommandé, rapide, compatible Vite) + @vue/test-utils pour monter les composants, simuler des interactions et vérifier le DOM. Pour l'E2E : Playwright ou Cypress.
Vitest est le framework de test recommandé pour les projets Vue 3 avec Vite. Configuration minimale, hot reload des tests.
Explication :
On peut créer un composable stateful : déclarer une
ref() ou reactive() en dehors de la fonction composable. Tous les composants qui appellent ce composable partagent la même instance réactive.
C'est un "mini-store" sans dépendance. Pour du partage simple entre composants proches, c'est plus léger que Pinia.
Explication :
Vue 3 est modulaire : les API sont des exports nommés (
import { ref, computed } from "vue"). Le bundler (Vite/Webpack) élimine les fonctions non utilisées du bundle final, réduisant sa taille.
Contrairement à Vue 2 où
Vue.nextTick() tirait tout l'objet Vue, Vue 3 permet import { nextTick } from "vue" pour n'inclure que ce qui est utilisé.
Explication :
app.config.errorHandler = (err, instance, info) => { ... } capture les erreurs de rendu et de watchers. On peut aussi utiliser le hook onErrorCaptured() dans un composant parent pour une boundary d'erreur locale.
Combinez
errorHandler avec un service de logging (Sentry, Datadog) pour tracer les erreurs en production.
Explication :
vue-i18n est la solution officielle. On définit des fichiers de messages par langue, on configure la locale, et on utilise
$t("cle.traduction") dans les templates ou useI18n() dans le script.
Pour le lazy loading des traductions : chargez les fichiers de langue à la demande avec
import() pour ne pas alourdir le bundle initial.
Explication :
On peut avoir plusieurs
v-model nommés : <Composant v-model:titre="titre" v-model:contenu="contenu" />. Le composant déclare defineProps(["titre", "contenu"]) et émet emit("update:titre", val) et emit("update:contenu", val).
Avec
defineModel() (Vue 3.4+) : const titre = defineModel("titre") et const contenu = defineModel("contenu"). Simple et élégant.
Explication :
Pinia est écrit en TypeScript et offre une excellente inférence.
const useStore = defineStore("main", () => { const count = ref<number>(0); return { count } }). Les types sont inférés automatiquement à l'utilisation.
Avec la syntaxe Setup Store (fonction), l'inférence TypeScript est parfaite. C'est la syntaxe recommandée pour les nouveaux projets.
Explication :
Le SSR exécute Vue.js sur le serveur pour générer du HTML complet avant de l'envoyer au navigateur. Nuxt est le framework qui facilite le SSR avec Vue.js. Avantages : SEO, performance perçue, preview sur réseaux sociaux.
Si vous avez besoin de SSR, utilisez Nuxt plutôt que d'implémenter le SSR manuellement. Nuxt gère le routage, le data fetching et l'hydratation.
Explication :
Navigation Guards :
router.beforeEach((to, from, next) => { ... }) pour la vérification globale (authentification). beforeEnter dans la définition de route. onBeforeRouteUpdate dans le composant.
Pour vérifier l'authentification, utilisez
beforeEach et redirigez vers /login si le token est absent. Stockez le token dans un store Pinia.
Explication :
<component :is="composantActif" /> permet de changer dynamiquement le composant affiché selon une variable. composantActif peut être un nom de composant enregistré ou un objet composant importé.
Combiné avec
<KeepAlive>, les composants dynamiques gardent leur état quand on passe de l'un à l'autre.
Explication :
FormKit (solution tout-en-un : génération, validation, style) et VeeValidate (validation puissante avec Zod/Yup) sont les solutions de référence. Elles gèrent la validation conditionnelle, les champs dépendants, et les messages d'erreur.
Pour la validation, Zod est recommandé car il s'intègre parfaitement avec TypeScript et offre l'inférence de types.
Explication :
unplugin-vue-components scanne les templates et importe automatiquement les composants. Plus besoin d'écrire
import MonBouton from "./MonBouton.vue". Compatible avec les bibliothèques UI (Naive UI, Ant Design Vue, PrimeVue).
Configuration minimale dans
vite.config.js. Pour les bibliothèques UI, il existe des resolvers dédiés (ex: NaiveUiResolver).
Explication :
Vue DevTools (extension Chrome/Firefox) permet d'inspecter les composants, l'état Pinia, les événements, le routeur, et la timeline de performance. Dans VSCode, les breakpoints JavaScript fonctionnent normalement.
La nouvelle Vue DevTools (v7+) est une application standalone qui fonctionne aussi avec les applications en production et les apps mobiles.
Explication :
L'attribut
scoped dans <style scoped> fait que Vue ajoute un attribut unique (data-v-xxxxx) aux éléments du composant et modifie les sélecteurs CSS en conséquence. Le style ne s'applique qu'au composant.
Pour styler un composant enfant depuis le parent avec scoped, utilisez
:deep(.classe-enfant) { ... }.