Préparation d'entretien 100% Gratuit angularforall.com

Entretien Vue Junior : Composition API et Pinia

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
Junior 🔀 Mixte 20 questions ⏱ 15 min
📝

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.

20 questions ⏱ ~15 min Niveau Junior

Partager

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.

  • ref() est pour les valeurs primitives et les objets, avec .value dans le script ; reactive() est uniquement pour les objets, sans .value (bonne réponse)
  • ref() est plus rapide que reactive()
  • reactive() est déprécié
  • Il n'y a pas de différence
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).

  • Une fonction réutilisable qui encapsule de la logique avec état, utilisant la Composition API (bonne réponse)
  • Un type de composant spécial
  • Un plugin Vue.js
  • Une directive personnalisée
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.

  • Avec des Proxies JavaScript (ES6) qui interceptent les accès et mutations pour suivre les dépendances (bonne réponse)
  • Avec Object.defineProperty comme Vue 2
  • Avec des observateurs manuels
  • Avec des Web Workers
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.

  • computed() retourne une valeur réactive dérivée ; watchEffect() exécute une fonction avec effets de bord quand les dépendances changent (bonne réponse)
  • computed() est pour le style, watchEffect() pour la logique
  • Il n'y a pas de différence
  • computed() est asynchrone, watchEffect() synchrone
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.

  • Créer un composable useDebounce() qui utilise watch() avec un timer pour retarder la mise à jour (bonne réponse)
  • Utiliser l'attribut debounce sur l'input
  • Avec v-model.debounce
  • Le debounce n'est pas possible en Vue
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.

  • Avec watch(source, callback, { deep: true }) pour surveiller les propriétés imbriquées d'un objet réactif (bonne réponse)
  • Avec watchDeep()
  • Tous les watchers sont profonds par défaut
  • Les watchers profonds n'existent pas
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.

  • Un mécanisme pour passer des données à travers l'arbre de composants sans props drilling (bonne réponse)
  • Un système d'injection de dépendances pour les services
  • Un pattern pour les requêtes HTTP
  • Un type de directive
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).

  • Avec defineProps() ou avec un type/interface (bonne réponse)
  • Avec PropTypes
  • Avec @Prop dans le template
  • TypeScript n'est pas supporté pour les props
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 }).

  • Enregistrer avec app.directive() ou utiliser des hooks de cycle de vie (created, mounted, updated) dans un objet directive (bonne réponse)
  • Les directives personnalisées n'existent plus dans Vue 3
  • Avec des composants uniquement
  • Avec des mixins
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.

  • avec des slots #default (composant asynchrone) et #fallback (affiché pendant le chargement) (bonne réponse)
  • n'existe pas dans Vue 3
  • Avec v-suspense
  • Uniquement avec Vuex
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().

  • Toujours utiliser :key avec un identifiant unique, éviter v-if avec v-for, et utiliser des computed pour les listes filtrées (bonne réponse)
  • Utiliser v-for sans key
  • Faire le rendu côté serveur
  • Les listes sont toujours optimisées automatiquement
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.

  • Avec defineAsyncComponent(() => import("./MonComposant.vue")) (bonne réponse)
  • Avec v-lazy
  • Avec import() directement dans le template
  • Le lazy loading est automatique
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.

  • Une collection de 200+ composables prêts à l'emploi couvrant les cas d'usage courants (state, sensors, browser, network...) (bonne réponse)
  • Un framework concurrent de Vue
  • Un outil de build
  • Une bibliothèque de composants UI
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.

  • Avec les composants et qui appliquent des classes CSS automatiquement (bonne réponse)
  • Uniquement avec des bibliothèques externes
  • Avec des animations JavaScript pures
  • Vue ne supporte pas les animations
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.

  • Organiser par fonctionnalité (features/), avec des composables partagés, stores Pinia, et composants réutilisables dans un dossier shared/ (bonne réponse)
  • Tout mettre dans le dossier components/
  • Un seul fichier .vue
  • Pas de structure particulière
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.

  • met en cache les composants inactifs pour préserver leur état et éviter de les recréer (bonne réponse)
  • Un système de cache HTTP
  • Une directive pour la mémoire
  • Un plugin de persistance
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>.

  • Avec Vitest (ou Jest) + @vue/test-utils pour les tests unitaires et de composants, et Playwright/Cypress pour les tests E2E (bonne réponse)
  • Uniquement des tests manuels
  • Avec des console.log
  • Les tests ne sont pas possibles avec Vue
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.

  • Créer un composable avec un état réactif partagé (ref/reactive en dehors de la fonction) (bonne réponse)
  • Avec des props partout
  • Avec des variables globales sur window
  • C'est impossible sans store
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.

  • L'élimination du code mort au build ; importer uniquement les fonctions nécessaires plutôt que l'objet Vue entier (bonne réponse)
  • Une technique pour secouer l'arbre DOM
  • Un type d'animation
  • Un outil de build
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é.

  • Avec app.config.errorHandler pour attraper toutes les erreurs non gérées pendant le rendu et les watchers (bonne réponse)
  • Avec try/catch dans chaque composant
  • Avec un composant ErrorBoundary
  • La gestion globale des erreurs n'existe pas
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.

  • Avec la bibliothèque vue-i18n : définir des messages par locale, utiliser $t() dans les templates et useI18n() dans le script (bonne réponse)
  • Traduire manuellement dans le code
  • Utiliser Google Translate API
  • L'i18n n'est pas supporté
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.

  • Avec v-model:titre="var1" et v-model:contenu="var2", le composant utilise defineProps + defineEmits pour chaque (bonne réponse)
  • v-model ne supporte qu'une seule liaison
  • Avec plusieurs v-model sans nom
  • Avec des props uniquement
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.

  • Définir le store avec defineStore et typer le state, les getters et les actions ; Pinia infère automatiquement les types (bonne réponse)
  • TypeScript n'est pas compatible avec Pinia
  • Utiliser any partout
  • Avec des fichiers .js uniquement
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.

  • Le rendu des composants Vue côté serveur en HTML, améliorant le SEO et le temps de chargement initial (bonne réponse)
  • Un type de base de données
  • Un outil de build
  • Une directive Vue
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.

  • Avec beforeEach() pour la vérification globale, beforeEnter() par route, ou beforeRouteEnter() dans le composant (bonne réponse)
  • En cachant les liens avec v-if
  • La sécurité n'est pas gérée par le routeur
  • Avec des cookies uniquement
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.

  • Avec qui change le composant rendu selon la valeur de la variable (bonne réponse)
  • Avec v-dynamic
  • Avec un switch/case dans le template
  • Les composants dynamiques n'existent pas
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.

  • Utiliser FormKit ou VeeValidate avec Zod/Yup pour la validation de schéma et la génération de formulaires (bonne réponse)
  • Avec v-model uniquement
  • Manuellement avec des if/else
  • Les formulaires complexes ne sont pas possibles
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.

  • Un plugin Vite/Webpack qui importe automatiquement les composants utilisés dans les templates, sans imports explicites (bonne réponse)
  • Un composant Vue spécial
  • Un outil de test
  • Un framework concurrent
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).

  • Utiliser Vue DevTools (extension navigateur), les breakpoints dans le code, et le logging stratégique (bonne réponse)
  • Avec des console.log partout
  • En redémarrant le serveur
  • Le débogage n'est pas possible
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.

  • Avec dans le fichier .vue ; Vue ajoute un attribut data-v-xxx unique au composant et à tous ses éléments (bonne réponse)
  • Avec des classes BEM
  • Avec CSS Modules uniquement
  • Le CSS local n'est pas possible
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) { ... }.