# 代码编写规范 ## 目录 1. [项目结构规范](#1-项目结构规范) 2. [TypeScript 规范](#2-typescript-规范) 3. [API 设计规范](#3-api-设计规范) 4. [页面开发规范](#4-页面开发规范) 5. [组件开发规范](#5-组件开发规范) 6. [状态管理规范](#6-状态管理规范) 7. [样式规范](#7-样式规范) 8. [工具函数规范](#8-工具函数规范) 9. [命名规范](#9-命名规范) 10. [注释规范](#10-注释规范) --- ## 1. 项目结构规范 ### 1.1 目录结构 ``` src/ ├── api/ # API 接口层 │ ├── module/ # 按业务模块分组 │ │ ├── index.ts # 导出该模块 API │ │ └── model/ # 类型定义 │ │ └── index.ts │ └── index.ts # 统一导出 ├── components/ # 组件 │ ├── business/ # 业务组件 │ ├── common/ # 通用组件 │ └── icons/ # 图标组件 ├── pages/ # 页面 │ └── module/ # 按业务模块分组 │ ├── index.vue # 页面主文件 │ └── components/ # 页面专用组件 ├── store/ # 状态管理(Pinia) ├── utils/ # 工具函数 ├── hooks/ # 自定义 Hooks ├── types/ # 全局类型定义 ├── http/ # HTTP 请求封装 ├── router/ # 路由配置 ├── layouts/ # 布局组件 ├── tabbar/ # 底部导航 └── config/ # 配置文件 ``` ### 1.2 文件命名规范 - **页面文件**:使用 kebab-case,如 `user-profile.vue` - **组件文件**:使用 kebab-case,如 `user-card.vue` - **工具文件**:使用 camelCase,如 `formatDate.ts` - **类型文件**:使用 camelCase,如 `userTypes.ts` - **API 文件**:使用 camelCase,如 `userApi.ts` - **常量文件**:使用 camelCase,如 `appConfig.ts` --- ## 2. TypeScript 规范 ### 2.1 类型定义 - 使用 `interface` 定义对象类型 - 使用 `type` 定义联合类型、基础类型别名 - 接口命名使用 PascalCase - 私有属性使用下划线前缀(可选) ```typescript /** * 用户信息 */ export interface User { /** 用户ID */ id: number; /** 用户名 */ username: string; /** 邮箱 */ email?: string; } /** * 用户登录参数 */ export interface LoginParams { username: string; password: string; remember?: boolean; } ``` ### 2.2 泛型使用 - 为 API 返回类型添加泛型约束 - 为组件 Props 添加类型约束 ```typescript // API 返回类型 export interface ApiResult { code: number; data: T; message: string; } // 组件 Props 类型 interface Props { userInfo: User; loading?: boolean; } ``` --- ## 3. API 设计规范 ### 3.1 文件组织 - 按业务模块创建目录 - API 函数统一在 `index.ts` 中导出 - 类型定义放在 `model/index.ts` 中 ### 3.2 函数命名 - 使用 camelCase 命名 - 使用动词 + 名词的方式命名 - 常用动词:`get`、`post`、`put`、`delete`、`add`、`update`、`remove` ```typescript // ✅ 正确的命名 export function getUserList(params: UserParams) { return http.get('/api/users', params); } export function createUser(data: CreateUserData) { return http.post('/api/users', data); } // ❌ 错误的命名 export function userList() {} export function add_new_user() {} ``` ### 3.3 返回处理 - 统一检查响应状态 - 成功时返回数据,失败时抛出错误 ```typescript export async function getUserInfo(id: number) { const res = await http.get>(`/api/users/${id}`); if (res.data.code === 200) { return res.data.data; } return Promise.reject(res.data.message); } ``` ### 3.4 参数说明 - 为每个 API 函数添加中文注释 - 说明参数含义和是否必填 ```typescript /** * 获取用户列表 * @param params 查询参数 * @param params.keyword 搜索关键词(可选) * @param params.page 当前页码(可选) * @param params.size 每页数量(可选) */ export function getUserList(params?: UserParams) { return http.get>>('/api/users', params); } ``` --- ## 4. 页面开发规范 ### 4.1 基本结构 ```vue ``` ### 4.2 变量声明 - 使用 `ref()` 声明基础类型响应式数据 - 使用 `reactive()` 声明对象类型响应式数据 - 使用 `computed()` 声明计算属性 - 变量命名使用 camelCase ```typescript // 基础类型 const loading = ref(false); const currentPage = ref(1); // 对象类型 const searchParams = reactive({ keyword: '', status: '', }); // 计算属性 const userList = computed(() => store.users); ``` ### 4.3 函数声明 - 使用箭头函数或 function 声明 - 函数命名使用 camelCase - 添加必要的注释说明 ```typescript /** * 搜索用户 */ const handleSearch = () => { loading.value = true; getUserList(searchParams) .then((res) => { // 处理成功 }) .finally(() => { loading.value = false; }); }; /** * 分页改变 * @param page 页码 */ const handlePageChange = (page: number) => { currentPage.value = page; handleSearch(); }; ``` ### 4.4 生命周期钩子 - 使用 Composition API 的生命周期钩子 - 常用钩子:`onMounted`、`onUnmounted`、`onShow`、`onHide` ```typescript onMounted(() => { initData(); }); onShow(() => { refreshData(); }); ``` --- ## 5. 组件开发规范 ### 5.1 组件结构 ```vue ``` ### 5.2 Props 规范 - 使用 TypeScript 类型约束 - 使用 `withDefaults` 提供默认值 - Props 命名使用 camelCase ```typescript interface Props { /** 标题文本 */ title: string; /** 是否显示(v-model) */ modelValue: boolean; /** 大小尺寸 */ size?: 'large' | 'medium' | 'small'; /** 是否禁用 */ disabled?: boolean; } const props = withDefaults(defineProps(), { size: 'medium', disabled: false, }); ``` ### 5.3 Emits 规范 - 使用 `defineEmits` 定义事件 - 事件名使用 kebab-case - 提供完整的类型定义 ```typescript const emit = defineEmits<{ (e: 'update:visible', visible: boolean): void; (e: 'confirm', data: any): void; (e: 'cancel'): void; }>(); const handleConfirm = () => { emit('confirm', data); }; ``` ### 5.4 组件命名 - 组件文件使用 PascalCase 或 kebab-case - 推荐使用 PascalCase ```vue UserCard.vue UserInfoForm.vue user-card.vue user_info_form.vue ``` --- ## 6. 状态管理规范 ### 6.1 Store 定义 - 使用 Pinia 的 setup 语法 - 使用 `defineStore` 创建 store - state 使用 `ref` 声明 - actions 直接声明为函数 ```typescript import { defineStore } from 'pinia'; import { ref } from 'vue'; import { getUserList } from '@/api/user'; export const useUserStore = defineStore('user', () => { // 状态 const userList = ref([]); const currentUser = ref(null); const loading = ref(false); // 异步操作 const fetchUserList = async () => { loading.value = true; try { const data = await getUserList(); userList.value = data; } finally { loading.value = false; } }; // 同步操作 const setCurrentUser = (user: any) => { currentUser.value = user; }; return { userList, currentUser, loading, fetchUserList, setCurrentUser, }; }); ``` ### 6.2 Store 使用 - 在页面或组件中引入 store - 使用 camelCase 命名 store 实例 ```typescript import { useUserStore } from '@/store/user'; const userStore = useUserStore(); // 使用 store userStore.fetchUserList(); ``` --- ## 7. 样式规范 ### 7.1 样式作用域 - 组件样式必须使用 `scoped` 属性 - 避免全局样式污染 ```vue ``` ### 7.2 命名规范 - 使用 BEM 命名规范 - 块(Block):使用 kebab-case - 元素(Element):使用 `__` 连接 - 修饰符(Modifier):使用 `--` 连接 ```scss .user-card { // 块 &__header { // 元素 } &__title { // 元素 } &--large { // 修饰符 } } ``` ### 7.3 样式组织 - 按元素类型分组 - 相关样式放在一起 - 避免重复代码 ```scss .card { padding: 16px; border: 1px solid #e0e0e0; border-radius: 8px; // 标题样式 &__title { font-size: 18px; font-weight: 600; margin-bottom: 12px; } // 内容样式 &__content { color: #666; line-height: 1.6; } // 按钮样式 &__button { margin-top: 16px; text-align: right; } } ``` ### 7.4 响应式设计 - 使用 rpx 单位适配不同屏幕 - 使用媒体查询或 uni-app 的响应式方案 ```scss .container { padding: 20rpx; @media (min-width: 768px) { padding: 40rpx; } } ``` --- ## 8. 工具函数规范 ### 8.1 函数命名 - 使用 camelCase 命名 - 函数名应该清晰表达功能 ```typescript // ✅ 正确的命名 export function formatDate(date: Date): string { return date.toISOString().split('T')[0]; } export function debounce any>( func: T, delay: number ): T { // 实现... } // ❌ 错误的命名 export function f(d: Date): string {} export function deb() {} ``` ### 8.2 函数注释 - 为复杂函数添加 JSDoc 注释 - 说明参数和返回值 ```typescript /** * 防抖函数 * @param func 要防抖的函数 * @param delay 延迟时间(毫秒) * @returns 防抖后的函数 */ export function debounce any>( func: T, delay: number ): T { // 实现... } ``` ### 8.3 工具分类 - 通用工具放在 `src/utils/` 目录 - 按功能分类创建文件 - 导出时统一在 `index.ts` 中聚合 ```typescript // src/utils/date.ts export function formatDate(date: Date): string { return date.toISOString().split('T')[0]; } // src/utils/index.ts export * from './date'; export * from './string'; export * from './number'; ``` --- ## 9. 命名规范 ### 9.1 文件命名 - 页面文件:kebab-case - 组件文件:PascalCase 或 kebab-case - 工具文件:camelCase - 类型文件:camelCase ``` pages/ user-profile.vue order-list.vue components/ UserCard.vue user-info-form.vue utils/ formatDate.ts validateForm.ts types/ userTypes.ts apiTypes.ts ``` ### 9.2 变量命名 - 基础变量:camelCase - 常量:大写字母 + 下划线 - 私有变量:下划线前缀(可选) ```typescript // 基础变量 const userName = '张三'; const userList = []; // 常量 const API_BASE_URL = 'https://api.example.com'; const MAX_RETRY_COUNT = 3; // 私有变量(可选) const _privateVar = '私有变量'; ``` ### 9.3 函数命名 - 使用 camelCase - 使用动词 + 名词的方式 ```typescript // 动词 + 名词 function getUserInfo() {} function updateUserData() {} function deleteUserById() {} // 布尔值命名 const isLoading = ref(false); const hasPermission = ref(true); const canEdit = ref(false); ``` ### 9.4 接口命名 - 使用 PascalCase - 可以添加后缀说明类型 ```typescript interface User {} interface UserInfo {} interface UserParams {} interface UserListResponse {} ``` --- ## 10. 注释规范 ### 10.1 文件注释 - 在文件顶部添加文件说明(可选) ```typescript /** * 用户管理相关 API * 包含用户信息的增删改查功能 */ import type { User } from './types'; ``` ### 10.2 函数注释 - 使用 JSDoc 格式 - 说明函数功能、参数和返回值 ```typescript /** * 获取用户信息 * @param id 用户ID * @param includeRoles 是否包含角色信息 * @returns 用户信息 */ function getUserInfo(id: number, includeRoles = false): User { // 实现... } ``` ### 10.3 类型注释 - 为接口属性添加注释 - 说明属性含义 ```typescript /** * 用户信息 */ interface User { /** 用户ID */ id: number; /** 用户名 */ username: string; /** 邮箱地址 */ email?: string; /** 创建时间 */ createTime: string; } ``` ### 10.4 复杂逻辑注释 - 为复杂业务逻辑添加注释 - 说明为什么这样做 ```typescript // 需要手动计算的原因是uni-app不提供原生的高度获取方法 const calculateHeight = () => { // 实现... }; // 由于后端接口返回的数据结构与前端期望不一致,需要进行转换 const transformData = (rawData: any) => { // 实现... }; ``` --- ## 11. 最佳实践 ### 11.1 性能优化 - 使用 `computed` 缓存计算结果 - 使用 `v-show` 而非 `v-if` 频繁切换的组件 - 合理使用 `onMounted` 和 `watch` ### 11.2 代码复用 - 提取公共逻辑为自定义 Hook - 提取公共组件 - 使用工具函数减少重复代码 ### 11.3 错误处理 - 统一处理 API 错误 - 提供友好的错误提示 - 记录错误日志(可选) ```typescript const fetchData = async () => { try { const data = await getData(); // 处理成功 } catch (error) { uni.showToast({ title: '加载失败,请重试', icon: 'none', }); console.error('数据加载失败:', error); } }; ``` ### 11.4 代码审查 - 提交代码前进行自检 - 检查命名、注释、格式 - 确保代码可读性和可维护性 --- ## 12. 常用代码片段 ### 12.1 页面模板 ```vue ``` ### 12.2 组件模板 ```vue ``` ### 12.3 Store 模板 ```typescript import { defineStore } from 'pinia'; import { ref } from 'vue'; import { getData } from '@/api/example'; export const useExampleStore = defineStore('example', () => { const data = ref([]); const loading = ref(false); const fetchData = async () => { loading.value = true; try { data.value = await getData(); } finally { loading.value = false; } }; return { data, loading, fetchData, }; }); ``` --- ## 总结 本规范旨在统一项目代码风格,提高代码质量和可维护性。开发者在编写代码时应当遵循以下原则: 1. **一致性**:遵循既定的命名规范和代码风格 2. **可读性**:使用清晰的命名和充分的注释 3. **可维护性**:保持代码简洁、模块化 4. **最佳实践**:遵循 Vue 3 和 TypeScript 的最佳实践 如果在开发过程中遇到特殊情况,可以与团队讨论后调整规范内容。 --- > **版本**:v1.0.0 > **更新日期**:2025-10-29 > **适用范围**:uni-app + Vue 3 + TypeScript 项目