编辑 | blame | 历史 | 原始文档

---
name: frontend-code-review

description: Vue 3 + TypeScript 项目前端代码审查指南

前端代码审查技能

何时使用

在以下场景激活此技能:
- 审查 Pull Request
- 进行 Vue 组件代码审查
- 检查安全漏洞
- 验证 TypeScript 类型安全
- 审查性能优化

工作原理

此技能提供前端代码审查的检查清单和指南。

审查清单

TypeScript 和类型

  • [ ] 没有不合理的 any 类型
  • [ ] Props 和 Emits 有正确的 TypeScript 接口
  • [ ] API 响应有类型接口
  • [ ] 正确使用泛型
  • [ ] 类型导入使用 import type 语法

Vue 组件

  • [ ] 使用 <script setup> 语法
  • [ ] 可选 Props 有默认值
  • [ ] Emits 使用 TypeScript 类型
  • [ ] 没有直接修改 props
  • [ ] 正确使用 computed vs watch
  • [ ] 在 onUnmounted 中清理副作用

安全性

  • [ ] 没有 XSS 漏洞(用户内容使用 v-dompurify-html
  • [ ] 没有硬编码的密钥或 API Key
  • [ ] 用户输入已过滤
  • [ ] 敏感数据不在 localStorage(使用 secure-ls 或 sessionStorage)
  • [ ] CSRF token 正确处理

性能

  • [ ] 大列表使用虚拟滚动
  • [ ] 图片已优化
  • [ ] 路由懒加载
  • [ ] 没有不必要的重渲染
  • [ ] 正确使用 v-memov-once

可访问性

  • [ ] 正确的 ARIA 属性
  • [ ] 键盘导航可用
  • [ ] 颜色对比度足够
  • [ ] 模态框焦点管理

代码质量

  • [ ] 函数职责单一
  • [ ] 没有重复代码(提取到组合式函数)
  • [ ] 错误处理完善
  • [ ] 加载状态已处理
  • [ ] 边界情况已考虑

常见问题标记

1. 直接修改 Props

// 错误
props.value = newValue;

// 正确
emit('update:value', newValue);

2. 内存泄漏

// 错误 - 没有清理
onMounted(() => {
  window.addEventListener('resize', handleResize);
});

// 正确 - 组件卸载时清理
onMounted(() => {
  window.addEventListener('resize', handleResize);
});

onUnmounted(() => {
  window.removeEventListener('resize', handleResize);
});

3. 不必要的响应式

// 错误 - 静态数据不需要响应式
const menuItems = reactive([
  { label: '首页', path: '/' },
  { label: '关于', path: '/about' },
]);

// 正确 - 静态数据不需要响应式
const menuItems = [
  { label: '首页', path: '/' },
  { label: '关于', path: '/about' },
];

4. 缺少错误边界

<!-- 错误 - 没有错误处理 -->
<template>
  <ExpensiveComponent />
</template>

<!-- 正确 - 有错误边界 -->
<template>
  <ErrorBoundary>
    <ExpensiveComponent />
  </ErrorBoundary>
</template>

安全红线

  1. XSS 风险
  • 使用 v-html 但没有过滤
  • 渲染用户生成的内容
  • 通过 window.location 进行 URL 注入
  1. 数据泄露
  • 控制台输出敏感数据
  • Token 在 localStorage 中未加密
  • 源代码中有 API Key
  1. 注入风险
  • 动态组件名来自用户输入
  • 使用 eval()Function()
  • API 调用中的 SQL 注入

审查意见格式

使用建设性的评论:

**建议**: 这里考虑使用 `computed` 替代 `watch` 以获得更好的性能。

// 当前代码
watch(() => props.value, (val) => {
doubled.value = val * 2;
});

// 建议修改
const doubled = computed(() => props.value * 2);
```

原因: 计算属性有缓存,只有依赖变化时才重新计算。
```