mcpField
V
vue-composition

vue-composition

github.com/claude-dev-suite开发4636 次安装2 天前更新
代码仓库

关于 vue-composition

面向 Vue 应用开发者的 Vue 3 Composition API 参考技能,讲解响应式与组合式函数,并提供安全、错误处理、性能、无障碍和测试方面的指导。

主要功能

  1. 01响应式 API 与状态
  2. 02组合式函数模式
  3. 03组件与属性实践
  4. 04安全与错误处理
  5. 05性能和无障碍指导
  6. 06测试配置

适用场景

  1. 01构建可复用的组合式函数
  2. 02管理组件的响应式状态
  3. 03检查 Vue 应用的安全与性能

MCP 相关

该技能指向 `mcp__documentation__fetch_docs`,用于获取完整的 Vue 文档。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/claude-dev-suite/claude-dev-suite --skill vue-composition

安装后在 Claude Code 中输入/vue-composition确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

advanced.md
quick-ref/
composables.md
reactivity-cheatsheet.md

详细介绍

Vue 3 Composition API

完整参考:请参阅 advanced.md,了解 WebSocket 组合式函数、provide/inject 插件模式、Socket.IO 集成和房间管理。

深入了解:使用 mcp__documentation__fetch_docs,并将技术设为:vue,获取全面的文档。

不要使用此技能的情况

以下情况请跳过此技能:

  • 使用 Vue 2 Options API(请使用旧版 Vue 文档)
  • 构建 React 应用(请使用 frontend-react)
  • 使用 Angular 框架(请使用 angular)
  • 使用 Svelte(请使用 svelte)
  • 处理仅在服务器端运行的逻辑(无需框架)

组件结构

<script setup lang="ts">
import { ref, computed, onMounted } from 'vue'

interface Props {
  title: string
  count?: number
}

const props = defineProps<Props>()
const emit = defineEmits<{
  update: [value: string]
}>()

const localState = ref('')
const doubled = computed(() => props.count * 2)

onMounted(() => {
  console.log('Component mounted')
})
</script>

<template>
  <div>
    <h1>{{ title }}</h1>
    <p>{{ doubled }}</p>
  </div>
</template>

响应式系统

API用途
ref()基本类型的响应式值
reactive()响应式对象
computed()派生状态
watch()监听响应式数据源
watchEffect()自动追踪依赖

组合式函数模式

// useCounter.ts
export function useCounter(initial = 0) {
  const count = ref(initial)
  const increment = () => count.value++
  const decrement = () => count.value--
  return { count, increment, decrement }
}

核心概念

  • 推荐使用 <script setup> 语法
  • 基本类型使用 ref,对象使用 reactive
  • 使用 v-model 实现双向绑定
  • 使用插槽分发内容

反模式

反模式不良原因正确做法
对基本类型使用 reactive()解构时会失去响应性基本类型使用 ref()
直接修改 props破坏单向数据流触发事件,或使用 v-model
未经清理就使用 v-html存在 XSS 漏洞渲染前使用 DOMPurify
使用未做记忆化的大型 computed每次渲染都会重新计算拆分为更小的 computed
未在 onUnmounted 中清理会造成内存泄漏清除计时器,取消订阅
在 computed 足以满足需求时仍使用 watch增加不必要的复杂性派生状态使用 computed

快速故障排查

问题可能原因解决方案
Computed 未更新忘记为 ref 使用 .value使用 .value 访问 ref
模板不是响应式的使用了 let 而不是 ref转换为 ref() 或 reactive()
Props 修改警告直接修改了 props克隆 props 或触发更新事件
组件未重新渲染对基本类型使用了 reactive基本类型使用 ref()
内存泄漏忘记清理在 onUnmounted 中添加清理逻辑
v-model 不起作用事件名称错误使用 update:modelValue 事件

生产环境就绪

安全最佳实践
<script setup lang="ts">
// NEVER use v-html with user input without sanitization
import DOMPurify from 'dompurify'

const props = defineProps<{ userContent: string }>()
const sanitizedContent = computed(() => DOMPurify.sanitize(props.userContent))
</script>

<template>
  
  <div v-html="userContent" />

  
  <div v-html="sanitizedContent" />
</template>
// Validate external URLs
const isValidUrl = (url: string): boolean => {
  try {
    const parsed = new URL(url)
    return ['http:', 'https:'].includes(parsed.protocol)
  } catch {
    return false
  }
}

// Never expose secrets in client code
// Use runtime config or server routes instead
const config = useRuntimeConfig()
// config.public.* is safe for client
// config.* (without public) stays server-side
错误处理
<script setup lang="ts">
import { onErrorCaptured } from 'vue'

// Component-level error boundary
onErrorCaptured((error, instance, info) => {
  // Log to error tracking service
  logError(error, { component: instance?.$options.name, info })

  // Return false to prevent error propagation
  return false
})
</script>
// Global error handler (main.ts)
const app = createApp(App)

app.config.errorHandler = (error, instance, info) => {
  console.error('Global error:', error)
  // Send to error tracking (Sentry, etc.)
  captureException(error, { extra: { info } })
}

app.config.warnHandler = (msg, instance, trace) => {
  // Log warnings in development
  if (import.meta.env.DEV) console.warn(msg, trace)
}
性能优化
<script setup lang="ts">
import { defineAsyncComponent, shallowRef } from 'vue'

// Lazy load heavy components
const HeavyChart = defineAsyncComponent({
  loader: () => import('./HeavyChart.vue'),
  loadingComponent: LoadingSpinner,
  delay: 200,
  errorComponent: ErrorDisplay,
})

// Use shallowRef for large objects that don't need deep reactivity
const largeDataset = shallowRef<DataItem[]>([])

// Computed with getter/setter for derived state
const filteredItems = computed(() =>
  items.value.filter(item => item.active)
)
</script>

<template>
  
  <header v-once>
    <h1>{{ appTitle }}</h1>
  </header>

  
  <div v-for="item in list" :key="item.id" v-memo="[item.id, item.updated]">
    <ExpensiveComponent :data="item" />
  </div>

  
  <VirtualList :items="largeDataset" :item-height="50" />
</template>
无障碍(a11y)
<template>
  
  <button @click="handleClick">Submit</button>

  
  <div role="alert" aria-live="polite" v-if="error">
    {{ error }}
  </div>

  
  <dialog ref="dialogRef" @vue:mounted="dialogRef?.focus()">
    <h2 id="dialog-title">Confirm Action</h2>
    <div aria-labelledby="dialog-title">...</div>
  </dialog>
</template>
测试设置
// Component testing with Vue Test Utils
import { mount } from '@vue/test-utils'
import { describe, it, expect, vi } from 'vitest'

describe('UserForm', () => {
  it('emits submit with form data', async () => {
    const wrapper = mount(UserForm)

    await wrapper.find('input[name="email"]').setValue('[email protected]')
    await wrapper.find('form').trigger('submit')

    expect(wrapper.emitted('submit')).toBeTruthy()
    expect(wrapper.emitted('submit')[0]).toEqual([{ email: '[email protected]' }])
  })
})
监控指标
指标警报阈值
最大内容绘制(LCP)> 2.5s
首次输入延迟(FID)> 100ms
累积布局偏移(CLS)> 0.1
JavaScript 包大小> 200KB(gzip 压缩后)
组件渲染时间> 16ms
构建优化
// vite.config.ts
export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        manualChunks: {
          vue: ['vue', 'vue-router', 'pinia'],
          ui: ['@headlessui/vue', '@vueuse/core'],
        },
      },
    },
    sourcemap: true,
  },
})
检查清单
  • 已配置全局错误处理程序
  • 客户端状态中不含敏感数据
  • 对 v-html 内容使用 DOMPurify
  • 使用异步组件进行代码拆分
  • 对大型非响应式数据使用 shallowRef
  • 对开销较大的列表渲染使用 v-memo
  • 对长列表使用虚拟滚动
  • 使用语义化 HTML 和 ARIA 标签
  • 已监控核心 Web 指标
  • 已优化包大小
  • 已集成错误报告服务

参考文档

深入了解:使用 mcp__documentation__fetch_docs,并将技术设为:vue,获取全面的文档。

评论

支持 Markdown