vue-nuxt
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseVue 3 / Nuxt 3 Development Skill
Vue 3 / Nuxt 3 开发技能
File Organization: This skill uses split structure. Seefor advanced patterns and security examples.references/
文件组织:本技能采用拆分结构。高级模式和安全示例请查看目录。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 基本原则
- TDD First: Write tests before implementation - red/green/refactor cycle
- Performance Aware: Use computed, shallowRef, lazy components for optimal reactivity
- Composition API First: Use Vue 3 Composition API with for better TypeScript inference and code organization
<script setup> - Server-Side Security: Leverage Nuxt's server routes for sensitive operations, never expose secrets to client
- Reactive State Safety: Use and
ref()with proper typing to prevent state corruptionreactive() - Input Sanitization: Always sanitize user inputs before rendering or processing
- Performance Optimization: Implement lazy loading, code splitting, and efficient reactivity for 3D HUD performance
- Type Safety: Enforce TypeScript throughout for compile-time error detection
- Secure Defaults: Configure CSP headers, disable dangerous features by default
- 测试驱动开发优先:先编写测试再实现功能 - 红/绿/重构循环
- 性能感知:使用computed、shallowRef、懒加载组件实现最优响应式
- 组合式API优先:使用Vue 3 Composition API结合,提升TypeScript类型推断能力和代码组织性
<script setup> - 服务端安全:利用Nuxt的服务端路由处理敏感操作,绝不向客户端暴露密钥
- 响应式状态安全:使用和
ref()并配合正确类型定义,防止状态损坏reactive() - 输入 sanitization:在渲染或处理前始终对用户输入进行清理
- 性能优化:实现懒加载、代码分割和高效响应式,优化3D HUD性能
- 类型安全:全程使用TypeScript进行编译时错误检测
- 安全默认配置:配置CSP头,默认禁用危险特性
3. Technology Stack & Versions
3. 技术栈与版本
3.1 Recommended Versions
3.1 推荐版本
| Package | Version | Security Notes |
|---|---|---|
| Vue | ^3.4.0 | Latest 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.0 | Latest 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
undefinedbash
undefinedRun 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
undefinednpx vitest run # 单元测试
npx eslint . --ext .vue,.ts # 代码检查
npx nuxi typecheck # 类型检查
npm run build # 构建验证
undefined6. 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研究)
| CVE | Severity | Description | Mitigation |
|---|---|---|---|
| CVE-2024-34344 | HIGH | Nuxt RCE via test component | Update to Nuxt 3.12.4+ |
| CVE-2024-23657 | HIGH | Devtools path traversal/RCE | Update devtools to 1.3.9+ |
| CVE-2023-3224 | CRITICAL | Dev server code injection | Update to Nuxt 3.4.4+, never expose dev server |
See: for detailed mitigation code
references/security-examples.md| 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.md5.2 OWASP Top 10 Coverage
7.2 OWASP Top 10 覆盖情况
| OWASP Category | Risk | Mitigation Strategy |
|---|---|---|
| A01 Broken Access Control | HIGH | Server-side route guards, middleware auth |
| A03 Injection | HIGH | Input validation with Zod, parameterized queries |
| A05 Security Misconfiguration | MEDIUM | CSP headers, secure nuxt.config |
| A07 XSS | HIGH | v-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组件开发流程
- Define TypeScript interfaces for all data structures
- Create composable for shared logic
- Implement component with Composition API
- Add input validation at component boundary
- Write security tests for XSS/injection
- Integrate with 3D scene via TresJS
- 定义TypeScript接口规范所有数据结构
- 创建Composable封装共享逻辑
- 使用Composition API实现组件
- 在组件边界添加输入验证
- 编写XSS/注入攻击的安全测试
- 通过TresJS集成3D场景
7.2 API Integration Workflow
9.2 API集成流程
- Define Zod schema for request/response
- Create server route with validation
- Implement client composable with error handling
- Add loading/error states to UI
- Test error cases and edge conditions
- 定义Zod Schema验证请求/响应数据
- 创建服务端路由并添加验证逻辑
- 实现客户端Composable并处理错误
- 为UI添加加载/错误状态
- 测试错误场景和边界情况
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
undefinedbash
undefinedDevelopment
开发
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
undefinednpx nuxi build
undefinedKey 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
构建验证
- shows no high/critical vulnerabilities
npm audit - 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:
- Security First: Always sanitize inputs, validate on server, use CSP headers
- Type Safety: TypeScript throughout with strict validation schemas
- Performance: Composition API, lazy loading, efficient reactivity
- 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:
- - Complex component patterns
references/advanced-patterns.md - - Detailed security implementations
references/security-examples.md
本Vue/Nuxt技能为构建JARVIS AI助手HUD界面提供了安全优先的开发模式:
- 安全优先:始终清理输入,服务端验证,使用CSP头
- 类型安全:全程使用TypeScript,配合严格的验证Schema
- 性能优化:Composition API、懒加载、高效响应式
- 可维护性:清晰的组件结构,Composable复用逻辑
谨记:JARVIS HUD处理敏感系统数据,每个组件都必须将用户输入视为潜在恶意,并验证所有数据边界。
参考资料:
- - 复杂组件模式
references/advanced-patterns.md - - 详细安全实现
references/security-examples.md