Communitygithub.com

vue-patterns

Modèles de composition API Vue.js 3, architecture de composants, bonnes pratiques de réactivité, gestion d'état Pinia, navigation Vue Router et modèles Nuxt SSR. S'active pour les projets Vue, Nuxt, Vite ou Pinia. À utiliser lors de la construction ou de la révision de code Vue 3, Nuxt ou Pinia — Composition API, réactivité ou navigation routeur.

Qu'est-ce que vue-patterns ?

Ce skill est un guide complet pour le développement Vue.js 3, axé sur la Composition API avec `<script setup>`. Il couvre l'architecture des composants, la réactivité, la gestion d'état avec Pinia, le routage avec Vue Router, les tests, et les modèles SSR. Il inclut des sections spécialisées pour Nuxt lorsqu'il diffère de Vue standard. L'utilisateur active ce skill lorsqu'il travaille sur des projets utilisant Vue, Nuxt, Vite + Vue ou Pinia, ou lorsqu'il pose des questions sur les composables, la réactivité, les stores ou le routage. Le skill fournit des conventions de nommage, des structures de fichiers recommandées (feature-first), des bonnes pratiques pour les props et événements, des anti-patrons à éviter, et des APIs Vue 3.5+ comme `useTemplateRef()` et le destructuring réactif des props. Il définit également des règles strictes pour les composables, les stores Pinia (syntaxe Setup Store), et les guards de navigation Vue Router. Des modèles de test sont inclus avec Vitest, Vue Test Utils et Playwright, ainsi que des techniques de performance comme `v-memo`, `shallowRef` et les routes paresseuses. Le skill est conçu pour être utilisé en contexte de développement ou de revue de code, garantissant des pratiques standardisées et performantes.

Compatible avec~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/affaan-m/everything-claude-code/tree/main/skills/vue-patterns

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Modèles et bonnes pratiques Vue.js

Guide complet pour le développement Vue.js 3 avec la Composition API (<script setup>), couvrant la conception de composants, la réactivité, la gestion d'état, le routage, les tests et les modèles SSR. Des conseils spécifiques à Nuxt sont inclus lorsqu'ils diffèrent de Vue standard.

Quand activer

Activez ce skill lorsque :

  • Le projet utilise Vue.js (toute version), Nuxt, Vite + Vue ou Pinia.
  • L'utilisateur pose des questions sur l'architecture des composants Vue, les composables, la réactivité ou la gestion d'état.
  • Vous révisez des composants monofichiers Vue (fichiers .vue).
  • Vous configurez Vue Router, des stores Pinia ou la configuration Vite/Vitest.
  • Vous discutez de performances spécifiques à Vue, de sécurité ou de modèles SSR.

1. Structure du projet

Organisation recommandée (feature-first)

src/
├── api/              # Client API et définitions d'endpoints
├── assets/           # Ressources statiques (images, polices, icônes)
├── components/       # Composants partagés/réutilisables
│   ├── base/         # Primitives UI de base (Button, Input, Modal)
│   └── features/     # Composants partagés spécifiques à une fonctionnalité
├── composables/      # Logique réutilisable de la Composition API
├── layouts/          # Mises en page (optionnel)
├── pages/            # Composants de page au niveau des routes
├── router/           # Configuration de Vue Router
├── stores/           # Stores Pinia
├── types/            # Définitions de types TypeScript
├── utils/            # Fonctions utilitaires pures
└── App.vue           # Composant racine

Convention de nommage

ConventionQuand l'utiliser
PascalCase.vueTous les composants (imposé par vue/multi-word-component-names)
useCamelCase.tsComposables
camelCase.tsUtilitaires, clients API, types
répertoires en kebab-caseSegments de route, dossiers de fonctionnalités

2. Architecture des composants

Ordre dans un composant monofichier

<script setup lang="ts">
// 1. Imports (vue → écosystème → absolu → relatif)
// 2. Props & Emits & Slots
// 3. Composables
// 4. État local (ref/reactive)
// 5. Propriétés calculées
// 6. Méthodes
// 7. Observateurs
// 8. Hooks de cycle de vie
</script>

<template>
  <!-- Contenu du template -->
</template>

<style scoped>
  /* Styles scopés */
</style>

Composants de présentation vs conteneurs

  • Composants conteneurs : Possèdent les récupérations de données, l'état et les effets de bord. Affichent les composants de présentation.
  • Composants de présentation : Reçoivent des props, émettent des événements. Pas d'appels API, pas d'accès aux stores. Rendu pur.

Bonnes pratiques pour les props

// Props typées avec valeurs par défaut
interface Props {
  label: string;
  variant?: "primary" | "secondary";
  disabled?: boolean;
  items: Item[];
}

const props = withDefaults(defineProps<Props>(), {
  variant: "primary",
  disabled: false,
});
  • Fournissez toujours type, et required/default le cas échéant.
  • Props booléennes : isXxx, hasXxx, canXxx.
  • Ne mute jamais les props — émettez des événements à la place.
  • Pour la liaison v-model, utilisez defineModel() (Vue 3.4+) ou modelValue + update:modelValue.

Événements

const emit = defineEmits<{
  submit: [];
  "update:modelValue": [value: string];
  select: [id: string, index: number];
}>();
  • Utilisez le kebab-case dans les templates (@update:model-value).
  • Utilisez le camelCase dans le script (emit("update:modelValue", val)).

3. Composables (logique réutilisable)

Structure

// composables/useDebounce.ts
export function useDebounce<T>(value: MaybeRef<T>, delay: number): Ref<T> {
  const debounced = ref(toValue(value)) as Ref<T>;

  let timer: ReturnType<typeof setTimeout>;
  watch(
    () => toValue(value),
    (newVal) => {
      clearTimeout(timer);
      timer = setTimeout(() => { debounced.value = newVal; }, delay);
    }
  );

  onUnmounted(() => clearTimeout(timer));
  return readonly(debounced);
}

Règles

  • Doit commencer par le préfixe use.
  • Renvoie des valeurs réactives (ref, computed, reactive), jamais des primitives simples.
  • Accepte les entrées réactives via MaybeRef / toRef() / toValue().
  • Nettoie les effets de bord dans onUnmounted ou via onCleanup de l'observateur.
  • Pas d'effets de bord au niveau du module.

vs Mixins

Les composables remplacent entièrement les mixins Vue 2 :

  • Mixins : Flux de données opaque, collisions de source de vérité, conflits de noms.
  • Composables : Imports explicites, valeurs de retour claires, composables et arborescents (tree-shakable).

4. Gestion d'état

Quand utiliser quoi

ModèleCas d'utilisation
ref() / reactive()État local du composant
Props + EmitsCommunication parent-enfant
Provide / InjectThème, configuration, API de plugin
Store PiniaÉtat global, partagé, complexe
Composable d'état serveurDonnées API avec mise en cache (wrapper fetch/TanStack Query)

Store Pinia (Setup Store) — Recommandé

// stores/useCartStore.ts
export const useCartStore = defineStore("cart", () => {
  const items = ref<CartItem[]>([]);
  const isLoading = ref(false);

  const totalPrice = computed(() =>
    items.value.reduce((sum, i) => sum + i.price * i.quantity, 0)
  );
  const itemCount = computed(() =>
    items.value.reduce((sum, i) => sum + i.quantity, 0)
  );

  async function addItem(productId: string) {
    isLoading.value = true;
    try {
      const item = await fetchProduct(productId);
      const existing = items.value.find(i => i.id === item.id);
      if (existing) existing.quantity++;
      else items.value.push({ ...item, quantity: 1 });
    } finally {
      isLoading.value = false;
    }
  }

  return { items, isLoading, totalPrice, itemCount, addItem };
});
  • Utilisez la syntaxe Setup Store (pas Options Store).
  • Préférez les actions pour les mutations de niveau métier et $patch() pour les mises à jour groupées.
  • Chaque action asynchrone : gérez chargement + succès + erreur.

5. Vue Router

Définitions de routes

const routes = [
  {
    path: "/users/:id",
    name: "user-detail",
    component: () => import("@/pages/UserDetail.vue"), // paresseux
    props: true, // passe les paramètres comme props
    meta: { requiresAuth: true },
  },
];

Guards de navigation

router.beforeEach((to, from) => {
  const { isLoggedIn } = useAuthStore();
  if (to.meta.requiresAuth && !isLoggedIn) {
    return { name: "login", query: { redirect: to.fullPath } };
  }
});

Paramètres de route réactifs

Lorsqu'un composant reste monté mais que les paramètres de route changent :

const route = useRoute();
const id = computed(() => route.params.id as string);
watch(id, (newId) => fetchItem(newId));

6. Modèles de templates

Syntaxe de template

<!-- v-if/v-else-if/v-else -->
<div v-if="isLoading">Chargement...</div>
<div v-else-if="error">Erreur : {{ error }}</div>
<div v-else>{{ content }}</div>

<!-- v-show pour les bascules fréquentes -->
<div v-show="isOpen">Contenu basculé</div>

<!-- v-for avec clés stables -->
<div v-for="item in items" :key="item.id">{{ item.name }}</div>

<!-- Liste filtrée calculée (pas v-if + v-for sur le même élément) -->
<div v-for="item in activeItems" :key="item.id">{{ item.name }}</div>

<!-- Gestion d'événements -->
<form @submit.prevent="handleSubmit">
  <button type="submit">Enregistrer</button>
</form>

<!-- v-model -->
<input v-model="name" />
<CustomInput v-model="value" v-model:title="title" />

7. Performances

TechniqueQuand l'utiliser
v-memoÉléments de liste qui changent rarement
v-onceContenu rendu une fois et statique pour toujours
shallowRef()Grandes structures de données remplacées en bloc
shallowReactive()Seules les propriétés de premier niveau sont réactives
v-show plutôt que v-ifBascules de visibilité fréquentes
<KeepAlive :max="10">Mettre en cache les vues basculées
Routes paresseuses() => import(...) pour les routes non critiques
SuspenseChargement asynchrone de composants avec fallback

8. Tests

Stack

  • Vitest pour les tests unitaires et de composants
  • Vue Test Utils pour le montage et l'interaction
  • @pinia/testing pour le mock des stores
  • Playwright pour les tests E2E

Modèle de test de composant

import { mount } from "@vue/test-utils";
import { createPinia, setActivePinia } from "pinia";
import UserCard from "./UserCard.vue";

beforeEach(() => { setActivePinia(createPinia()); });

it("affiche et émet", async () => {
  const wrapper = mount(UserCard, {
    props: { user: { id: "1", name: "Alice" } },
  });
  expect(wrapper.text()).toContain("Alice");
  await wrapper.find("button").trigger("click");
  expect(wrapper.emitted("select")![0]).toEqual(["1"]);
});

9. Modèles spécifiques à Nuxt

Auto-imports

Nuxt importe automatiquement ref, computed, watch, useFetch, useAsyncData, etc. Utilisez-les directement sans importer. Pour les projets non Nuxt, importez toujours explicitement.

useAsyncData / useFetch

const { data: user, pending, error, refresh } = await useAsyncData(
  "user", // clé unique pour la mise en cache
  () => $fetch(`/api/users/${id}`),
);

const { data: posts } = await useFetch("/api/posts", {
  query: { page: 1 },
  key: "posts-page-1", // déduplication des requêtes
});

Routes serveur

// server/api/users/[id].ts
export default defineEventHandler(async (event) => {
  const { id } = await getValidatedRouterParams(event, z.object({
    id: z.string().uuid(),
  }).parse);
  // ... récupérer et retourner
});

Configuration runtime

// nuxt.config.ts
export default defineNuxtConfig({
  runtimeConfig: {
    // serveur uniquement
    apiSecret: "",
    // public (exposé au client)
    public: {
      apiBase: "https://api.example.com",
    },
  },
});

10. Nouvelles APIs Vue 3.5+

Destructuring réactif des props

Vue 3.5 a stabilisé le destructuring réactif des props — les variables destructurées de defineProps() sont automatiquement réactives :

// Vue 3.5+ : les props destructurées sont réactives (pas besoin de toRefs)
const { count = 0, msg = "hello" } = defineProps<{
  count?: number;
  msg?: string;
}>();

// Limitation : impossible d'observer une prop destructurée directement
watch(() => count, (newVal) => { ... }); // PASS : un getter est requis

useTemplateRef()

Remplacez les refs simples nommées par useTemplateRef() pour les références de template :

import { useTemplateRef } from "vue";
const inputEl = useTemplateRef<HTMLInputElement>("input");
// "input" correspond à l'attribut ref="input" dans le template, pas au nom de la variable

Prend en charge les identifiants de ref dynamiques : useTemplateRef(dynamicRefId).

onWatcherCleanup()

API de nettoyage d'observateur importable globalement (Vue 3.5+). Doit être appelée de manière synchrone à l'intérieur du callback de l'observateur :

import { watch, onWatcherCleanup } from "vue";

watch(userId, async (newId) => {
  const controller = new AbortController();
  onWatcherCleanup(() => controller.abort());
  // ... récupération avec signal
});

useId()

Génération d'identifiants uniques stables pour le SSR pour les éléments de formulaire et l'accessibilité :

import { useId } from "vue";
const id = useId();

Téléportation différée (defer)

<Teleport defer> permet de téléporter vers des cibles rendues dans le même cycle :

<Teleport defer to="#container">Contenu</Teleport>
<div id="container"></div>

Hydratation paresseuse (SSR)

defineAsyncComponent() prend désormais en charge la stratégie hydrate :

import { defineAsyncComponent, hydrateOnVisible } from "vue";
const AsyncComp = defineAsyncComponent({
  loader: () => import("./Comp.vue"),
  hydrate: hydrateOnVisible(),
});

Anti-patrons

Anti-patronPourquoi c'est mauvaisLa correction
Destructurer defineProps() (Vue < 3.5)Capture un instantané, perd la réactivitéAccéder via props.xxx ou utiliser toRefs()
watch() sur une prop destructurée (Vue 3.5+)Erreur à la compilation — les props destructurées ne peuvent pas être observées directementUtiliser un getter wrapper : watch(() => count, ...)
v-if + v-for sur le même élémentOrdre d'exécution ambiguUtiliser un tableau filtré calculé
Clé v-for = indexÉtat corrompu lors du réordonnancementUtiliser des IDs de base de données stables
Muter les propsViolation du flux de données unidirectionnelÉmettre des événements ou utiliser v-model
v-html avec contenu utilisateurVulnérabilité XSSNettoyer avec DOMPurify
Mixins dans Vue 3Opaque, propice aux collisionsRemplacer par des composables
Effets de bord au niveau du module dans un composablePartagé entre les instancesPortée dans onMounted + onUnmounted
reactive() pour un état remplaçableLe remplacement casse la réactivitéUtiliser ref() à la place
Observateur sans nettoyageFuites mémoire, conditions de courseUtiliser onCleanup ou onWatcherCleanup() (Vue 3.5+)
Options API dans du nouveau code Vue 3L'écosystème migre vers la Composition APIUtiliser <script setup>
Ref simple pour les références de templatePas de support de ref dynamique, correspondance de nom fragileUtiliser useTemplateRef() (Vue 3.5+)

Compétences associées

  • accessibility — ARIA, HTML sémantique, gestion du focus
  • frontend-patterns — Architecture frontend multi-frameworks
  • typescript — Bonnes pratiques TypeScript appliquées aux projets Vue
  • coding-standards — Standards généraux de qualité de code

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

accessibility

Design, implement, and audit inclusive digital products using WCAG 2.2 Level AA. Use when building or auditing UI that must meet WCAG 2.2 Level AA, or when reviewing a change for keyboard, contrast, or screen-reader support.

affaan-m/claude-api

Anthropic Claude API patterns for Python and TypeScript. Covers Messages API, streaming, tool use, vision, extended thinking, batches, prompt caching, and Claude Agent SDK. Use when building applications with the Claude API or Anthropic SDKs.

affaan-m/everything-claude-code

End-to-end marketing campaign planning and execution. Covers audience research, positioning, campaign angle definition, landing page copy, email sequences, social posts, ad copy, short-form video scripts, and content calendars. Use as the orchestration layer for multi-channel product launches. Use when planning or executing a multi-channel product launch, or producing landing page, email, social, or ad copy.

affaan-m/everything-claude-code

Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.

affaan-m/everything-claude-code-conventions

Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.

affaan-m/frontend-design

Create distinctive, production-grade frontend interfaces with high design quality. Use when the user asks to build web components, pages, or applications and the visual direction matters as much as the code quality.

affaan-m/gget

gget CLI and Python workflow for quick genomic database queries, sequence lookup, BLAST-style searches, enrichment checks, and reproducible bioinformatics evidence logs.

affaan-m/literature-review

Systematic literature-review workflow for academic, biomedical, technical, and scientific topics, including search planning, source screening, synthesis, citation checks, and evidence logging.

affaan-m/motion-ui

Production-ready UI motion system for React/Next.js. Use when implementing animations, transitions, or motion patterns.

affaan-m/project-guidelines-example

Example project-specific skill template based on a real production application.

affaan-m/pubmed-database

Direct PubMed and NCBI E-utilities search workflows for biomedical literature, MeSH queries, PMID lookup, citation retrieval, and API-backed literature monitoring.

affaan-m/scholar-evaluation

Structured scholarly-work evaluation for papers, proposals, literature reviews, methods sections, evidence quality, citation support, and research-writing feedback.

affaan-m/uspto-database

USPTO patent and trademark data workflow for official record lookup, PatentSearch queries, TSDR checks, assignment data, and reproducible IP research logs.

agent-architecture-audit

Full-stack diagnostic for agent and LLM applications. Audits the 12-layer agent stack for wrapper regression, memory pollution, tool discipline failures, hidden repair loops, and rendering corruption. Produces severity-ranked findings with code-first fixes. Essential for developers building agent applications, autonomous loops, or any LLM-powered feature. Use when an agent or LLM feature misbehaves and the failing layer is unknown, or before shipping an agent stack.

agent-eval

Head-to-head comparison of coding agents (Claude Code, Aider, Codex, etc.) on custom tasks with pass rate, cost, time, and consistency metrics. Use when choosing between coding agents, or when a change to an agent setup needs measured pass rate, cost, and time rather than an impression.

agent-harness-construction

Design and optimize AI agent action spaces, tool definitions, and observation formatting for higher completion rates. Use when defining or revising an agent

agentic-engineering

Operate as an agentic engineer using eval-first execution, decomposition, and cost-aware model routing. Use when planning or executing engineering work that agents will carry out end to end.

agentic-os

Build persistent multi-agent operating systems on Claude Code. Covers kernel architecture, specialist agents, slash commands, file-based memory, scheduled automation, and state management without external databases. Use when building a persistent multi-agent system on Claude Code with its own memory, commands, and scheduling.

agent-introspection-debugging

Structured self-debugging workflow for AI agent failures using capture, diagnosis, contained recovery, and introspection reports. Use when an agent run fails and you need a reproducible diagnosis instead of a retry.

agent-payment-x402

Add x402 payment execution to AI agents with per-task budgets, spending controls, and non-custodial wallets. Supports Base through agentwallet-sdk and X Layer through OKX Payments / OKX Agent Payments Protocol. Use when an agent must pay for something itself and needs per-task budgets, spending controls, and a non-custodial wallet.

Skills associés