Skip to content

前端开发规范

引言

本规范旨在为基于 Vue3、Vite 和 TypeScript 的前端项目开发提供统一的标准和指导,确保项目的代码质量、可维护性和团队协作效率。

Javascript规范

文件命名

  • 全部采用 kebab-case 命名,字母小写,以短横分隔单词。render-dom.ts / home.ts / get-user-info.ts

声明变量

  • 变量名使用 camelCase 驼峰命名。
  • 不能以数字,特殊符号开头。
  • 不能使用 JavaScript 关键字和保留字。
  • 避免使用没有意义的命名。
  • 变量名起名以 类型+对象描述 的规则。
typescript
let userId = 1;
let userName = "小明";
let tableTitle = "表格标题";

声明常量

  • 常量名使用全部大写命名,多个单词中间用_下划线分隔。
typescript
const AMOUNT = 10;
const MAX_COUNT = 10;
const APPROVE_TYPE = { DOING: 1, APPROVED: 2 };

形参命名

参数描述示例
i索引switchTab(i) {}
i,vlist.forEach((i,v) => {})
e事件onInput(e) {}
obj对象for(let obj of userList) {}
arr数组let arr = [];
fun函数callback(fun) {}
item列表项list.map(item => {})
item,indexvue遍历数据v-for="(item,index) in arr"
key,value键值对for(let [key,value] of arr) {}

函数命名

  • 函数名使用camelCase驼峰命名,命名为动词形式,或者动词+名词形式。
typescript
function getName() {}
function setName() {}
function canEdit() {}
function addUser() {}
function hasCode() {}
  • 增删改查和查看详情,统一使用下面的单词。

add / delete / update / get / detail

  • 附带常用的动词列表
html
get 获取 | set 设置
add 增加 | delete 删除
start 启动 | launch 启动 | run 运行 | ready 准备 | stop 停止
open 打开 | close 关闭
read 读取 | write 写入 | save 保存
load 载入 | unload 不加载
create 创建 | destroy 销毁
begin 开始 | start 开始 | end 结束
from 从.. | to 到..
backup 备份 | restore 恢复
import 导入 | export 导出
print 打印 | afterprint 打印机关闭
split 分割 | merge 合并
touch 轻按 | click 点击  | dblclick 双击 | drag 拖拽
inject 注入 | extract 提取
attach 附着 | detach 脱离
bind 绑定 | separate 分离
view 查看 | browse 浏览
edit 编辑 | modify 修改 | update 更新 | upgrade 升级
select 选取 | change 改变 | mark 标记
copy 复制 | paste 粘贴
do 做 | undo 撤销 | redo 重做
insert 插入 | remove 移除 | revoke 撤销 |  revert 复原 | reset 重置
clean 清理 | clear 清除
index 索引 | sort 排序
find 查找 | search 搜索
increase 增加 | decrease 减少
rise 上涨 | fall 下降
play 播放 | pause 暂停
forward 前进 | rewind 后退
compile 编译 | execute 执行
suspend 挂起 | complete 完成
debug 调试 | trace 跟踪
observe 观察 | listen 监听
build 构建 | publish 发布
input 输入 | output 输出
encode 编码 | decode 解码
encrypt 加密 | decrypt 解密
compress 压缩 | decompress 解压缩
pack 打包 | unpack 解包
parse 解析 | emit 生成
connect 连接 | disconnect 断开
send 发送 | receive 接收
upload 上传 | download 下载
refresh 刷新 | synchronize 同步
lock 锁定 | unlock 解锁
check out 签出 | check in 签入
submit 提交 | commit 交付
push 推 | pull 拉
expand 展开 | collapse 折叠
active 激活 | deactive 未激活
wait 等待 | process 进程中 | finish 完成
enter 进入 | exit 退出
abort 中止 | quit 离开
obsolete 废弃 | depreciate 废旧
collect 收集 | aggregate 聚集

代码规范

三元条件简单判断

  • 在简单的判断条件下,使用三元运算符能更加的精简代码,增加可读性。
typescript
let status = 0;
console.log(status == 0 ? "代办" : status == 1 ? "已办" : "无");

创建对象

  • 使用字面量创建对象,更加简洁
typescript
let user = {
  id: 1,
  name: "小红",
  sex: "女",
  age: 18,
};

判断函数参数太多,封装为对象传参

typescript
let user = {
  id: 1,
  name: "小红",
  sex: "女",
  age: 18,
};
function addUser(user) {}

使用 Promise,async/await 代替回调函数

typescript
// 使用Promise
function getMsg(res) {
  return new Promise((resolve, reject) => {
    if (res.code == 200) {
      resolve(res);
    } else {
      reject(res);
    }
  });
}
getMsg({ code: 200, result: [] }).then((res) => {});

// 使用ssync/await
async function login() {
  // 先执行获取用户信息
  let user = await getUserInfo();
  // 再执行获取菜单,传入用户的id
  let menu = await getMenuList(user.id);
  console.log(user, menu);
}

TypeScript规范

命名规范

变量和函数命名

typescript
// 变量
let userName: string = 'John';
// 函数
function getFullName(firstName: string, lastName: string): string {
  return `${firstName} ${lastName}`;
}

类和接口命名

  • 大驼峰命名法:类和接口名使用大驼峰命名法,即每个单词的首字母都大写。
typescript
// 类
class UserProfile {
    (public name: string, public age: number) {}
}

// 接口
interface Person {
    name: string;
    age: number;
}

常量命名

  • 全大写单词间用下划线分隔:常量使用全大写字母,单词之间用下划线分
typescript
const MAX_COUNT: number = 100;

类型定义规范

明确类型注释

  • 尽可能明确地指定变量、函数参数和返回值的类型,避免使用隐式类型或 any 类型,除非确实无法确定类型。
typescript
// 明确指定类型
let score: number = 90;

// 函数参数和返回值类型注解
function add(a: number, b: number): number {
    return a + b;
}

类型别名和接口使用

  • 类型别名:适用于简单类型的重命名、联合类型、交叉类型等。
typescript
// 类型别名
type ID = string | number;
type User = {
    id: ID;
    name: string;
};
  • 接口:更适合用于定义对象的结构,可实现继承和扩展。
typescript
// 接口
interface Animal {
    name: string;
    eat(): void;
}

interface Dog extends Animal {
    bark(): void;
}
  • 枚举类型的使用

枚举类型使用大驼峰命名法,枚举成员通常使用全大写,单词间用下划线分隔。

typescript
enum Color {
    RED = 'red',
    GREEN = 'green',
    BLUE = 'blue'
}

代码结构规范

模块化开发

  • 使用 ES6 模块语法(import 和 export)来组织代码,每个文件应具有单一的职责。
typescript
// utils.ts
export function formatDate(date: Date): string {
    return date.toLocaleDateString();
}

// main.ts
import { formatDate } from './utils';
const now = new Date();
const formattedDate = formatDate(now);

类的结构

  • 类的成员按照以下顺序排列:静态属性、实例属性、构造函数、静态方法、实例方法。
typescript
class Calculator {
    static PI: number = 3.14;
    private result: number = 0;

    (initialValue: number) {
        this.result = initialValue;
    }

    static add(a: number, b: number): number {
        return a + b;
    }

    addToResult(value: number): void {
        this.result += value;
    }

    getResult(): number {
        return this.result;
    }
}

命名规则

布尔值命名

  • 布尔值是两种逻辑状态的变量真和假,对应 true false ,也可以用数字 1 0 表示真假。
  • 推荐命名方式为 is + 动词(现在进行时)/ 形容词 ,但是有些场景下也可以不用写 is 开头。

可见性/进行中

json
{
  "isShow": "是否显示",
  "isVisible": "是否可见",
  "isLoading": "是否处于加载中",
  "isConnecting": "是否处于连接中",
  "isValidating": "正在验证中",
  "isDoing": "正在进行中",
  "isRunning": "正在运行中",
  "isListening": "正在监听中"
}

属性/状态

json
{
  "isDisabled": "是否禁用",
  "isEdit": "是否可编辑",
  "isAdd": "是否可增加",
  "isUpdate": "是否可修改",
  "isRemove": "是否可删除",
  "isClearable": "是否可清空",
  "isReadonly": "是否只读",
  "isExpand": "是否可展开",
  "isShrink": "是否可收缩",
  "isChecked": "是否选中",
  "isClick": "是否可点击",
  "isDrag": "是否可拖拽",
  "isOpen": "是否打开",
  "isClose": "是否打开",
  "isChoice": "是否选择(复选框,单选框)",
  "isSelect": "是否选择(下拉框,列表)",
  "isConfig": "是否可配置"
}

弹框显示/隐藏

json
{
  // 组合1-基础表单
  "addModal": "新增弹框",
  "editModal": "编辑弹框",
  "detailModal": "详情弹框",

  // 组合2-业务相关
  "syncDataModal": "同步数据弹框",
  "addUserModal": "新增用户弹框",
  "userInfoModal": "用户信息弹框",
  "assignPermissionModal": "分配权限弹框",
  "departTreeModal": "部门树弹框"
}

数组变量命名

  • 数组主要有 复数形式 xxxList 形式,简单的区别是 复数形式 的适合前端本身声明的数组, xxxList 形式的适合后台接口返回的数组。
typescript
{
  // 前端声明变量
  "users": "用户列表",
  "menus": "菜单列表",
  "selectNodes": "选中节点列表",

  // 后台返回数据接收变量
  "userList": "用户列表",
  "menuList": "菜单列表",
  "statusList": "状态列表"
}

变量命名选项变量命名

  • 主要针对的是单选框,复选框,下拉框,选项卡等元素数据。
  • 常见的词汇有: title, name,label,field,text,id,key,value,children,index,nodes 等。
  • 其中 title,name,label,text,field 作为选项显示名, id,key,value 用于唯一标识, children,nodes 用于包含子节点内容。

复选/单选/下拉

json
{
  // 常用组合
  "label": "标题",
  "value": "值",

  // 组合1
  "title": "标题",
  "value": "值",

  // 组合2
  "text": "文本",
  "value": "值",

  // 组合3
  "id": "标题",
  "name": "值",

  // 组合4
  "field": "标题",
  "value": "值",
  "index": "标题"
}

激活状态

json
{
  "activeName": "激活的项名称",
  "activeTab": "激活的选项卡",
  "currentPage": "当前页",
  "currentIndex": "当前选项的下标"
}

Api接口命名

  • 主要用作 axios 请求后台接口封装,接口方法使用camelCase驼峰命名,命名为动词+名词形式。
  • 后台一般采用 Restful Api 规范,如下示例:
text
/api/user/list
/api/user/detail/${id}
/api/user/add
/api/user/update
/api/user/delete/${id}
  • 前端对应的接口方法命名用getXxx,addXxx,updateXxx,deleteXxx这几种命名形式,并且一定要写注释,注释格式为模块名-方法描述,如下示例:
typescript
/**
 * 用户管理-分页列表
 */
export const getUserList = (params) => {
  return axios.get("/api/user/list", params);
};

/**
 * 用户管理-详情
 */
export const getUserDetail = (params) => {
  return axios.get(`/api/user/detail/${params.id}`);
};

/**
 * 用户管理-新增
 */
export const addUser = (data) => {
  return axios.post("/api/user/add", data);
};

/**
 * 用户管理-修改
 */
export const updateUser = (params) => {
  return axios.post("/api/user/update", data);
};

/**
 * 用户管理-删除
 */
export const deleteUser = (params) => {
  return axios.get(`/api/user/delete/${params.id}`);
};

命名参考

样式文件命名

text
index.css    // 一般用于首页建立样式
head.css     // 头部样式,当多个页面头部设计风格相同时使用。
base.css     // 共用样式。
style.css    // 独立页面所使用的样式文件。
global.css   // 页面样式基础,全局公用样式,页面中必须包含。
layout.css   // 布局、版面样式,公用类型较多时使用,一般用在首页级页面和产品类页面中
module.css   // 模块,用于产品类页,也可与其它样式配合使用。
master.css   // 主要的样式表
columns.css  // 专栏样式
themes.css   // 主体样式
forms.css    // 表单样式
mend.css     // 补丁,基于以上样式进行的私有化修补。
print.css    // 打印

页面结构命名

text
page         // 代表整个页面,用于最外层。
wrap         // 外套,将所有元素包在一起的一个外围包,用于最外层
wrapper      // 页面外围控制整体布局宽度,用于最外层
container    // 一个整体容器,用于最外层
head|header  // 页头区域,用于头部
nav          // 导航条
content      // 内容,网站中最重要的内容区域,用于网页中部主体
main         // 网站中的主要区域(表示最重要的一块位置),用于中部主体内容
column       // 栏目
sidebar      // 侧栏
foot|footer  // 页尾、页脚。网站一些附加信息放置区域,(或命名为 copyright)用于底部
left|right|center  // 左右中

导航命名

text
nav|navbar|navigation|nav-wrapper  // 导航条或导航包,代表横向导航
topnav     // 顶部导航
mainbav    // 主导航
subnav     // 子导航
sidebar    // 边导航
left-sidebar|sidebar-l   // 左导航
right-sidebar|sidebar-r  // 右导航
title      // 标题
summary    // 摘要
menu       // 菜单,区域包含一般的链接和菜单
submenu    // 子菜单
drop       // 下拉
dorp-menu  // 下拉菜单
links      // 链接菜单

功能命名

text
logo            // 标记网站logo标志
banner          // 标语、广告条、顶部广告条
login           // 登陆,(例如: 登录表单 form-login)
loginbar        // 登录条
register        // 注册
tool|toolbar    // 工具条
search          // 搜索
searchbar       // 搜索条
searchlnput     // 搜索输入框
shop            // 功能区,表示现在的
icon            // 小图标
label           // 商标
homepage        // 首页
subpage         // 二级页面子页面
hot             // 热门热点
list            // 文章列表,(例如: 新闻列表 list-news)
scroll          // 滚动
tab             // 标签
sitemap         // 网站地图
msg|message     // 提示信息
current         // 当前的
joinus          // 加入
status          // 状态
btn             // 按钮,(例如: 搜索按钮可写成  btn-search)
tips            // 小技巧
note            // 注释
guild           // 指南
arr|arrow       // 标记箭头
service         // 服务
breadcrumb      // (即页面所处位置导航提示)
download        // 下载
vote            // 投票
news            // 新闻
siteinfo        // 网站信息
partner         // 合作伙伴
link|friendlink // 友情链接
copyright       // 版权信息
siteinfoCredits // 信誉
siteinfoLegal   // 法律信息

注释规范

文件注释

  • 文件开头添加注释,描述功能、作者、创建日期等,如:
typescript
/**
 * @fileoverview 该文件定义用户相关 API 服务函数
 * @author John Doe <john@example.com>
 * @date 2025 - 01 - 01
 */

函数注释

  • 复杂函数定义上方添加 JSDoc 风格注释,描述功能、参数、返回值等,如:
typescript
/**
 * 计算两个数的和
 * @param {number} num1 - 第一个数
 * @param {number} num2 - 第二个数
 * @returns {number} 两个数的和
 */
 /**
 * @description@description 描述说明
 * @param param {参数类型} 参数说明
 * @returns returns {返回类型} 返回结果说明
 * @author author 作者
 * @version version 版本号
 * @example  example 示例代码
 * @todo todo 待办的内容描述
 */
function addNumbers(num1: number, num2: number): number {
    return num1 + num2;
}

组件注释

  • Vue 组件 script 标签上方添加注释,描述功能、props、emits 等,如:
typescript
<script lang="ts">
/**
 * @description 用户登录组件,用于用户输入用户名和密码登录
 * @props {string} username - 用户名,默认值为空字符串
 * @props {string} password - 密码,默认值为空字符串
 * @emits {event} login - 用户点击登录按钮且验证通过时触发,传递登录成功用户信息
 */
</script>

Vue开发规范

组件命名

  • views目录下单文件统一采用kebab-case命名,字母小写,以短横分隔单词。
  • 组件名不能和 html 标签元素冲突。
  • 组件名应该以描述性单词开头,以 修饰性单词 结尾。
  • 使用有意义的单词组合, 2~3 个 单词最佳,单词不能过长。
  • 只有一个单词的组件全部都要小写。
text
login.vue
home.vue
user-info.vue
base-config.vue
search-button-clear.vue

紧密耦合的组件名

  • 如果一个组件只在某个父组件的场景下有意义,这层关系应该体现在其名字上,因为编辑器通常会按字母顺序组织文件,所以这样做可以把相关联的文件排在一起。
text
├─ todo-list.vue
├─ todo-list-item.vue
└─ todo-list-item-button.vue

公用组件

局部公用

  • 在当前功能的目录新建 components 文件夹,所有声明的组件放在里面,采用 PascalCase 命名,并且功能目录需要有 index.vue 入口文件。
text
src/views/user-info
├─ index.vue
└─ components/
  ├─ BaseInfo.vue
  └─ UserInfo.vue

全局公用

  • 统一放到工程目录的 src/components 下面,目录名称采用 PascalCase 命名,并且每个公用组件目录必须有 index.vue 入口文件,Attribute属性和 Event 事件的命名都是要用 kebab-case 命名,不能用驼峰命名。
text
src/components/
├─ PageHeader
   └─ index.vue
├─ UploadData
   └─ index.vue

template模版中使用

  • 需要用 kebab-case 命名
vue
<template>
  <div class="app-container">
      <user-info :user-detail="userDetail"></user-info>
    </div>
</template>

组件结构

  • 遵循单一职责原则,一个组件负责一个特定功能。
  • template 简洁,复杂逻辑在 script 中用计算属性或方法处理。
  • 使用 setup 函数编写组件逻辑,通过 defineProps defineEmits 定义属性和事件。全局样式在 src/styles 目录创建文件并在 main.ts 引入。

组件通信

  • 父子组件通信:父传子通过 props ,子组件用 defineProps 定义并指定类型和默认值。
  • 子传父:通过 $emit 触发事件,子组件用 defineEmits 定义,父组件用 v-on 监听。
  • 兄弟组件通信:可通过 中央事件总线 pinia 实现。
  • 跨层级组件通信:推荐 pinia ,简单情况可使用 provide 和 inject 组合。

模板中引入资源和组件的顺序

  • 在模板中引入资源是有顺序的,一般是 先公用后局部 ,资源引入顺序 为js资源 > 组件 > css资源 ,如果引入资源比较多,需要合理的分组并写上注释。
vue
// 引入第三方工具类
import util from "@lime-util/util";
// 引入第三方组件
import VueScroll from "vuescroll";

// 引入公用方法
import { uploadFile } from "@/common";
// 引入公用组件
import PageHeader from "@/components/PageHeader";

// 引入api
import {
  getUserList,
  getUserDetail,
  addUser,
  updateUser,
  deleteUser,
} from "@/api/user";
// 引入局部组件
import UserInfo from "./components/UserInfo";

组件name大写

  • 声明组件的 name 使用 PascalCase 帕斯卡命名,尽量每个组件页面都写,方便 vue 识别,或者在使用 keep-alive 时候做缓存。
vue
defineOptions({
  name: "UpdateForm",
})

传参数属性命名

  • 主要针对 Vue 组件中 attribute 传参,采用 kebab-case 命名,字母小写,以短横分隔单词。

普通attribute

  • 属性类型是 String,Number,Boolean,Object,Array,Date 这几种数据类型,采用 名词 或者 名词+修饰词 形式。
json
{
  "class-name": "类名",
  "z-index": "层级",
  "fullscreen": "全屏显示",
  "show-upload-list": "是否展示上传文件列表"
}

function类型

  • 场景:传参 function 组件除了能传普通的数据类型,还能传递 function ,采用 介词+动词/形容词 形式,注意这里事件名是允许用 on-xx 形式的,用来区分该 props 传递的是个函数。
json
{
  "on-success": "上传成功",
  "on-progress": "上传进度",
  "on-error": "上传失败",
  "on-preview": "预览",
  "before-upload": "上传之前",
  "before-close": "关闭之前",
  "after-close": "关闭之后"
}

组件prop定义

  • 必须使用 camelCase 驼峰命名。
  • 必须指定参数类型。
  • 必须加上注释,表明参数的含义。
  • 必须加上 default 默认值。
  • 推荐加上 required ,如果有业务校验也需要加上 validator
typescript
// 简洁的
const props = defineProps({
  userDetail: Object,
})

// 符合eslint推荐的
const props = defineProps({
  userDetail: {
      type: Object,
      default: () => {}
    },
})

// 更加详情,带业务校验的
const props = defineProps({
  userDetail: {
      type: Object,
      required: true,
      validator: function (value) {
        // 校验
      }
    }
})

函数命名

绑定事件监听

  • 绑定的事件名采用 kebab-case 命名,字母小写,以短横分隔单词。因为在 Dom 模板 中的事件监听,由于 HTML 中是不区分大小写的,Vue 会自动转换事件监听为全小写,所以推荐 始终使用 kebab-case 的命名。
  • 事件的命名采用动词形式,事件绑定本身就是 v-on 指令,不能写成 v-on:on-close ,所以绑定的事件统一都不用 on-xx 的形式。
json
{
  // 原生事件监听
  "input": "输入",
  "change": "改变",
  "blur": "失去焦点",
  "focus": "聚焦",
  "submit": "提交",
  "keyup": "提交",
  "keydown": "提交",
  "enter": "提交",
  "submit": "提交",

  // 自定义事件监听
  "preview": "预览",
  "clear": "清空",
  "cancel": "关闭",
  "open": "打开",
  "select-change": "选择",
  "select-all": "选择所有",
  "selection-change": "选项改变",
  "sort-change": "排序",
  "row-click": "单击行",
  "row-dblclick": "双击行"
}
  • 在声明 事件监听函数 或者声明 props 绑定函数 的时候有些是需要用 onXxx 的形式,有些则可以不带 on,具体要看当前环境中的作用和语义。
typescript
// 组合1
function onInput() {}
function onPreview() {}
function onSelectAll() {}
function onRowClick() {}
function onSelectionChange() {}

// 组合2
function beforeUpload() {}
function beforeOpen() {}
function beforeClose() {}

自定义事件

  • 自定义事件名使用 camelCase 驼峰命名,命名为 动词+名词 形式。
  • 名称不能过长,要明确表达此事件处理的作用,避免望文不知义。
  • 可以参考 JavaScript 规范中 函数命名 章节,使用常用的动词来命名。
  • 一般由页面直接或者间接发起的操作,用 handleXxx 的形式。
typescript
function handleSearch() {}
function handleReset() {}
function handleResize() {}
  • 由方法发起调用的操作,用 动词 开头的形式,命名看方法的用途决定
typescript
function resetQuery() {}
function resetForm() {}
function resetSelect() {}
  • 在其他场景下,很多命名方式也都可以用 动词+形容词/名词 形式,例如 elect+范围,元素+click,change+元素,clear+元素 ,这些动词开头,用在改变元素,改变分页,改变业务状态,切换 Modal 弹框显示等等。
typescript
// 组合1-元素操作
function selectOne() {}
function selectAll() {}
function tabClick() {}
function switchTab() {}
function clearName() {}

// 组合2-分页
function changePageNum() {}
function changePageSize() {}
function jumpPage() {}

// 组合3-业务弹框
function showAddModal() {}
function showEditModal() {}
function showDetailModal() {}
function showSyncDataModal() {}
function showUserInfoModal() {}
function showDepartTreeModal() {}

// 组合4-业务状态
function changeUserStatus() {}
function changeUserStatus() {}
function changeUserPermission() {}

异步处理方法

  • 在了解过接口命名规则之后,前端页面中使用 Api 接口 的异步事件,这些一般比较固定,以下组合列举出了一些场景。
typescript
// 组合1
// 查询的是后台返回的列表,推荐是用 queryXxxList 这种形式
function queryList() {}
function queryMenuList() {}
function queryUserList() {}
function queryDetail() {}

// 组合2
// 查询的是后台返回的数据信息,详情等,推荐用 queryXxx+Data/Info/Detail 这种形式
function queryProcessData() {}
function queryStepInfo() {}
function queryTaskDetail() {}

// 组合3
// 页面增删查改的操作,用 handleXxx 的形式
function handleAdd() {}
function handleEdit() {}
function handleDelete() {}
function handleSubmit() {}

Git 提交规范

  • 采用 Conventional Commits 标准:
typescript
<type>(<scope>): <subject>
# 示例
feat(user): add password reset UI
fix(router): handle 404 redirect
chore(deps): upgrade axios to 1.2.0

常用 type

  • feat: 新功能
  • fix: Bug修复
  • docs: 文档变更
  • style: 代码样式调整
  • refactor: 重构(不修复 bug 也不增加功能)
  • test: 测试相关
  • chore: 构建/工具变更