CODING-STANDARDS.md
6.29 KB
代码规范
更新时间: 2026-02-05
本文档定义项目的代码规范。
📋 命名规范
文件命名
组件: PascalCase UserCard.vue
页面: PascalCase Dashboard/index.vue
API 文件: camelCase userAPI.js
工具函数: camelCase formatDate.js
常量文件: UPPER_CASE API_CONSTANTS.js
变量命名
// ✅ 正确
const userList = ref([])
const isLoading = ref(false)
const MAX_COUNT = 100
// ❌ 错误
const UserList = ref([])
const is_loading = ref(false)
const max_count = 100
函数命名
// ✅ 正确 - 动词开头
const fetchUserData = async () => {}
const handleSubmit = () => {}
const formatDate = (date) => {}
// ❌ 错误
const userData = async () => {} // 应该是 fetchUserData
const submit = () => {} // 应该是 handleSubmit
🎯 Vue 3 规范
组件定义
<script setup>
// 1. 导入
import { ref, computed, onMounted } from 'vue'
import { useLoad } from '@tarojs/taro'
import { userAPI } from '@/api/user'
// 2. Props 定义
const props = defineProps({
userId: {
type: Number,
required: true,
default: 0
}
})
// 3. Emits 定义
const emit = defineEmits(['update', 'delete'])
// 4. 响应式状态
const loading = ref(false)
const dataList = ref([])
// 5. 计算属性
const totalCount = computed(() => dataList.value.length)
// 6. 方法
const fetchData = async () => {
loading.value = true
try {
const res = await userAPI()
if (res.code === 1) {
dataList.value = res.data
}
} finally {
loading.value = false
}
}
// 7. 生命周期(Taro Hooks)
useLoad(() => {
fetchData()
})
</script>
Props 验证
// ✅ 正确 - 完整的类型和默认值
const props = defineProps({
userId: {
type: Number,
required: true,
default: 0
},
userName: {
type: String,
default: ''
},
isActive: {
type: Boolean,
default: false
}
})
// ❌ 错误 - 缺少类型
const props = defineProps(['userId', 'userName'])
Emits 定义
// ✅ 正确 - 定义事件名
const emit = defineEmits({
// 带验证的事件
update: (payload) => typeof payload.id === 'number',
// 无验证的事件
delete: null
})
// ❌ 错误 - 未定义事件
const emit = defineEmits()
🎨 样式规范
TailwindCSS 优先
<template>
<!-- ✅ 优先使用 TailwindCSS -->
<view class="flex items-center justify-between p-4 bg-white">
<text class="text-xl font-bold text-gray-900">标题</text>
</view>
</template>
<style lang="less" scoped>
/* ✅ 仅在必要时使用 Less */
.custom-element {
// 深度选择器
:deep(.nut-popup) {
background-color: #fff;
}
// 复杂动画
@keyframes slide-in {
from { transform: translateX(-100%); }
to { transform: translateX(0); }
}
}
</style>
样式作用域
<!-- ✅ 页面组件必须使用 scoped -->
<template>
<view class="page-container">...</view>
</template>
<style lang="less" scoped>
.page-container {
padding: 30px;
}
</style>
📡 API 调用规范
统一错误处理
// ✅ 正确 - 完整的错误处理
const fetchData = async () => {
loading.value = true
try {
const res = await userAPI()
if (res.code === 1) {
dataList.value = res.data
} else {
Taro.showToast({
title: res.msg || '请求失败',
icon: 'none'
})
}
} catch (err) {
console.error('请求失败:', err)
Taro.showToast({
title: '网络异常',
icon: 'none'
})
} finally {
loading.value = false
}
}
// ❌ 错误 - 没有错误处理
const fetchData = async () => {
const res = await userAPI()
dataList.value = res.data
}
SessionID 管理
// ✅ 正确 - sessionid 由请求拦截器自动注入
// 详见 src/utils/request.js:75-78
// ❌ 错误 - 手动设置 sessionid
const sessionid = Taro.getStorageSync('sessionid')
const res = await userAPI({ headers: { cookie: sessionid } })
🧪 测试规范
单元测试
// ✅ 好的测试 - 清晰的描述和断言
describe('formatDate', () => {
it('should format date to YYYY-MM-DD', () => {
const result = formatDate('2026-02-05')
expect(result).toBe('2026-02-05')
})
it('should handle invalid date', () => {
const result = formatDate('invalid')
expect(result).toBe('')
})
})
测试覆盖率目标
- 全局覆盖率: > 80%
- 核心业务逻辑: > 90%
- 工具函数: 100%
📝 注释规范
JSDoc 注释
/**
* 格式化日期
* @param {string|Date} date - 日期对象或日期字符串
* @param {string} format - 格式化模板(默认:'YYYY-MM-DD')
* @returns {string} 格式化后的日期字符串
* @example
* formatDate('2026-02-05', 'YYYY年MM月DD日')
* // 返回:'2026年02月05日'
*/
const formatDate = (date, format = 'YYYY-MM-DD') => {
// ...
}
复杂逻辑注释
// 步骤 1: 验证用户权限
const hasPermission = await checkUserPermission()
if (!hasPermission) {
throw new Error('无权限操作')
}
// 步骤 2: 检查数据有效性
const isValid = validateData(data)
if (!isValid) {
throw new Error('数据格式错误')
}
// 步骤 3: 提交到服务器
const result = await submitData(data)
🔒 安全规范
防止 XSS
<!-- ❌ 危险 - 用户输入未转义 -->
<view v-html="userComment"></view>
<!-- ✅ 安全 - 使用 text 插值 -->
<view>{{ userComment }}</view>
敏感信息保护
// ❌ 错误 - 硬编码密钥
const API_KEY = 'sk-proj-xxxxx'
// ✅ 正确 - 使用环境变量
const API_KEY = process.env.API_KEY
✅ 代码检查清单
提交代码前,确认:
- 代码可读性强,命名清晰
- 函数单一职责,长度 < 50 行
- 无深度嵌套(> 4 层)
- 无魔法数字,使用常量
- 无 console.log 或 debugger
- Props 有类型和默认值
- Emits 有事件名定义
-
API 调用检查
res.code === 1 - 所有 async 函数有 try-catch
- 组件样式使用 scoped
- 优先使用 TailwindCSS
- 复杂逻辑有注释说明
- JSDoc 注释完整
维护者: 开发团队 最后更新: 2026-02-05