Communitygithub.com

vue-patterns

Vue.js 3 Composition API 模式、组件架构、响应式最佳实践、Pinia 状态管理、Vue Router 导航和 Nuxt SSR 模式。适用于 Vue、Nuxt、Vite 或 Pinia 项目。在构建或审查 Vue 3、Nuxt 或 Pinia 代码时激活——包括 Composition API、响应式或路由导航。

vue-patterns 是什么?

该技能提供了一套全面的 Vue.js 3 开发指南,重点涵盖 Composition API (`<script setup>`)、组件架构设计、响应式系统最佳实践、Pinia 状态管理、Vue Router 导航、测试策略以及 SSR 模式。它还包含 Nuxt 特定指导,当 Nuxt 实践与普通 Vue 不同时会单独说明。该技能适用于 Vue、Nuxt、Vite 和 Pinia 项目,帮助开发者避免常见反模式,并利用 Vue 3.5+ 的新 API(如 `useTemplateRef()`、`onWatcherCleanup()`、`useId()` 和 `defer` Teleport)编写更高效、可维护的代码。通过结构化的文件组织建议、组件模式(容器/展示组件)、组合式函数(Composables)使用规则以及性能优化技巧,该技能显著提升了 Vue 项目的开发效率和代码质量。

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

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

Vue.js 模式和最佳实践

关于使用 Composition API (<script setup>) 进行 Vue.js 3 开发的全面指南,涵盖组件设计、响应式、状态管理、路由、测试和 SSR 模式。其中也包含与普通 Vue 不同的 Nuxt 特定指导。

何时激活

在以下情况激活此技能:

  • 项目使用 Vue.js(任何版本)、Nuxt、Vite + Vue 或 Pinia。
  • 用户询问 Vue 组件架构、组合式函数、响应式或状态管理。
  • 审查 Vue 单文件组件(.vue 文件)。
  • 设置 Vue Router、Pinia stores 或 Vite/Vitest 配置。
  • 讨论 Vue 特定的性能、安全或 SSR 模式。

1. 项目结构

推荐布局(功能优先)

src/
├── api/              # API 客户端和端点定义
├── assets/           # 静态资源(图片、字体、图标)
├── components/       # 共享/可复用组件
│   ├── base/         # 基础 UI 原语(Button, Input, Modal)
│   └── features/     # 特定功能的共享组件
├── composables/      # 可复用的 Composition API 逻辑
├── layouts/          # 页面布局(可选)
├── pages/            # 路由级别的页面组件
├── router/           # Vue Router 配置
├── stores/           # Pinia stores
├── types/            # TypeScript 类型定义
├── utils/            # 纯工具函数
└── App.vue           # 根组件

文件命名

约定使用场景
PascalCase.vue所有组件(由 vue/multi-word-component-names 强制要求)
useCamelCase.ts组合式函数
camelCase.ts工具、API 客户端、类型
kebab-case 目录路由段、功能文件夹

2. 组件架构

单文件组件顺序

<script setup lang="ts">
// 1. 导入(vue → 生态系统 → 绝对路径 → 相对路径)
// 2. Props、Emits 和 Slots
// 3. 组合式函数
// 4. 本地状态(ref/reactive)
// 5. 计算属性
// 6. 方法
// 7. 监听器
// 8. 生命周期钩子
</script>

<template>
  <!-- 模板内容 -->
</template>

<style scoped>
  /* 作用域样式 */
</style>

展示组件 vs 容器组件

  • 容器组件:负责数据获取、状态和副作用。渲染展示组件。
  • 展示组件:接收 props,触发事件。无 API 调用,无 store 访问。纯渲染。

Props 最佳实践

// 基于类型的 props,带默认值
interface Props {
  label: string;
  variant?: "primary" | "secondary";
  disabled?: boolean;
  items: Item[];
}

const props = withDefaults(defineProps<Props>(), {
  variant: "primary",
  disabled: false,
});
  • 始终提供 type,以及 required/default(如适用)。
  • 布尔 props:使用 isXxx、hasXxx、canXxx。
  • 永远不要修改 props——而是触发事件。
  • 对于 v-model 绑定,使用 defineModel()(Vue 3.4+)或 modelValue + update:modelValue。

事件

const emit = defineEmits<{
  submit: [];
  "update:modelValue": [value: string];
  select: [id: string, index: number];
}>();
  • 在模板中使用 kebab-case(@update:model-value)。
  • 在 script 中使用 camelCase(emit("update:modelValue", val))。

3. 组合式函数(可复用逻辑)

结构

// 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);
}

规则

  • 必须以 use 前缀开头。
  • 返回响应式值(ref、computed、reactive),而不是普通原始值。
  • 通过 MaybeRef / toRef() / toValue() 接受响应式输入。
  • 在 onUnmounted 或 watcher 的 onCleanup 中清理副作用。
  • 无模块级副作用。

vs Mixins

组合式函数完全取代 Vue 2 mixins:

  • Mixins:不透明的数据流、数据源冲突、命名冲突。
  • 组合式函数:显式导入、清晰的返回值、可组合且支持 tree-shaking。

4. 状态管理

何时使用什么

模式使用场景
ref() / reactive()本地组件状态
Props + Emits父子通信
Provide / Inject主题、配置、插件 API
Pinia store全局、共享、复杂状态
服务端状态组合式函数API 数据及缓存(封装 fetch/TanStack Query)

Pinia Setup Store(首选)

// 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 };
});
  • 使用 Setup Store 语法(非 Options Store)。
  • 首选用 actions 进行业务级别的变更,$patch() 用于批量更新。
  • 每个异步 action:处理 loading + success + error。

5. Vue Router

路由定义

const routes = [
  {
    path: "/users/:id",
    name: "user-detail",
    component: () => import("@/pages/UserDetail.vue"), // 懒加载
    props: true, // 将参数作为 props 传递
    meta: { requiresAuth: true },
  },
];

导航守卫

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

响应式路由参数

当组件保持挂载但路由参数变化时:

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

6. 模板模式

模板语法

<!-- v-if/v-else-if/v-else -->
<div v-if="isLoading">加载中...</div>
<div v-else-if="error">错误: {{ error }}</div>
<div v-else>{{ content }}</div>

<!-- v-show 用于频繁切换 -->
<div v-show="isOpen">切换的内容</div>

<!-- v-for 带稳定 key -->
<div v-for="item in items" :key="item.id">{{ item.name }}</div>

<!-- 计算后的过滤列表(不在同一元素上同时使用 v-if 和 v-for) -->
<div v-for="item in activeItems" :key="item.id">{{ item.name }}</div>

<!-- 事件处理 -->
<form @submit.prevent="handleSubmit">
  <button type="submit">保存</button>
</form>

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

7. 性能

技术使用场景
v-memo几乎不变的列表项
v-once只渲染一次且静态不变的内容
shallowRef()整体替换的大型数据结构
shallowReactive()只有顶层属性需要响应式
v-show 优于 v-if频繁的可见性切换
<KeepAlive :max="10">缓存切换的视图
懒加载路由非关键路由使用 () => import(...)
Suspense带 fallback 的异步组件加载

8. 测试

技术栈

  • Vitest 用于单元测试和组件测试
  • Vue Test Utils 用于挂载和交互
  • @pinia/testing 用于 store 模拟
  • Playwright 用于端到端测试

组件测试模式

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

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

it("渲染并触发事件", 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. Nuxt 特定模式

自动导入

Nuxt 自动导入 ref、computed、watch、useFetch、useAsyncData 等。直接使用无需导入。对于非 Nuxt 项目,始终显式导入。

useAsyncData / useFetch

const { data: user, pending, error, refresh } = await useAsyncData(
  "user", // 用于缓存的唯一 key
  () => $fetch(`/api/users/${id}`),
);

const { data: posts } = await useFetch("/api/posts", {
  query: { page: 1 },
  key: "posts-page-1", // 去重请求
});

服务端路由

// server/api/users/[id].ts
export default defineEventHandler(async (event) => {
  const { id } = await getValidatedRouterParams(event, z.object({
    id: z.string().uuid(),
  }).parse);
  // ... 获取并返回
});

运行时配置

// nuxt.config.ts
export default defineNuxtConfig({
  runtimeConfig: {
    // 仅服务端
    apiSecret: "",
    // 公开(暴露给客户端)
    public: {
      apiBase: "https://api.example.com",
    },
  },
});

10. Vue 3.5+ 新 API

响应式 Props 解构

Vue 3.5 稳定了响应式 props 解构——从 defineProps() 解构的变量自动具有响应性:

// Vue 3.5+:解构的 props 是响应式的(无需 toRefs)
const { count = 0, msg = "hello" } = defineProps<{
  count?: number;
  msg?: string;
}>();

// 限制:不能直接监听解构后的 prop
watch(() => count, (newVal) => { ... }); // 必须传递 getter

useTemplateRef()

使用 useTemplateRef() 替代名称匹配的普通 ref 来获取模板引用:

import { useTemplateRef } from "vue";
const inputEl = useTemplateRef<HTMLInputElement>("input");
// "input" 匹配模板中的 ref="input" 属性,而非变量名

支持动态 ref ID:useTemplateRef(dynamicRefId)。

onWatcherCleanup()

全局可导入的 watcher 清理 API(Vue 3.5+)。必须在 watcher 回调内部同步调用:

import { watch, onWatcherCleanup } from "vue";

watch(userId, async (newId) => {
  const controller = new AbortController();
  onWatcherCleanup(() => controller.abort());
  // ... 使用 signal 进行 fetch
});

useId()

为表单元素和无障碍生成 SSR 稳定的唯一 ID:

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

defer Teleport

<Teleport defer> 允许传送到同一渲染周期中渲染的目标:

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

延迟水合(SSR)

defineAsyncComponent() 现在支持 hydrate 策略:

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

反模式

反模式错误原因修复方法
解构 defineProps()(Vue < 3.5)获取快照,失去响应性通过 props.xxx 访问或使用 toRefs()
watch() 监听解构后的 prop(Vue 3.5+)编译时错误——不能直接监听解构后的 props使用 getter 包装:watch(() => count, ...)
同一元素上同时使用 v-if 和 v-for执行顺序不明确使用计算后的过滤数组
v-for 的 key 为索引重排序时状态错误使用稳定的数据库 ID
修改 props违反单向数据流触发事件或使用 v-model
对用户内容使用 v-htmlXSS 漏洞使用 DOMPurify 进行清理
在 Vue 3 中使用 Mixins不透明、易冲突替换为组合式函数
组合式函数中的模块级副作用跨实例共享作用域限定在 onMounted + onUnmounted
对可替换状态使用 reactive()替换会破坏响应性改用 ref()
无清理的 Watcher内存泄漏、竞态条件使用 onCleanup 或 onWatcherCleanup()(Vue 3.5+)
在新 Vue 3 代码中使用 Options API生态系统已转向 Composition API使用 <script setup>
使用普通 ref 获取模板引用不支持动态 ref,名称匹配脆弱使用 useTemplateRef()(Vue 3.5+)

相关技能

  • accessibility — ARIA、语义化 HTML、焦点管理
  • frontend-patterns — 跨框架前端架构
  • typescript — 应用于 Vue 项目的 TypeScript 最佳实践
  • coding-standards — 通用代码质量标准

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.

相关技能