mcpField
V
vue-nuxt

vue-nuxt

github.com/martinholovsky开发48227 次安装47 周前更新
代码仓库

关于 vue-nuxt

面向 Vue 3 和 Nuxt 3 开发的技能指南,聚焦 JARVIS AI Assistant 的 HUD 界面,并强调安全、性能与 TypeScript。适合构建响应式组件、服务端路由和 3D 界面,提供测试、输入清理及部署检查模式。

主要功能

  1. 01Vue 3 Composition API 与 TypeScript
  2. 02Nuxt 服务端路由和安全配置
  3. 03输入校验与 HTML 清理
  4. 04响应式性能优化和延迟加载
  5. 05组件测试与安全验证

适用场景

  1. 01构建 JARVIS HUD 组件和 3D 场景
  2. 02实现经校验的 API 路由
  3. 03防护动态内容中的 XSS 风险
  4. 04部署前检查类型、漏洞和构建

安装

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

$npx skills add https://github.com/martinholovsky/claude-skills-generator --skill vue-nuxt

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

附带文件references/advanced-patterns.mdreferences/security-examples.md

详细介绍

Vue 3 / Nuxt 3 开发技能

文件组织:此技能采用拆分式结构。高级模式和安全示例请参阅 references/。

1. 概述

此技能提供使用 Vue 3 和 Nuxt 3 构建 JARVIS AI 助手用户界面的专业知识,重点介绍如何通过安全优先的开发实践,创建响应式、高性能的 3D HUD 界面。

风险级别:中 — 处理用户输入、渲染动态内容,可能存在 XSS 攻击向量

主要用例:

  • 为 JARVIS 界面构建响应式 3D HUD 组件
  • 通过服务端渲染提升初始加载性能
  • 集成客户端状态管理
  • 安全处理用户输入和 API 响应

2. 核心职责

2.1 基本原则
  1. TDD 优先:先编写测试,再实现功能,遵循红灯/绿灯/重构循环
  2. 关注性能:使用 computed、shallowRef 和惰性组件,实现最佳响应性
  3. 优先使用组合式 API:使用 Vue 3 组合式 API 和 <script setup>,以改善 TypeScript 类型推断和代码组织
  4. 服务端安全:利用 Nuxt 服务端路由处理敏感操作,绝不向客户端暴露机密信息
  5. 响应式状态安全:使用 ref() 和 reactive(),并设置适当的类型,以防止状态损坏
  6. 输入净化:在渲染或处理用户输入之前,始终对其进行净化
  7. 性能优化:实现延迟加载、代码分割和高效响应式处理,提升 3D HUD 性能
  8. 类型安全:全程使用 TypeScript,以便在编译时检测错误
  9. 安全默认值:配置 CSP 标头,并默认禁用危险功能

3. 技术栈与版本

3.1 建议版本
包版本安全说明
Vue^3.4.0最新稳定版本,响应式能力有所改进
Nuxt^3.12.4+严重:修复 CVE-2024-34344 RCE
@nuxt/devtools^1.3.9+严重:修复 CVE-2024-23657
vite^5.0.0最新版本,包含安全补丁
3.2 安全关键依赖
{
  "dependencies": {
    "nuxt": "^3.12.4",
    "vue": "^3.4.0",
    "dompurify": "^3.0.6",
    "isomorphic-dompurify": "^2.0.0"
  },
  "devDependencies": {
    "@nuxt/devtools": "^1.3.9",
    "eslint-plugin-vue": "^9.0.0",
    "eslint-plugin-security": "^2.0.0"
  }
}

4. 实现模式

4.1 安全的组件结构
<script setup lang="ts">
// ✅ Type-safe props with validation
interface Props {
  hudData: HUDDisplayData
  userId: string
}

const props = defineProps<Props>()

// ✅ Emit events with typed payloads
const emit = defineEmits<{
  'update:status': [status: string]
  'command:execute': [command: JARVISCommand]
}>()

// ✅ Secure ref initialization
const displayState = ref<HUDState>({
  isActive: false,
  securityLevel: 'standard'
})
</script>

<template>
  
  <div class="hud-panel">
    <span v-text="props.hudData.title" />
  </div>
</template>
4.2 输入净化模式
// composables/useSanitize.ts
import DOMPurify from 'isomorphic-dompurify'

export function useSanitize() {
  const sanitizeHTML = (dirty: string): string => {
    // ✅ Strict sanitization for any HTML content
    return DOMPurify.sanitize(dirty, {
      ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'span'],
      ALLOWED_ATTR: ['class']
    })
  }

  const sanitizeText = (input: string): string => {
    // ✅ Strip all HTML for plain text
    return DOMPurify.sanitize(input, { ALLOWED_TAGS: [] })
  }

  return { sanitizeHTML, sanitizeText }
}
4.3 安全的 API 路由模式
// server/api/jarvis/command.post.ts
import { z } from 'zod'

// ✅ Define strict schema for command validation
const commandSchema = z.object({
  action: z.enum(['status', 'control', 'query']),
  target: z.string().max(100).regex(/^[a-zA-Z0-9-_]+$/),
  parameters: z.record(z.string()).optional()
})

export default defineEventHandler(async (event) => {
  const body = await readBody(event)

  // ✅ Validate input against schema
  const result = commandSchema.safeParse(body)
  if (!result.success) {
    throw createError({
      statusCode: 400,
      message: 'Invalid command format'  // ✅ Generic error message
    })
  }

  // ✅ Process validated command
  const command = result.data

  // Never log sensitive data
  console.log(`Processing command: ${command.action}`)

  return { success: true, commandId: generateSecureId() }
})
4.4 安全的环境配置
// nuxt.config.ts
export default defineNuxtConfig({
  // ✅ Security headers
  routeRules: {
    '/**': {
      headers: {
        'Content-Security-Policy': "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'",
        'X-Content-Type-Options': 'nosniff',
        'X-Frame-Options': 'DENY',
        'X-XSS-Protection': '1; mode=block'
      }
    }
  },

  // ✅ Runtime config - secrets stay server-side
  runtimeConfig: {
    apiSecret: process.env.API_SECRET,  // Server only
    public: {
      apiBase: '/api'  // Client accessible
    }
  },

  // ✅ Disable devtools in production
  devtools: { enabled: process.env.NODE_ENV === 'development' }
})
4.5 3D HUD 组件集成
<script setup lang="ts">
// components/HUDDisplay.vue
import { TresCanvas } from '@tresjs/core'

const props = defineProps<{
  metrics: SystemMetrics
}>()

// ✅ Validate metrics before rendering
const validatedMetrics = computed(() => {
  return {
    cpu: Math.min(100, Math.max(0, props.metrics.cpu)),
    memory: Math.min(100, Math.max(0, props.metrics.memory)),
    status: sanitizeText(props.metrics.status)
  }
})
</script>

<template>
  <TresCanvas>
    <HUDMetricsDisplay :data="validatedMetrics" />
  </TresCanvas>
</template>

5. 实现工作流(TDD)

5.1 步骤 1:先编写失败的测试

始终先编写测试,明确预期行为:

// tests/components/VoiceIndicator.test.ts
import { describe, it, expect } from 'vitest'
import { mount } from '@vue/test-utils'
import VoiceIndicator from '@/components/VoiceIndicator.vue'

describe('VoiceIndicator', () => {
  it('displays idle state by default', () => {
    const wrapper = mount(VoiceIndicator)
    expect(wrapper.find('.indicator').classes()).toContain('idle')
    expect(wrapper.text()).toContain('Ready')
  })

  it('shows listening state when active', async () => {
    const wrapper = mount(VoiceIndicator, {
      props: { isListening: true }
    })
    expect(wrapper.find('.indicator').classes()).toContain('listening')
    expect(wrapper.find('.pulse-animation').exists()).toBe(true)
  })

  it('emits cancel event on escape key', async () => {
    const wrapper = mount(VoiceIndicator, {
      props: { isListening: true }
    })
    await wrapper.trigger('keydown.escape')
    expect(wrapper.emitted('cancel')).toBeTruthy()
  })
})
5.2 步骤 2:仅实现通过测试所需的内容

只编写足以让测试通过的代码:

<script setup lang="ts">
const props = defineProps<{ isListening?: boolean }>()
const emit = defineEmits<{ 'cancel': [] }>()

const handleKeydown = (e: KeyboardEvent) => {
  if (e.key === 'Escape') emit('cancel')
}
</script>

<template>
  <div
    class="indicator"
    :class="isListening ? 'listening' : 'idle'"
    @keydown="handleKeydown"
    tabindex="0"
  >
    <span v-if="!isListening">Ready</span>
    <div v-else class="pulse-animation" />
  </div>
</template>
5.3 步骤 3:按需重构

测试通过后,在不改变行为的前提下改进代码质量。每次重构后都要重新运行测试。

5.4 步骤 4:运行完整验证
# Run all verification steps before committing
npx vitest run                    # Unit tests
npx eslint . --ext .vue,.ts       # Linting
npx nuxi typecheck                # Type checking
npm run build                     # Build verification

6. 性能模式

6.1 使用计算属性派生状态
// ❌ BAD - Recalculates in template on every render
<template>
  <div>{{ items.filter(i => i.active).length }} active</div>
</template>

// ✅ GOOD - Cached until dependencies change
const activeCount = computed(() => items.value.filter(i => i.active).length)
<template>
  <div>{{ activeCount }} active</div>
</template>
6.2 对大型对象使用 shallowRef
// ❌ BAD - Deep reactivity on large 3D data
const meshData = ref<MeshData>({ vertices: new Float32Array(100000), ... })

// ✅ GOOD - Shallow reactivity, manual trigger
const meshData = shallowRef<MeshData>({ vertices: new Float32Array(100000), ... })
// Trigger update explicitly
meshData.value = { ...newData }
triggerRef(meshData)
6.3 使用 defineAsyncComponent 实现延迟加载
// ❌ BAD - All components loaded upfront
import HeavyChart from '@/components/HeavyChart.vue'

// ✅ GOOD - Load only when needed
const HeavyChart = defineAsyncComponent(() =>
  import('@/components/HeavyChart.vue')
)

// With loading state
const HeavyChart = defineAsyncComponent({
  loader: () => import('@/components/HeavyChart.vue'),
  loadingComponent: LoadingSpinner,
  delay: 200
})
6.4 使用 v-memo 优化列表

<div v-for="item in items" :key="item.id">
  <ExpensiveComponent :data="item" />
</div>


<div v-for="item in items" :key="item.id" v-memo="[item.id, item.updated]">
  <ExpensiveComponent :data="item" />
</div>
6.5 对长列表使用虚拟滚动
<script setup lang="ts">
import { useVirtualList } from '@vueuse/core'

const { list, containerProps, wrapperProps } = useVirtualList(
  items,
  { itemHeight: 50 }
)
</script>

<template>
  
  <div v-bind="containerProps" class="h-[400px] overflow-auto">
    <div v-bind="wrapperProps">
      <div v-for="{ data, index } in list" :key="index">
        {{ data.name }}
      </div>
    </div>
  </div>
</template>
6.6 使用防抖侦听器
// ❌ BAD - Fires on every keystroke
watch(searchQuery, async (query) => {
  results.value = await searchAPI(query)
})

// ✅ GOOD - Debounced to reduce API calls
import { watchDebounced } from '@vueuse/core'

watchDebounced(
  searchQuery,
  async (query) => {
    results.value = await searchAPI(query)
  },
  { debounce: 300 }
)

// Alternative with manual debounce
watch(searchQuery, useDebounceFn(async (query) => {
  results.value = await searchAPI(query)
}, 300))

7. 安全标准

7.1 已知漏洞(CVE 研究)
CVE严重性描述缓解措施
CVE-2024-34344高通过测试组件实现 Nuxt 远程代码执行(RCE)更新至 Nuxt 3.12.4+
CVE-2024-23657高Devtools 路径遍历/远程代码执行(RCE)将 devtools 更新至 1.3.9+
CVE-2023-3224严重开发服务器代码注入更新至 Nuxt 3.4.4+,绝不暴露开发服务器

参见:references/security-examples.md,了解详细的缓解措施代码

5.2 OWASP Top 10 覆盖情况
OWASP 类别风险缓解策略
A01 访问控制失效高服务端路由防护、身份验证中间件
A03 注入高使用 Zod 验证输入、参数化查询
A05 安全配置错误中CSP 标头、安全的 nuxt.config
A07 XSS高v-text 指令、使用 DOMPurify 清理
5.3 输入验证框架
// ❌ DANGEROUS - Direct v-html with user input
<div v-html="userMessage" />

// ✅ SECURE - Sanitized HTML or plain text
<div v-html="sanitizeHTML(userMessage)" />
<span v-text="userMessage" />
5.4 身份验证中间件
// middleware/auth.ts
export default defineNuxtRouteMiddleware((to) => {
  const { authenticated } = useAuthState()

  if (!authenticated.value && to.meta.requiresAuth) {
    return navigateTo('/login')
  }
})

6. 测试与质量

6.1 安全测试
// tests/security/xss.test.ts
import { describe, it, expect } from 'vitest'
import { mount } from '@vue/test-utils'
import HUDPanel from '@/components/HUDPanel.vue'

describe('XSS Prevention', () => {
  it('should sanitize malicious input', () => {
    const wrapper = mount(HUDPanel, {
      props: {
        title: '<script>alert("xss")</script>Hello'
      }
    })

    expect(wrapper.html()).not.toContain('<script>')
    expect(wrapper.text()).toContain('Hello')
  })
})
6.2 组件测试
// tests/components/HUDDisplay.test.ts
describe('HUDDisplay', () => {
  it('validates metric bounds', () => {
    const wrapper = mount(HUDDisplay, {
      props: {
        metrics: { cpu: 150, memory: -10, status: 'active' }
      }
    })

    // Should clamp values to valid range
    expect(wrapper.vm.validatedMetrics.cpu).toBe(100)
    expect(wrapper.vm.validatedMetrics.memory).toBe(0)
  })
})

7. 常见模式 / 工作流

7.1 JARVIS HUD 组件工作流
  1. 定义 TypeScript 接口,涵盖所有数据结构
  2. 创建组合式函数,封装共享逻辑
  3. 使用 Composition API 实现组件
  4. 在组件边界处添加输入验证
  5. 编写安全测试,检查 XSS/注入
  6. 通过 TresJS 与 3D 场景集成
7.2 API 集成工作流
  1. 定义 Zod 架构,用于请求/响应
  2. 创建服务端路由并进行验证
  3. 创建客户端组合式函数并处理错误
  4. 为 UI 添加加载/错误状态
  5. 测试错误情况和边界条件

8. 常见错误与反模式

8.1 严重安全反模式
切勿:对未清理的输入使用 v-html

<div v-html="userProvidedContent" />


<div v-html="sanitizeHTML(userProvidedContent)" />


<span v-text="userProvidedContent" />
切勿:在客户端代码中暴露机密信息
// ❌ DANGEROUS - Secret in public config
runtimeConfig: {
  public: {
    apiKey: process.env.API_KEY  // Exposed to client!
  }
}

// ✅ SECURE - Secrets stay server-side
runtimeConfig: {
  apiKey: process.env.API_KEY,  // Server only
  public: {
    apiBase: '/api'
  }
}
切勿:只信任客户端验证
// ❌ DANGEROUS - Client-only validation
const handleSubmit = () => {
  if (isValidEmail(email.value)) {
    $fetch('/api/subscribe', { body: { email: email.value } })
  }
}

// ✅ SECURE - Server-side validation
// server/api/subscribe.post.ts
export default defineEventHandler(async (event) => {
  const body = await readBody(event)
  const result = emailSchema.safeParse(body)
  if (!result.success) {
    throw createError({ statusCode: 400, message: 'Invalid email' })
  }
  // Process validated email
})
8.2 性能反模式
避免:在 computed 中使用响应式数组
// ❌ BAD - Creates new array on every access
const filtered = computed(() => {
  return items.value.filter(i => i.active).sort()
})

// ✅ GOOD - Memoized with stable reference
const filtered = computed(() => {
  const result = items.value.filter(i => i.active)
  result.sort((a, b) => a.name.localeCompare(b.name))
  return result
})

9. 快速参考

基本命令
# Development
npx nuxi dev --host  # Never expose to public network!

# Security audit
npm audit --audit-level=high
npx nuxi typecheck

# Production build
npx nuxi build
关键组合式函数
// State management
const state = useState<T>('key', () => initialValue)

// Runtime config access
const config = useRuntimeConfig()

// Route navigation
const router = useRouter()
await navigateTo('/path')

13. 部署前检查清单

安全验证
  • Nuxt 版本 >= 3.12.4(修复 CVE-2024-34344)
  • Devtools 版本 >= 1.3.9(修复 CVE-2024-23657)
  • 已在 nuxt.config 中配置 CSP 标头
  • runtimeConfig.public 中没有机密信息
  • 已使用 DOMPurify 清理所有用户输入
  • 服务端路由已使用 Zod 架构进行验证
  • 受保护的路由上已启用身份验证中间件
  • 已在生产环境中禁用 Devtools
构建验证
  • npm audit 未发现高危或严重漏洞
  • TypeScript 编译通过
  • 所有安全测试均通过
  • 生产构建顺利完成,没有错误

14. 总结

此 Vue/Nuxt 技能为构建 JARVIS AI 助手 HUD 界面提供了安全模式:

  1. 安全优先:始终清理输入、在服务端进行验证,并使用 CSP 标头
  2. 类型安全:全程使用 TypeScript 和严格的验证架构
  3. 性能:使用 Composition API、延迟加载和高效的响应式机制
  4. 可维护性:采用清晰的组件结构,并使用组合式函数实现复用

请记住:JARVIS HUD 会处理敏感的系统数据。每个组件都必须将用户输入视为潜在的恶意内容,并验证所有数据边界。


参考资料:

  • references/advanced-patterns.md - 复杂组件模式
  • references/security-examples.md - 详细的安全实现

评论

支持 Markdown