865 lines
16 KiB
Markdown
865 lines
16 KiB
Markdown
|
|
# 代码编写规范
|
|||
|
|
|
|||
|
|
## 目录
|
|||
|
|
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<T> {
|
|||
|
|
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<User[]>('/api/users', params);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export function createUser(data: CreateUserData) {
|
|||
|
|
return http.post<User>('/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<ApiResult<User>>(`/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<ApiResult<PageResult<User[]>>>('/api/users', params);
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 4. 页面开发规范
|
|||
|
|
|
|||
|
|
### 4.1 基本结构
|
|||
|
|
```vue
|
|||
|
|
<script lang="ts" setup>
|
|||
|
|
// 导入顺序:框架 -> 第三方库 -> 工具库 -> 本地模块
|
|||
|
|
import { ref, computed, onMounted } from 'vue';
|
|||
|
|
import { getUserList } from '@/api/user';
|
|||
|
|
|
|||
|
|
// 页面逻辑...
|
|||
|
|
definePage({
|
|||
|
|
style: {
|
|||
|
|
navigationBarTitleText: '用户列表',
|
|||
|
|
},
|
|||
|
|
});
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<template>
|
|||
|
|
<!-- 模板内容 -->
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<style scoped lang="scss">
|
|||
|
|
/* 样式内容 */
|
|||
|
|
</style>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 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
|
|||
|
|
<script lang="ts" setup>
|
|||
|
|
import { ref } from 'vue';
|
|||
|
|
|
|||
|
|
// Props 定义
|
|||
|
|
interface Props {
|
|||
|
|
title: string;
|
|||
|
|
size?: 'large' | 'medium' | 'small';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const props = withDefaults(defineProps<Props>(), {
|
|||
|
|
size: 'medium',
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// Emits 定义
|
|||
|
|
const emit = defineEmits<{
|
|||
|
|
(e: 'update:visible', visible: boolean): void;
|
|||
|
|
(e: 'confirm', data: any): void;
|
|||
|
|
}>();
|
|||
|
|
|
|||
|
|
// 组件逻辑...
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<template>
|
|||
|
|
<!-- 模板内容 -->
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<style scoped lang="scss">
|
|||
|
|
/* 样式内容 */
|
|||
|
|
</style>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 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<Props>(), {
|
|||
|
|
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
|
|||
|
|
<style scoped lang="scss">
|
|||
|
|
.example {
|
|||
|
|
color: #333;
|
|||
|
|
}
|
|||
|
|
</style>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 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<T extends (...args: any[]) => 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<T extends (...args: any[]) => 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
|
|||
|
|
<script lang="ts" setup>
|
|||
|
|
import { ref, onMounted } from 'vue';
|
|||
|
|
import { getData } from '@/api/example';
|
|||
|
|
|
|||
|
|
definePage({
|
|||
|
|
style: {
|
|||
|
|
navigationBarTitleText: '页面标题',
|
|||
|
|
},
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
const loading = ref(false);
|
|||
|
|
const data = ref([]);
|
|||
|
|
|
|||
|
|
const init = async () => {
|
|||
|
|
loading.value = true;
|
|||
|
|
try {
|
|||
|
|
data.value = await getData();
|
|||
|
|
} finally {
|
|||
|
|
loading.value = false;
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
onMounted(() => {
|
|||
|
|
init();
|
|||
|
|
});
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<template>
|
|||
|
|
<view class="page">
|
|||
|
|
<!-- 内容 -->
|
|||
|
|
</view>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<style scoped lang="scss">
|
|||
|
|
.page {
|
|||
|
|
padding: 20rpx;
|
|||
|
|
}
|
|||
|
|
</style>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 12.2 组件模板
|
|||
|
|
```vue
|
|||
|
|
<script lang="ts" setup>
|
|||
|
|
interface Props {
|
|||
|
|
title: string;
|
|||
|
|
modelValue: boolean;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const props = withDefaults(defineProps<Props>(), {
|
|||
|
|
title: '',
|
|||
|
|
modelValue: false,
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
const emit = defineEmits<{
|
|||
|
|
(e: 'update:modelValue', value: boolean): void;
|
|||
|
|
(e: 'confirm'): void;
|
|||
|
|
}>();
|
|||
|
|
|
|||
|
|
const handleClose = () => {
|
|||
|
|
emit('update:modelValue', false);
|
|||
|
|
};
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<template>
|
|||
|
|
<view class="dialog">
|
|||
|
|
<!-- 内容 -->
|
|||
|
|
</view>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<style scoped lang="scss">
|
|||
|
|
.dialog {
|
|||
|
|
/* 样式 */
|
|||
|
|
}
|
|||
|
|
</style>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 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 项目
|