项目规范
常用命名法有以下几种:
camelCase
(小驼峰式命名法 — 首字母小写)PascalCase
(大驼峰式命名法 — 首字母大写)kebab-case
(短横线连接式命名法)Snake
(下划线连接式命名法)
项目名命名
全部采用[短横线命名法]
,字母均为小写,单词分词以短横线分隔。
具体项目名可根据部门或团队,项目或项目名等综合命名。团队名非必须。
如:[部门/团队]-[项目/产品名]-[admin/h5/mobile]
说明:
- 项目/产品名采用短横线命名法。例如:
my-project-name
- admin 可用来表示管理端
- h5 用来表示移动端 H5
也可使用 mobile 表示 M 栈,app 表示原生 APP 中内嵌的 H5。
目录名命名
同样采用[短横线命名法]
。
- 目录存在复数则采用复数命名。例:docs、assets、components、directives、mixins、utils、views。
- 多词目录,采用 短横线“-” 分割词语。例:system-config
目录结构示例如下:
my-project-name/
|- .vscode //
|- extensions.json //推荐VS CODE扩展安装配置
|- launch.json //vs code启动文件配置,可调试node_modules中文件和nodejs项目
|- settings.json //配置项目级别的格式化等信息
|- build // 流水线部署脚本目录
|- config // 可配置如dev、test、prod三个环境所需的配置文件。(可选)
|- docs // 项目文档目录(可选),可存储设计文档,需求文档,TODO.md等
|- nginx // 部署在容器上前端项目nginx代理文件目录
|- node_modules // 下载的依赖包
|- public // 静态页面目录
|- index.html // 项目入口
|- src // 源码目录
|- api // http 请求目录
|- assets // 静态资源目录,这里的资源会被wabpack构建
|- icons // icon 存放目录
|- imgs // 图片存放目录
|- js // 公共 js 文件目录
|- css // 样式存放目录,可同事支持sass、stylus文件
|- global.scss // 全局公共样式,提供统一的水平,垂直居中等公共样式类库
|- element-ui.styl // 重写elementUI样式
|- vant.styl // 重写vant样式
|- project.styl // 定义项目级别的统一样式,如Button按钮颜色和居中,
|- components // 组件库(大驼峰或短横线命名方式二选其一)
|- HeaderSearch //头部搜索组件
|- index.vue
|- DynForm //动态表单组件
|- index.vue
|- define // 常量,变量的定义
|- constant.js //常量
|- enums.js //定义的枚举
|- event.js //定义的事件
|- libs // 依赖库
|- http // http请求库
|- axios.js // axios文件
|- fetch.js //fetch请求库
|- utils // 工具存放目录
|- converter.js // 转换器
|- checker.js // 类型检查器
|- storage.js // 存储器
|- plugins // 插件
|- router // 路由
|- modules // 各模块的路由定义,方便各成员编辑路由防止冲突
|- home.js // 首页路由
|- xxx.js // 其他模块路由
|- index.js //动态加载聚合各模块路由
|- constant-routes.js //固定路由,如404,nopermission等
|- index.js // 加载modules和constant-routes路由,聚合导出全部路由
|- store // 全局状态管理
|- views // 单页面存放目录
|- system-config
|- Index.vue
|- pages // 多页面应用存放目录
|- App.vue // 根组件
|- main.js // 入口文件
|- tests // 测试用例
|- .browserslistrc// 浏览器兼容配置文件
|- .editorconfig // 编辑器配置文件
|- .eslintignore // eslint 忽略规则
|- .eslintrc.js // eslint 规则
|- .gitignore // git 忽略规则
|- babel.config.js // babel 规则
|- Dockerfile // Docker 部署文件
|- jest.config.js
|- package.json // 依赖
|- README.md // 项目README,编写项目介绍,安装,依赖等描述文件
|- vue.config.js // webpack 编译打包配置文件
|- yarn.lock // YARN生成的版本锁定文件
补充说明:
- docs 目录:不建议存储太多文档,会影响 git 的 clone、占用过多存储空间
- tests 目录:测试用例目录结构按照 views 中的模块页面。 建议测试用例文件也都创建在 tests 目录,而不是在开发页面统计目录创建测试用例文件。
- 页面存储目录:单页面应用存储在 views 中,多页面应用存储到 pages 中
文件命名
文件名命名单词都应为名词,非动词。
如:推荐:logger.service.js
,不推荐:log.service.js
单词较长可采用简写,如 message 可简写 msg 等,变量命令可通过CODELF检索确定,VS Code 也可以搜 Codelf 插件。
文件夹采用 [短横线],全部字母小写
views 下交易页面文件夹 ,例:user-settings
(重点)
因为 npm 包的命名规范是短横线,所以也建议约定目录命名规范也是短横线,便于统一共识。JavaScript 文件采用 [短横线],全字母小写
例:event-bus.js
具有不同角色功能模块可通过**.[模块名称].[js/ts]
符号分割区分。
例:message.service.js
、message.controller.ts
、message.provider.ts
。css 文件采用 [短横线],全字母小写
例:element-ui.js
、date-picker.js
html 文件采用 [下划线] 连接,全字母小写
例:error_message.html
图片等资源文件采用 [下划线] 连接,全字母小写
例:banner-head.jpg
、card-bg.png
切记:不要使用中文,不要使用中文,不要使用中文。
容易导致部署后图片显示不出来,发现很多项目中居然一直有使用中文命名。Vue 文件采用 [大驼峰]
例:Layout.vue
、MyComponent.vue
代码规范
代码规范主要目标:
- 代码整洁,提高可阅读和可维护性。
建议参阅《代码整洁之道》,了解如何编写整洁代码。 - 提高应用的健壮性
避免踩坑,避免隐藏 bug
代码编写过程中如有未完成,可通过//TODO:[待做事项]
标记
VS Code 可安装【Todo Tree】插件,查看所有待做事项。 标记 TODO 的优点主要体现在,在编程过程中,可先编写主流程代码(类似伪代码),通过处理分线事项标记 TODO 事项即可。这样逻辑主线清晰,分线任务后续再详细实现细节。这样开发效率高、功能稳定可靠。
变量函数命名
- 常量命名:单词全部大写,分词使用下划线
例如:MAX_COUNT=100
- 变量命名:
私有变量,建议采用以下划线 _ 为前缀,例:let _dataType=0
ES12 新特性的私有变量采用#,如下建议未使用 ES12 新特性时,使用**_**作为私有变量标记。class Student { get #Age() { return 18; } get publicAge() { return this.#Age; } }
- 公共变量:建议采用 [小驼峰],例:
dataType=0
- 函数命名采用 [小驼峰],动词 + 名词形式 例:
goPage(){}
、getOrderList()
、commitFormData()
常用动词:can、has、is、get、set、commit、post、open、show - 事件命名
采用 [小驼峰],以on为前缀,即:[on]+[名称(可选)]+[动词]
例:onButtonClick(){}
路由命名
- 路由 path 命名采用 [短横线],全字母小写 例:
/route-path
,因为浏览器只能识别短横线 - - 命名符合 RESTful API
可参考阮一峰大神的文章 RESTful API 最佳实践,概括如下: 1. 动词 + 宾语 命令是动词(如 GET),path 是宾语如:/articles
2. 动词的覆盖 服务器必须接受 POST 模拟其他三个方法(PUT、PATCH、DELETE) 3. 宾语必须是名词 例如:/articles
,/getAllCars
是错误的 4. 复数 URL
比如GET /articles/2
要好于GET /article/2
5. 避免多级 URL
推荐:GET /authors/12?categories=2
不推荐:GET /authors/12/categories/2
编码规范
先对比两种写法:
写法一
async function submit() {
if (!elForm) return;
loading.value=true;
await elForm.validate((valid, fields) =>{
if (valid) {
serviceApi.submit().then((res)=>{
if(res.code===200){ //业务代码code=200,表示业务处理成功
//处理数据,如:tableComponent.data=res.data
loading.value=false;
}else if (res.code===210){
//业务有特定分支,需要执行不同逻辑,则执行不同代码。
} else {
loading.value=false;
//业务类型错误
//通常情况无特定业务执行逻辑,则可以都返回错误信息即可
ElMessage.error(res?.message)
}
})
}.catch(err=>{
//主要是通信类型的错误,如404,405等
loading.value=true;
ElMessage.error(res?.message)
})
}
});
写法二(推荐)
async function submit() {
//el-form组件执行表单支持promise,直接执行validate校验即可。
//不需要放到try catch中捕获表单校验异常,因为此异常已表现在表单界面上
await elForm?.validate();
loading.value = true;
try {
const res = await serviceApi.submit();
//处理数据,如:tableComponent.data=res?.data?.list || []
//执行其他js操作
} catch (err) {
if (err?.code === 210) {
//业务有特定分支,需要执行不同逻辑代码。通常不回执行
} else {
//建议错误信息字段为message
//因为trycatch可以报错“执行其他js操作”时的js错误,js Error的错误信息字段是message
//使用message可以在同时捕捉js错误和业务异常时提示错误信息,
ElMessage.error(err?.message);
}
} finally {
loading.value = false;
}
}
对比写法一和写法二,可以看出差异。好的代码编写方式和约定可以使程序较少异常,更加稳定。
项目的约定如下
1. 参照“写法二”。逻辑代码要采用try catch方式判断异常并提示消息。
原因如下:
- 省去了大部分请求写判断 res.code!=200的代码
- try catch中有非请求的其他逻辑代码时 也可以捕获到异常信息并弹出错误。
- 因为JS的Error对象的错误信息属性是message,后台返回的是msg ,所以统一返回了message,这样try catch捕获js错误和后台错误都可以统一弹出message作为错误消息
2. 使用对象属性时,尽量不使用解构对象。
因为 const obj={name:'名称'}; 使用获取name属性 { name }=obj;
const obj={name:'名称'};
const { name }=obj; //使用解构时,当obj=null/undefined时,则js就会报错。
//不如直接 obj?.name 获取属性值更直观方便
3. 对象属性类型要写可选链,即问号
- 如 获取用户名称 = data?.userinfo?.name || '用户名' 可选链?为了避免对象属性中有任何一个字段为null都不会报错,并且若值为空,则给默认值。
- 并且vue的中绑定字段也要判断每个属性空值,否则会白屏,并且无任何报错。如下:(若userinfo为空,则白屏不会报错)
<template>
<div>{{data.userinfo.name}}</div>
</template>
正确做法 vue3+volar插件,可以支持dom绑定可选链
<template>
<div>{{data?.userinfo?.name}}</div>
</template>
4. API的参数要定义类型。
API接口定义类型是为了跟后台服务API接口规范保持一致,比如必填非必填,字段类型。 和后台服务接口保持一致,则开发和编译阶段就能快速报错类型或必填错误,避免遗漏或者API参数错误导致接口异常。
updateUser(data: { username: string; nickName?: string,phone?:string }) {
return Http({ method: 'POST', data, url: BaseURL + '/user/update' })
},
5. Typescript编写,则可定义类型(如 interface,function 等)
- 若需要多出使用或公共数据模型,则定义到/types目录下,并配置tsconfig.json中的include包"types/**/*.d.ts"。
- 定义Typescript类型,可以多使用Typescript继承的Partial、Required、Record、Pick、Omit等类型
- 引入的第三方模块,若提示找不到模块,如可以在types/index.d.ts进行声明
declare module '3th-module'
注释
函数命名可一看知其意,则不建议添加注释。
添加注释主要标注以下几方面:
- 说明业务注意点
- 业务逻辑实现是如何考虑
- 附上引用第三方 API 的链接地址,方便维护者再次查看
项目 UI/UE
产品和设计的风格要保持统一,约定好同类型页面如何布局等。 也建议开发团队给团队人员指定好基准页面,让项目成员参照开发。
- 请求数据地方都要加 loading
- 页面数据加载建议使用骨架屏
- 提交按钮上加 loading 效果
- 表格要添加斑马线
- 提示或异常消息,统一提示文案的结尾没有叹号等标点
项目约定
- 有主题皮肤颜色设置的。 适配主题主题空间都无需设置背景颜色,字体颜色等。 针对主题颜色功能,编辑UI时尽量使用组件库,若组件库主题色没生效反馈负责人,若必须自定义的则使用变量$theme-color即可
- 按钮都建议使用el-button,否则需要使用$theme-color变量同步主题颜色
- el-button 需要显示主题的则使用 type="primary"类型按钮,无需再设置颜色。
- div 实现的按钮,则 class 添加 $theme-color
- 引入资源Icon时,尽量使用svg格式的, 图片如果UI可以导出svg,也优先使用svg,只有图片的图片上传到cdn。
- vite可以使用vite-plugin-svg-icons插件
- vue-cli脚手架可以使用svg-sprite-loader插件
- 图片需要使用el-image,设置预览属性preview-src-list和initial-index 默认打开的图片索引