三、前端规范化 项目代码规范

项目代码规范

一、概述

本文档定义了 web-admin 项目的代码规范,旨在提高代码质量、可读性和可维护性。所有团队成员都应该遵守这些规范。

适用范围:

  • Vue 3 组件
  • TypeScript 代码
  • JavaScript 代码
  • HTML/CSS/SCSS 代码
  • 配置文件

相关文档:


二、命名规范

2.1 文件命名

规则:

  • 使用 PascalCase(大驼峰)命名 Vue 组件
  • 使用 kebab-case(短横线)命名其他文件
  • 使用大写字母命名常量文件

示例:

复制代码
# 正确
LoginForm.vue           # Vue 组件 - PascalCase
user-list.vue           # Vue 组件 - PascalCase
api.service.ts          # 服务文件 - kebab-case
utils.ts                # 工具文件 - kebab-case
CONSTANTS.ts            # 常量文件 - 大写

# 错误
login_form.vue          # ❌ 不使用下划线
Loginform.vue           # ❌ 不使用连续大写
UserList.TS             # ❌ 扩展名小写

2.2 变量命名

规则:

  • 使用 camelCase(小驼峰)命名变量和函数
  • 使用 PascalCase(大驼峰)命名类和接口
  • 使用 UPPER_SNAKE_CASE(大写蛇形)命名常量
  • 使用下划线 _ 开头命名私有变量

示例:

typescript 复制代码
// 正确
const userName = "John Doe";           // 变量 - camelCase
function getUserInfo() {}              // 函数 - camelCase
interface UserData {}                  // 接口 - PascalCase
class UserService {}                   // 类 - PascalCase
const MAX_COUNT = 100;                 // 常量 - UPPER_SNAKE_CASE
const _privateData = {};               // 私有变量 - 下划线开头

// 错误
const UserName = "John Doe";          // ❌ 变量不使用大驼峰
function GetUserInfo() {}              // ❌ 函数不使用大驼峰
interface userData {}                  // ❌ 接口不使用小驼峰
const maxCount = 100;                  // ❌ 常量不使用小驼峰

2.3 组件命名

规则:

  • 使用 PascalCase(大驼峰)命名组件
  • 使用多个单词组合(至少两个单词)
  • 避免使用 Vue、Component 等通用后缀

示例:

vue 复制代码
<!-- 正确 -->
<template>
  <LoginForm />
  <UserList />
  <ProductCard />
</template>

<!-- 错误 -->
<template>
  <Login />
  <User />
  <Product />
  <VueComponent />
</template>

2.4 路由命名

规则:

  • 使用 kebab-case(短横线)命名路由路径
  • 使用 camelCase(小驼峰)命名路由名称

示例:

typescript 复制代码
// 正确
const routes = [
  { path: "/userList", name: "userList", component: UserList },
  { path: "/login-form", name: "loginForm", component: LoginForm },
];

// 错误
const routes = [
  { path: "/UserList", name: "UserList", component: UserList },
  { path: "/user_list", name: "user_list", component: UserList },
];

三、代码格式

3.1 缩进

规则:

  • 使用 2 个空格缩进
  • 不使用 Tab 缩进

示例:

typescript 复制代码
// 正确
function getUserInfo() {
  return {
    name: "John",
    age: 30,
  };
}

// 错误
function getUserInfo() {
    return {
        name: "John",
        age: 30,
    };
}

3.2 引号

规则:

  • 使用双引号 " 而不是单引号 '
  • 模板字符串使用反引号 `````

示例:

typescript 复制代码
// 正确
const name = "John Doe";
const message = `Hello, ${name}`;

// 错误
const name = 'John Doe';
const message = 'Hello, ' + name;

3.3 分号

规则:

  • 行尾必须加分号

示例:

typescript 复制代码
// 正确
const name = "John Doe";
function getUserInfo() {
  return name;
}

// 错误
const name = "John Doe"
function getUserInfo() {
  return name
}

3.4 行宽

规则:

  • 单行代码不超过 120 字符
  • 超过时需要换行

示例:

typescript 复制代码
// 正确
const result = calculateData(
  param1,
  param2,
  param3,
  param4,
);

// 错误
const result = calculateData(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10);

3.5 空格

规则:

  • 运算符前后加空格
  • 逗号后加空格
  • 大括号前后加空格
  • 函数参数括号后加空格

示例:

typescript 复制代码
// 正确
const sum = a + b;
const list = [1, 2, 3];
const obj = { name: "John" };
function getUserInfo() {}

// 错误
const sum=a+b;
const list=[1,2,3];
const obj={name:"John"};
function getUserInfo(){
}

四、TypeScript 规范

4.1 类型定义

规则:

  • 为所有变量、函数参数和返回值定义类型
  • 避免使用 any 类型
  • 使用接口定义复杂类型

示例:

typescript 复制代码
// 正确
interface User {
  id: number;
  name: string;
  age?: number;
}

function getUserInfo(userId: number): User {
  return { id: userId, name: "John" };
}

// 错误
function getUserInfo(userId) {
  return { id: userId, name: "John" };
}

function getUserInfo(userId: number): any {
  return { id: userId, name: "John" };
}

4.2 接口和类型

规则:

  • 使用 interface 定义对象类型
  • 使用 type 定义联合类型和交叉类型
  • 接口名使用 I 开头(可选)

示例:

typescript 复制代码
// 正确
interface IUser {
  id: number;
  name: string;
}

type Status = "active" | "inactive" | "pending";

type UserWithStatus = IUser & { status: Status };

// 错误
type User = {
  id: number;
  name: string;
};

4.3 函数

规则:

  • 为函数参数和返回值定义类型
  • 使用箭头函数优先
  • 避免使用 function 关键字

示例:

typescript 复制代码
// 正确
const getUserInfo = (userId: number): IUser => {
  return { id: userId, name: "John" };
};

// 错误
function getUserInfo(userId) {
  return { id: userId, name: "John" };
}

4.4 可选链和空值合并

规则:

  • 使用可选链 ?. 访问嵌套属性
  • 使用空值合并 ?? 提供默认值

示例:

typescript 复制代码
// 正确
const userName = user?.profile?.name ?? "Guest";

// 错误
const userName = user && user.profile && user.profile.name ? user.profile.name : "Guest";
const userName = user.profile.name || "Guest"; // ❌ 0 和 "" 会被覆盖

五、Vue 3 规范

5.1 组件结构

规则:

  • 使用 <script setup> 语法
  • 按顺序组织代码:导入、状态、计算属性、方法、生命周期
  • 模板使用 2 空格缩进

示例:

vue 复制代码
<template>
  <div class="user-profile">
    <h2>{{ userName }}</h2>
    <button @click="handleClick">Click</button>
  </div>
</template>

<script setup lang="ts">
// 1. 导入
import { ref, computed, onMounted } from "vue";
import { useUserStore } from "@/store";

// 2. 状态
const userStore = useUserStore();
const userId = ref(1);

// 3. 计算属性
const userName = computed(() => userStore.userName);

// 4. 方法
const handleClick = () => {
  console.log("Clicked");
};

// 5. 生命周期
onMounted(() => {
  console.log("Mounted");
});
</script>

<style scoped lang="scss">
.user-profile {
  padding: 16px;
}
</style>

5.2 Props 和 Emits

规则:

  • 使用 defineProps 定义 props
  • 使用 defineEmits 定义 emits
  • 为 props 定义类型和默认值

示例:

vue 复制代码
<script setup lang="ts">
interface Props {
  userId: number;
  userName?: string;
  isActive: boolean;
}

const props = withDefaults(defineProps<Props>(), {
  userName: "Guest",
  isActive: false,
});

const emit = defineEmits<{
  (e: "update", value: number): void;
  (e: "delete", id: number): void;
}>();

const handleUpdate = () => {
  emit("update", props.userId);
};
</script>

5.3 模板语法

规则:

  • 使用双大括号 {``{ }} 绑定数据
  • 使用 v-bind: 绑定属性
  • 使用 v-on@ 绑定事件
  • 使用 v-if 而不是 v-show 用于条件渲染

示例:

vue 复制代码
<template>
  <!-- 正确 -->
  <div :class="{ active: isActive }" :id="elementId">
    <p>{{ userName }}</p>
    <button @click="handleClick">Click</button>
    <div v-if="isVisible">Content</div>
  </div>

  <!-- 错误 -->
  <div class="active" id="elementId">
    <p v-text="userName"></p>
    <button v-on:click="handleClick">Click</button>
    <div v-show="isVisible">Content</div>
  </div>
</template>

5.4 样式

规则:

  • 使用 scoped 属性隔离样式
  • 使用 SCSS 语法
  • 使用 kebab-case 命名 CSS 类
  • 使用 BEM 命名规范(可选)

示例:

vue 复制代码
<style scoped lang="scss">
/* 正确 */
.user-profile {
  padding: 16px;

  &__header {
    font-size: 18px;
  }

  &__content {
    margin-top: 8px;
  }
}

/* 错误 */
.UserProfile {
  padding: 16px;
}

.userProfileHeader {
  font-size: 18px;
}
</style>

六、代码质量

6.1 注释

规则:

  • 使用 JSDoc 格式注释函数和类
  • 为复杂逻辑添加注释
  • 避免注释明显的代码
  • 使用中文注释

示例:

typescript 复制代码
/**
 * 获取用户信息
 * @param userId - 用户 ID
 * @returns 用户信息对象
 */
const getUserInfo = async (userId: number): Promise<IUser> => {
  // 调用 API 获取用户数据
  const response = await api.get(`/users/${userId}`);
  return response.data;
};

// 计算用户年龄(从出生日期计算)
const userAge = computed(() => {
  const birthDate = new Date(userStore.birthDate);
  const today = new Date();
  return today.getFullYear() - birthDate.getFullYear();
});

6.2 错误处理

规则:

  • 使用 try-catch 处理异步错误
  • 为所有 Promise 添加错误处理
  • 提供友好的错误提示

示例:

typescript 复制代码
// 正确
const fetchData = async () => {
  try {
    const response = await api.get("/data");
    return response.data;
  } catch (error) {
    console.error("获取数据失败:", error);
    ElMessage.error("获取数据失败,请稍后重试");
    throw error;
  }
};

// 错误
const fetchData = async () => {
  const response = await api.get("/data");
  return response.data;
};

6.3 性能优化

规则:

  • 使用 computed 缓存计算结果
  • 使用 v-memo 缓存模板
  • 避免在模板中使用复杂表达式
  • 避免在循环中使用 v-if

示例:

vue 复制代码
<template>
  <!-- 正确 -->
  <div v-for="item in filteredList" :key="item.id">
    {{ item.name }}
  </div>

  <!-- 错误 -->
  <div v-for="item in list" :key="item.id" v-if="item.isActive">
    {{ item.name }}
  </div>
</template>

<script setup lang="ts">
import { computed } from "vue";

const list = ref([{ id: 1, name: "John", isActive: true }]);

// 正确:使用 computed 过滤列表
const filteredList = computed(() => list.value.filter((item) => item.isActive));
</script>

七、API 调用规范

7.1 API 封装

规则:

  • 使用 Axios 封装 API 调用
  • 为每个模块创建独立的 API 文件
  • 使用拦截器处理请求和响应

示例:

typescript 复制代码
// api/user.api.ts
import request from "@/utils/request";

export const userApi = {
  getUserInfo: (userId: number) => request.get(`/users/${userId}`),
  updateUserInfo: (data: IUser) => request.put("/users", data),
  deleteUser: (userId: number) => request.delete(`/users/${userId}`),
};

7.2 请求和响应

规则:

  • 使用统一的请求格式
  • 使用统一的响应格式
  • 处理分页和排序参数

示例:

typescript 复制代码
// 请求参数
interface PageParams {
  page: number;
  pageSize: number;
  sortBy?: string;
  sortOrder?: "asc" | "desc";
}

// 响应格式
interface ApiResponse<T> {
  code: number;
  message: string;
  data: T;
}

interface PageResponse<T> {
  list: T[];
  total: number;
  page: number;
  pageSize: number;
}

八、状态管理规范

8.1 Pinia Store

规则:

  • 使用 Pinia 进行状态管理
  • 为每个模块创建独立的 Store
  • 使用 defineStore 定义 Store

示例:

typescript 复制代码
// store/modules/user.store.ts
import { defineStore } from "pinia";

interface UserState {
  userId: number;
  userName: string;
  isLoggedIn: boolean;
}

export const useUserStore = defineStore({
  id: "user",
  state: (): UserState => ({
    userId: 0,
    userName: "",
    isLoggedIn: false,
  }),
  getters: {
    fullName: (state) => state.userName,
  },
  actions: {
    setUserInfo(userInfo: UserState) {
      this.userId = userInfo.userId;
      this.userName = userInfo.userName;
      this.isLoggedIn = true;
    },
    logout() {
      this.userId = 0;
      this.userName = "";
      this.isLoggedIn = false;
    },
  },
});

九、代码审查规范

9.1 审查要点

  1. 代码质量

    • 是否符合代码规范
    • 是否有语法错误
    • 是否有逻辑错误
  2. 性能优化

    • 是否有性能问题
    • 是否有内存泄漏
    • 是否有重复请求
  3. 安全性

    • 是否有 XSS 漏洞
    • 是否有 CSRF 漏洞
    • 是否有敏感信息泄露
  4. 可维护性

    • 是否有足够的注释
    • 是否有测试用例
    • 是否有文档

9.2 审查流程

复制代码
1. 提交代码到 Git
2. 创建 Pull Request
3. 分配审查人员
4. 审查代码
5. 修复问题
6. 合并代码

十、总结

10.1 关键规范

  1. 命名规范

    • 组件使用 PascalCase
    • 变量使用 camelCase
    • 常量使用 UPPER_SNAKE_CASE
  2. 代码格式

    • 2 空格缩进
    • 双引号
    • 行尾分号
    • 120 字符行宽
  3. TypeScript

    • 定义所有类型
    • 尽量避免使用 any
    • 使用接口定义复杂类型
  4. Vue 3

    • 使用 <script setup>
    • 定义 Props 和 Emits
    • 使用 scoped 样式

10.2 工具支持

  1. ESLint - 代码检查
  2. Prettier - 代码格式化
  3. Husky - Git 钩子
  4. lint-staged - 暂存文件检查

附录:

版本历史:

  • v1.0 (2026-01-16) - 初始版本

上一篇: 02-遇到的问题及解决方案.md

返回目录: README.md

相关推荐
xkxnq2 小时前
第二阶段:Vue 组件化开发(第 28天)
前端·javascript·vue.js
Yvonne爱编码2 小时前
前端工程化进阶:从搭建完整项目脚手架到性能优化【技术类】
前端·状态模式
cypking2 小时前
二、前端规范化 遇到的问题及解决方案
前端
小范馆2 小时前
STM32F03C8T6通过AT指令获取天气API
前端·javascript·stm32
zhengxianyi5153 小时前
vue-cli build, vite build 生产部署刷新或弹窗404,页面空白修复方法
前端·javascript·vue.js·nginx·生产部署
Filotimo_3 小时前
前端项目打包部署完整流程
前端
Savvy..3 小时前
Day15 Talis 前端
前端
恋爱绝缘体13 小时前
Vue.js 组件 - 自定义事件【1】
前端·javascript·vue.js
梦6503 小时前
JavaScript ES5 + ES6+ 字符串 (String) 所有方法大全
前端·javascript·es6