Vue/Nuxt安全前端开发技能Skill vue-nuxt

此技能专注于使用 Vue 3 和 Nuxt 3 构建 JARVIS AI 助手的用户界面,强调安全第一的开发模式,包括响应式 3D HUD 组件、服务器端渲染、性能优化和安全处理用户输入。关键词:Vue 3, Nuxt 3, 前端开发, 安全开发, 3D HUD, AI助手UI, 性能优化, 测试驱动开发, TypeScript。

前端开发 0 次安装 0 次浏览 更新于 3/15/2026

name: vue-nuxt description: Vue 3 和 Nuxt 3 用于 JARVIS AI 助手用户界面开发,采用安全优先模式 model: sonnet risk_level: 中等 version: 1.0.0

Vue 3 / Nuxt 3 开发技能

文件组织:此技能采用分割结构。查看 references/ 获取高级模式和安全性示例。

1. 概述

此技能提供使用 Vue 3 和 Nuxt 3 构建 JARVIS AI 助手用户界面的专业知识。它专注于创建响应式、高性能的 3D HUD 界面,采用安全优先的开发实践。

风险等级:中等 - 处理用户输入,渲染动态内容,潜在 XSS 向量

主要用例

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

2. 核心职责

2.1 基本原则

  1. 测试驱动开发优先:先写测试再实现 - 红/绿/重构循环
  2. 性能意识:使用计算属性、浅引用、懒加载组件以实现最佳响应式
  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">
// ✅ 类型安全的属性与验证
interface Props {
  hudData: HUDDisplayData
  userId: string
}

const props = defineProps<Props>()

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

// ✅ 安全引用初始化
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 输入清理模式

// 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 安全 API 路由模式

// server/api/jarvis/command.post.ts
import { z } from 'zod'

// ✅ 定义严格模式用于命令验证
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)

  // ✅ 根据模式验证输入
  const result = commandSchema.safeParse(body)
  if (!result.success) {
    throw createError({
      statusCode: 400,
      message: '无效命令格式'  // ✅ 通用错误消息
    })
  }

  // ✅ 处理已验证命令
  const command = result.data

  // 永不记录敏感数据
  console.log(`处理命令:${command.action}`)

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

4.4 安全环境配置

// 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: { 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
}>()

// ✅ 在渲染前验证指标
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. 实现工作流程(测试驱动开发)

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('默认显示空闲状态', () => {
    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 步骤 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:运行全面验证

# 提交前运行所有验证步骤
npx vitest run                    # 单元测试
npx eslint . --ext .vue,.ts       # 代码检查
npx nuxi typecheck                # 类型检查
npm run build                     # 构建验证

6. 性能模式

6.1 用于派生状态的计算属性

// ❌ 坏 - 每次渲染都在模板中重新计算
<template>
  <div>{{ items.filter(i => i.active).length }} active</div>
</template>

// ✅ 好 - 缓存直到依赖项改变
const activeCount = computed(() => items.value.filter(i => i.active).length)
<template>
  <div>{{ activeCount }} active</div>
</template>

6.2 浅引用用于大型对象

// ❌ 坏 - 对大型 3D 数据进行深度响应式
const meshData = ref<MeshData>({ vertices: new Float32Array(100000), ... })

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

6.3 定义异步组件用于懒加载

// ❌ 坏 - 所有组件预先加载
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 用于列表优化

<!-- ❌ 坏 - 任何更改都重新渲染所有项 -->
<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 防抖监视器

// ❌ 坏 - 每次击键都触发
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. 安全标准

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 输入验证框架

// ❌ 危险 - 直接 v-html 与用户输入
<div v-html="userMessage" />

// ✅ 安全 - 清理的 HTML 或纯文本
<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 预防', () => {
  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 组件测试

// 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. 常见模式 / 工作流程

7.1 JARVIS HUD 组件工作流程

  1. 定义 TypeScript 接口 用于所有数据结构
  2. 创建可组合项 用于共享逻辑
  3. 实现组件 使用组合 API
  4. 添加输入验证 在组件边界
  5. 编写安全测试 用于 XSS/注入
  6. 集成 3D 场景 通过 TresJS

7.2 API 集成工作流程

  1. 定义 Zod 模式 用于请求/响应
  2. 创建服务器路由 带验证
  3. 实现客户端可组合项 带错误处理
  4. 添加加载/错误状态 到 UI
  5. 测试错误情况 和边缘条件

8. 常见错误与反模式

8.1 关键安全反模式

绝不:使用未清理输入的 v-html

<!-- ❌ 危险 - XSS 漏洞 -->
<div v-html="userProvidedContent" />

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

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

绝不:在客户端代码中暴露秘密

// ❌ 危险 - 公共配置中的秘密
runtimeConfig: {
  public: {
    apiKey: process.env.API_KEY  // 暴露给客户端!
  }
}

// ✅ 安全 - 秘密保持服务器端
runtimeConfig: {
  apiKey: process.env.API_KEY,  // 仅服务器
  public: {
    apiBase: '/api'
  }
}

绝不:仅信任客户端验证

// ❌ 危险 - 仅客户端验证
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 性能反模式

避免:在计算属性中使用响应式数组

// ❌ 坏 - 每次访问都创建新数组
const filtered = computed(() => {
  return items.value.filter(i => i.active).sort()
})

// ✅ 好 - 带稳定引用的记忆化
const filtered = computed(() => {
  const result = items.value.filter(i => i.active)
  result.sort((a, b) => a.name.localeCompare(b.name))
  return result
})

9. 快速参考

基本命令

# 开发
npx nuxi dev --host  # 永不暴露到公共网络!

# 安全审计
npm audit --audit-level=high
npx nuxi typecheck

# 生产构建
npx nuxi build

关键可组合项

// 状态管理
const state = useState<T>('key', () => initialValue)

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

// 路由导航
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 模式验证
  • [ ] 受保护路由使用认证中间件
  • [ ] 在生产中禁用开发工具

构建验证

  • [ ] npm audit 显示无高/关键漏洞
  • [ ] TypeScript 编译通过
  • [ ] 所有安全测试通过
  • [ ] 生产构建无错误完成

14. 总结

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

  1. 安全第一:始终清理输入,在服务器上验证,使用 CSP 头部
  2. 类型安全:全程使用 TypeScript,带严格验证模式
  3. 性能:组合 API,懒加载,高效响应式
  4. 可维护性:清晰的组件结构,可组合项用于重用

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


参考资料

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