vue-nuxt

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Vue 3 / Nuxt 3 Development Skill

Vue 3 / Nuxt 3 开发技能

File Organization: This skill uses split structure. See
references/
for advanced patterns and security examples.
文件组织:本技能采用拆分结构。高级模式和安全示例请查看
references/
目录。

1. Overview

1. 概述

This skill provides expertise for building the JARVIS AI Assistant user interface using Vue 3 and Nuxt 3. It focuses on creating responsive, performant 3D HUD interfaces with security-first development practices.
Risk Level: MEDIUM - Handles user input, renders dynamic content, potential XSS vectors
Primary Use Cases:
  • Building reactive 3D HUD components for JARVIS interface
  • Server-side rendering for initial load performance
  • Client-side state management integration
  • Secure handling of user inputs and API responses
本技能提供使用Vue 3和Nuxt 3构建JARVIS AI助手用户界面的专业方案,专注于创建响应式、高性能的3D HUD界面,并遵循安全优先的开发实践。
风险等级:中等 - 处理用户输入,渲染动态内容,存在潜在XSS攻击风险
主要使用场景
  • 为JARVIS界面构建响应式3D HUD组件
  • 服务端渲染优化初始加载性能
  • 客户端状态管理集成
  • 安全处理用户输入和API响应

2. Core Responsibilities

2. 核心职责

2.1 Fundamental Principles

2.1 基本原则

  1. TDD First: Write tests before implementation - red/green/refactor cycle
  2. Performance Aware: Use computed, shallowRef, lazy components for optimal reactivity
  3. Composition API First: Use Vue 3 Composition API with
    <script setup>
    for better TypeScript inference and code organization
  4. Server-Side Security: Leverage Nuxt's server routes for sensitive operations, never expose secrets to client
  5. Reactive State Safety: Use
    ref()
    and
    reactive()
    with proper typing to prevent state corruption
  6. Input Sanitization: Always sanitize user inputs before rendering or processing
  7. Performance Optimization: Implement lazy loading, code splitting, and efficient reactivity for 3D HUD performance
  8. Type Safety: Enforce TypeScript throughout for compile-time error detection
  9. Secure Defaults: Configure CSP headers, disable dangerous features by default
  1. 测试驱动开发优先:先编写测试再实现功能 - 红/绿/重构循环
  2. 性能感知:使用computed、shallowRef、懒加载组件实现最优响应式
  3. 组合式API优先:使用Vue 3 Composition API结合
    <script setup>
    ,提升TypeScript类型推断能力和代码组织性
  4. 服务端安全:利用Nuxt的服务端路由处理敏感操作,绝不向客户端暴露密钥
  5. 响应式状态安全:使用
    ref()
    reactive()
    并配合正确类型定义,防止状态损坏
  6. 输入 sanitization:在渲染或处理前始终对用户输入进行清理
  7. 性能优化:实现懒加载、代码分割和高效响应式,优化3D HUD性能
  8. 类型安全:全程使用TypeScript进行编译时错误检测
  9. 安全默认配置:配置CSP头,默认禁用危险特性

3. Technology Stack & Versions

3. 技术栈与版本

3.1 Recommended Versions

3.1 推荐版本

PackageVersionSecurity Notes
Vue^3.4.0Latest stable with improved reactivity
Nuxt^3.12.4+CRITICAL: Fixes CVE-2024-34344 RCE
@nuxt/devtools^1.3.9+CRITICAL: Fixes CVE-2024-23657
vite^5.0.0Latest with security patches
包名版本安全说明
Vue^3.4.0最新稳定版,响应式系统优化
Nuxt^3.12.4+关键:修复CVE-2024-34344远程代码执行漏洞
@nuxt/devtools^1.3.9+关键:修复CVE-2024-23657漏洞
vite^5.0.0最新版本,包含安全补丁

3.2 Security-Critical Dependencies

3.2 安全关键依赖

json
{
  "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"
  }
}
json
{
  "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. Implementation Patterns

4. 实现模式

4.1 Secure Component Structure

4.1 安全组件结构

vue
<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>
  <!-- ✅ Use v-text for user content to prevent XSS -->
  <div class="hud-panel">
    <span v-text="props.hudData.title" />
  </div>
</template>
vue
<script setup lang="ts">
// ✅ 带验证的类型安全Props
interface Props {
  hudData: HUDDisplayData
  userId: string
}

const props = defineProps<Props>()

// ✅ 带类型化负载的事件触发
const emit = defineEmits<{
  'update:status': [status: string]
  'command:execute': [command: JARVISCommand]
}>()

// ✅ 安全的ref初始化
const displayState = ref<HUDState>({
  isActive: false,
  securityLevel: 'standard'
})
</script>

<template>
  <!-- ✅ 使用v-text渲染用户内容,防止XSS -->
  <div class="hud-panel">
    <span v-text="props.hudData.title" />
  </div>
</template>

4.2 Input Sanitization Pattern

4.2 输入清理模式

typescript
// 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 }
}
typescript
// composables/useSanitize.ts
import DOMPurify from 'isomorphic-dompurify'

export function useSanitize() {
  const sanitizeHTML = (dirty: string): string => {
    // ✅ 对所有HTML内容进行严格清理
    return DOMPurify.sanitize(dirty, {
      ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'span'],
      ALLOWED_ATTR: ['class']
    })
  }

  const sanitizeText = (input: string): string => {
    // ✅ 剥离所有HTML标签,保留纯文本
    return DOMPurify.sanitize(input, { ALLOWED_TAGS: [] })
  }

  return { sanitizeHTML, sanitizeText }
}

4.3 Secure API Route Pattern

4.3 安全API路由模式

typescript
// 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() }
})
typescript
// server/api/jarvis/command.post.ts
import { z } from 'zod'

// ✅ 定义严格的命令验证Schema
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)

  // ✅ 验证输入是否符合Schema
  const result = commandSchema.safeParse(body)
  if (!result.success) {
    throw createError({
      statusCode: 400,
      message: 'Invalid command format'  // ✅ 通用错误提示
    })
  }

  // ✅ 处理验证通过的命令
  const command = result.data

  // 绝不要记录敏感数据
  console.log(`Processing command: ${command.action}`)

  return { success: true, commandId: generateSecureId() }
})

4.4 Secure Environment Configuration

4.4 安全环境配置

typescript
// 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' }
})
typescript
// nuxt.config.ts
export default defineNuxtConfig({
  // ✅ 安全头配置
  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'
      }
    }
  },

  // ✅ 运行时配置 - 密钥仅保留在服务端
  runtimeConfig: {
    apiSecret: process.env.API_SECRET,  // 仅服务端可访问
    public: {
      apiBase: '/api'  // 客户端可访问
    }
  },

  // ✅ 生产环境禁用DevTools
  devtools: { enabled: process.env.NODE_ENV === 'development' }
})

4.5 3D HUD Component Integration

4.5 3D HUD组件集成

vue
<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>
vue
<script setup lang="ts">
// components/HUDDisplay.vue
import { TresCanvas } from '@tresjs/core'

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

// ✅ 渲染前验证指标数据
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. Implementation Workflow (TDD)

5. 实现工作流(TDD)

5.1 Step 1: Write Failing Test First

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

Always start by writing tests that define expected behavior:
typescript
// 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()
  })
})
始终从编写定义预期行为的测试开始:
typescript
// 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('默认显示空闲状态', () => {
    const wrapper = mount(VoiceIndicator)
    expect(wrapper.find('.indicator').classes()).toContain('idle')
    expect(wrapper.text()).toContain('Ready')
  })

  it('激活时显示监听状态', async () => {
    const wrapper = mount(VoiceIndicator, {
      props: { isListening: true }
    })
    expect(wrapper.find('.indicator').classes()).toContain('listening')
    expect(wrapper.find('.pulse-animation').exists()).toBe(true)
  })

  it('按下ESC键时触发取消事件', async () => {
    const wrapper = mount(VoiceIndicator, {
      props: { isListening: true }
    })
    await wrapper.trigger('keydown.escape')
    expect(wrapper.emitted('cancel')).toBeTruthy()
  })
})

5.2 Step 2: Implement Minimum to Pass

5.2 步骤2:编写最小代码使测试通过

Write only enough code to make the tests pass:
vue
<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>
仅编写足够的代码让测试通过:
vue
<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 Step 3: Refactor if Needed

5.3 步骤3:按需重构

After tests pass, improve code quality without changing behavior. Re-run tests after each refactor.
测试通过后,在不改变功能的前提下优化代码质量。每次重构后重新运行测试。

5.4 Step 4: Run Full Verification

5.4 步骤4:运行完整验证

bash
undefined
bash
undefined

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
undefined
npx vitest run # 单元测试 npx eslint . --ext .vue,.ts # 代码检查 npx nuxi typecheck # 类型检查 npm run build # 构建验证
undefined

6. Performance Patterns

6. 性能优化模式

6.1 Computed Properties for Derived State

6.1 使用计算属性处理派生状态

typescript
// ❌ 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>
typescript
// ❌ 不良实践 - 每次渲染时在模板中重复计算
<template>
  <div>{{ items.filter(i => i.active).length }} 个激活项</div>
</template>

// ✅ 最佳实践 - 缓存结果,仅在依赖变化时重新计算
const activeCount = computed(() => items.value.filter(i => i.active).length)
<template>
  <div>{{ activeCount }} 个激活项</div>
</template>

6.2 shallowRef for Large Objects

6.2 对大型对象使用shallowRef

typescript
// ❌ 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)
typescript
// ❌ 不良实践 - 对大型3D数据启用深度响应式
const meshData = ref<MeshData>({ vertices: new Float32Array(100000), ... })

// ✅ 最佳实践 - 浅响应式,手动触发更新
const meshData = shallowRef<MeshData>({ vertices: new Float32Array(100000), ... })
// 显式触发更新
meshData.value = { ...newData }
triggerRef(meshData)

6.3 defineAsyncComponent for Lazy Loading

6.3 使用defineAsyncComponent实现懒加载

typescript
// ❌ 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
})
typescript
// ❌ 不良实践 - 所有组件初始时全部加载
import HeavyChart from '@/components/HeavyChart.vue'

// ✅ 最佳实践 - 仅在需要时加载
const HeavyChart = defineAsyncComponent(() =>
  import('@/components/HeavyChart.vue')
)

// 带加载状态的懒加载
const HeavyChart = defineAsyncComponent({
  loader: () => import('@/components/HeavyChart.vue'),
  loadingComponent: LoadingSpinner,
  delay: 200
})

6.4 v-memo for List Optimization

6.4 使用v-memo优化列表渲染

vue
<!-- ❌ BAD - Re-renders all items on any change -->
<div v-for="item in items" :key="item.id">
  <ExpensiveComponent :data="item" />
</div>

<!-- ✅ GOOD - Skip re-render if item unchanged -->
<div v-for="item in items" :key="item.id" v-memo="[item.id, item.updated]">
  <ExpensiveComponent :data="item" />
</div>
vue
<!-- ❌ 不良实践 - 任何变更都会重新渲染所有项 -->
<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 Virtual Scrolling for Long Lists

6.5 虚拟滚动处理长列表

vue
<script setup lang="ts">
import { useVirtualList } from '@vueuse/core'

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

<template>
  <!-- ✅ Only renders visible items -->
  <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>
vue
<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 Debounced Watchers

6.6 防抖监听器

typescript
// ❌ 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))
typescript
// ❌ 不良实践 - 每次按键都触发
watch(searchQuery, async (query) => {
  results.value = await searchAPI(query)
})

// ✅ 最佳实践 - 防抖减少API调用
import { watchDebounced } from '@vueuse/core'

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

// 手动防抖的替代方案
watch(searchQuery, useDebounceFn(async (query) => {
  results.value = await searchAPI(query)
}, 300))

7. Security Standards

7. 安全标准

7.1 Known Vulnerabilities (CVE Research)

7.1 已知漏洞(CVE研究)

CVESeverityDescriptionMitigation
CVE-2024-34344HIGHNuxt RCE via test componentUpdate to Nuxt 3.12.4+
CVE-2024-23657HIGHDevtools path traversal/RCEUpdate devtools to 1.3.9+
CVE-2023-3224CRITICALDev server code injectionUpdate to Nuxt 3.4.4+, never expose dev server
See:
references/security-examples.md
for detailed mitigation code
CVE编号严重程度描述缓解方案
CVE-2024-34344高危Nuxt测试组件存在远程代码执行漏洞升级至Nuxt 3.12.4+
CVE-2024-23657高危DevTools存在路径遍历/远程代码执行漏洞升级DevTools至1.3.9+
CVE-2023-3224严重开发服务器存在代码注入漏洞升级至Nuxt 3.4.4+,绝不对外暴露开发服务器
参考
references/security-examples.md
包含详细的漏洞缓解代码

5.2 OWASP Top 10 Coverage

7.2 OWASP Top 10 覆盖情况

OWASP CategoryRiskMitigation Strategy
A01 Broken Access ControlHIGHServer-side route guards, middleware auth
A03 InjectionHIGHInput validation with Zod, parameterized queries
A05 Security MisconfigurationMEDIUMCSP headers, secure nuxt.config
A07 XSSHIGHv-text directive, DOMPurify sanitization
OWASP类别风险等级缓解策略
A01 访问控制失效高危服务端路由守卫,中间件鉴权
A03 注入攻击高危使用Zod进行输入验证,参数化查询
A05 安全配置错误中等CSP头配置,安全的nuxt.config设置
A07 XSS跨站脚本高危使用v-text指令,DOMPurify内容清理

5.3 Input Validation Framework

7.3 输入验证框架

typescript
// ❌ 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" />
typescript
// ❌ 危险 - 直接使用v-html渲染用户输入
<div v-html="userMessage" />

// ✅ 安全 - 使用清理后的HTML或纯文本
<div v-html="sanitizeHTML(userMessage)" />
<span v-text="userMessage" />

5.4 Authentication Middleware

7.4 鉴权中间件

typescript
// middleware/auth.ts
export default defineNuxtRouteMiddleware((to) => {
  const { authenticated } = useAuthState()

  if (!authenticated.value && to.meta.requiresAuth) {
    return navigateTo('/login')
  }
})
typescript
// middleware/auth.ts
export default defineNuxtRouteMiddleware((to) => {
  const { authenticated } = useAuthState()

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

6. Testing & Quality

8. 测试与质量保障

6.1 Security Testing

8.1 安全测试

typescript
// 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')
  })
})
typescript
// 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防护', () => {
  it('应清理恶意输入', () => {
    const wrapper = mount(HUDPanel, {
      props: {
        title: '<script>alert("xss")</script>Hello'
      }
    })

    expect(wrapper.html()).not.toContain('<script>')
    expect(wrapper.text()).toContain('Hello')
  })
})

6.2 Component Testing

8.2 组件测试

typescript
// 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)
  })
})
typescript
// tests/components/HUDDisplay.test.ts
describe('HUDDisplay', () => {
  it('验证指标数据范围', () => {
    const wrapper = mount(HUDDisplay, {
      props: {
        metrics: { cpu: 150, memory: -10, status: 'active' }
      }
    })

    // 应将值限制在有效范围内
    expect(wrapper.vm.validatedMetrics.cpu).toBe(100)
    expect(wrapper.vm.validatedMetrics.memory).toBe(0)
  })
})

7. Common Patterns / Workflows

9. 常用模式/工作流

7.1 JARVIS HUD Component Workflow

9.1 JARVIS HUD组件开发流程

  1. Define TypeScript interfaces for all data structures
  2. Create composable for shared logic
  3. Implement component with Composition API
  4. Add input validation at component boundary
  5. Write security tests for XSS/injection
  6. Integrate with 3D scene via TresJS
  1. 定义TypeScript接口规范所有数据结构
  2. 创建Composable封装共享逻辑
  3. 使用Composition API实现组件
  4. 在组件边界添加输入验证
  5. 编写XSS/注入攻击的安全测试
  6. 通过TresJS集成3D场景

7.2 API Integration Workflow

9.2 API集成流程

  1. Define Zod schema for request/response
  2. Create server route with validation
  3. Implement client composable with error handling
  4. Add loading/error states to UI
  5. Test error cases and edge conditions
  1. 定义Zod Schema验证请求/响应数据
  2. 创建服务端路由并添加验证逻辑
  3. 实现客户端Composable并处理错误
  4. 为UI添加加载/错误状态
  5. 测试错误场景和边界情况

8. Common Mistakes & Anti-Patterns

10. 常见错误与反模式

8.1 Critical Security Anti-Patterns

10.1 严重安全反模式

Never: Use v-html with Unsanitized Input

禁止:使用v-html渲染未清理的用户输入

vue
<!-- ❌ DANGEROUS - XSS vulnerability -->
<div v-html="userProvidedContent" />

<!-- ✅ SECURE - Sanitized content -->
<div v-html="sanitizeHTML(userProvidedContent)" />

<!-- ✅ BEST - Plain text when HTML not needed -->
<span v-text="userProvidedContent" />
vue
<!-- ❌ 危险 - 存在XSS漏洞 -->
<div v-html="userProvidedContent" />

<!-- ✅ 安全 - 使用清理后的内容 -->
<div v-html="sanitizeHTML(userProvidedContent)" />

<!-- ✅ 最佳 - 无需HTML时使用纯文本 -->
<span v-text="userProvidedContent" />

Never: Expose Secrets in Client Code

禁止:在客户端代码中暴露密钥

typescript
// ❌ 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'
  }
}
typescript
// ❌ 危险 - 密钥暴露在公共配置中
runtimeConfig: {
  public: {
    apiKey: process.env.API_KEY  // 会暴露给客户端!
  }
}

// ✅ 安全 - 密钥仅保留在服务端
runtimeConfig: {
  apiKey: process.env.API_KEY,  // 仅服务端可访问
  public: {
    apiBase: '/api'
  }
}

Never: Trust Client-Side Validation Alone

禁止:仅依赖客户端验证

typescript
// ❌ 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
})
typescript
// ❌ 危险 - 仅客户端验证
const handleSubmit = () => {
  if (isValidEmail(email.value)) {
    $fetch('/api/subscribe', { body: { email: email.value } })
  }
}

// ✅ 安全 - 服务端验证
// 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: '无效邮箱' })
  }
  // 处理验证通过的邮箱
})

8.2 Performance Anti-Patterns

10.2 性能反模式

Avoid: Reactive Arrays in Computed

避免:在计算属性中返回响应式数组

typescript
// ❌ 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
})
typescript
// ❌ 不良实践 - 每次访问时创建新数组
const filtered = computed(() => {
  return items.value.filter(i => i.active).sort()
})

// ✅ 最佳实践 - 稳定引用的 memoized 结果
const filtered = computed(() => {
  const result = items.value.filter(i => i.active)
  result.sort((a, b) => a.name.localeCompare(b.name))
  return result
})

9. Quick Reference

11. 快速参考

Essential Commands

常用命令

bash
undefined
bash
undefined

Development

开发

npx nuxi dev --host # Never expose to public network!
npx nuxi dev --host # 绝不要暴露到公网!

Security audit

安全审计

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

Production build

生产构建

npx nuxi build
undefined
npx nuxi build
undefined

Key Composables

核心Composable

typescript
// State management
const state = useState<T>('key', () => initialValue)

// Runtime config access
const config = useRuntimeConfig()

// Route navigation
const router = useRouter()
await navigateTo('/path')
typescript
// 状态管理
const state = useState<T>('key', () => initialValue)

// 运行时配置访问
const config = useRuntimeConfig()

// 路由导航
const router = useRouter()
await navigateTo('/path')

13. Pre-Deployment Checklist

12. 部署前检查清单

Security Verification

安全验证

  • Nuxt version >= 3.12.4 (CVE-2024-34344 fix)
  • Devtools version >= 1.3.9 (CVE-2024-23657 fix)
  • CSP headers configured in nuxt.config
  • No secrets in
    runtimeConfig.public
  • All user inputs sanitized with DOMPurify
  • Server routes validate with Zod schemas
  • Authentication middleware on protected routes
  • Devtools disabled in production
  • Nuxt版本 >= 3.12.4(修复CVE-2024-34344)
  • DevTools版本 >= 1.3.9(修复CVE-2024-23657)
  • nuxt.config中已配置CSP头
  • runtimeConfig.public
    中无密钥
  • 所有用户输入均通过DOMPurify清理
  • 服务端路由使用Zod Schema验证
  • 受保护路由已添加鉴权中间件
  • 生产环境已禁用DevTools

Build Verification

构建验证

  • npm audit
    shows no high/critical vulnerabilities
  • TypeScript compilation passes
  • All security tests pass
  • Production build completes without errors
  • npm audit
    无高危/严重漏洞
  • TypeScript编译通过
  • 所有安全测试通过
  • 生产构建无错误完成

14. Summary

13. 总结

This Vue/Nuxt skill provides secure patterns for building the JARVIS AI Assistant HUD interface:
  1. Security First: Always sanitize inputs, validate on server, use CSP headers
  2. Type Safety: TypeScript throughout with strict validation schemas
  3. Performance: Composition API, lazy loading, efficient reactivity
  4. Maintainability: Clear component structure, composables for reuse
Remember: The JARVIS HUD handles sensitive system data. Every component must treat user input as potentially malicious and validate all data boundaries.

References:
  • references/advanced-patterns.md
    - Complex component patterns
  • references/security-examples.md
    - Detailed security implementations
本Vue/Nuxt技能为构建JARVIS AI助手HUD界面提供了安全优先的开发模式:
  1. 安全优先:始终清理输入,服务端验证,使用CSP头
  2. 类型安全:全程使用TypeScript,配合严格的验证Schema
  3. 性能优化:Composition API、懒加载、高效响应式
  4. 可维护性:清晰的组件结构,Composable复用逻辑
谨记:JARVIS HUD处理敏感系统数据,每个组件都必须将用户输入视为潜在恶意,并验证所有数据边界。

参考资料:
  • references/advanced-patterns.md
    - 复杂组件模式
  • references/security-examples.md
    - 详细安全实现