写在前面
- 开发规范是为了作用于团队,保证团队的高效协同工作
- 规范的最好维护原则即团队每个成员的严格执行,以及客观的错误总结、完善
- 规范不是为了抹灭开发过程中的自由度等,只是避免过度个性化,降低沟通成本
- 代码的质量并不由代码规范所保证,质量在于切实提高稳定性,减少踩坑可能性,避免踩同一个坑,小心过早优化等
- 代码规范需要配套的检测工具,不要信任人的自觉性
- 必要的代码设计与文档沉淀
代码规范参考Code Guide,并在此基础上有所改动,部分示例可以参考
统一规范
- 缩进:采用
4空格
缩进,使用tab - 编码:UTF-8
文件顶部、类、接口声明作者邮箱和时间
1
2
3
4
5/**
* Author: xxxx@mail.com
* Date: 2018-03-04
* Desc: 可省略,选择性填写项
*/1
2
3<!--Author: xxx@mail.com
Date: 2019-03-04
Desc: 可省略,选择性填写项-->换行符统一使用’LF’(Unix格式)
- 行尾不要有空白字符
- tab和space不能混用
- 代码中不能提交
debug, console.error
- 注释需要和代码保持同步,禁止修改代码后对注释一直不改动
- 单行代码不超过80字符
命名规范
含义与功能匹配的全英文、国际通用的拼音(例如:hangzhou)、常见英文缩写
- 【强制】 项目命名: 小写,尽量保持一个单词,多个单词以下划线’_’分隔,例如
my_project
- 目录命名: 小写,英文复数形式,例如
images, utils, data_models
- js文件、less文件、HTML文件、资源文件等,与项目命名规则相同
- Vue文件名:UpperCamelCase风格,例如
MultiSelect.vue
,使用时采用<multi-select></multi-select>
方式 - class命名:小写单词加中划线’-‘分隔或者lowerCamelCase风格,例如
page-edit-link, pageEditLink
- id命名、less中的变量、函数等:lowerCamelCase风格
- 编程变量命名:
- 普通变量(成员变量、局部变量)、方法名、参数等使用lowerCamelCase风格, 私有属性、方法以下划线开头,例如
_getTypes
- 常量全大写加下划线’_’分隔,例如
MAX_LIMIT
- 类名使用UpperCamelCase风格,抽象类以Abstract或者Base开头,测试类以Test结束,异常类使用Exception结尾,类名若涉及设计模式,将设计模式体现在命名中,例如
QueryProxy
- 不使用魔法数字或魔法字符串
- ‘ID’在变量名中全大写
- ‘URL’在变量名中全大写
- ‘Android’在变量名中大写第一个字母
- ‘iOS’在变量名中小写第一个,大写后两个字母
- jquery对象必须以’$’开头命名
- 普通变量(成员变量、局部变量)、方法名、参数等使用lowerCamelCase风格, 私有属性、方法以下划线开头,例如
HTML
- 启用标准模式,
<!DOCTYPE html>
- 引号:属性值使用双引号,
<img src="images/company_logo.png" alt="Company">
- 注释:使用
<!-- html 注释 -->
- 尽量避免使用内联样式
区分开行内元素及块级元素, 不建议使用行内元素包裹块级元素的做法,然后使用display进行更改
1
2
3
4
5
6
7
8
9
10
11
12
13
14<!-- not good -->
<style>
.article {
display: block;
}
</style>
<span class="article">
<p>这里是内容</p>
</span>
<!-- good -->
<article>
<p>这里是内容</p>
</article>单标签不需要封口,类似于img,br,link…之类的标签不需要进行封口
属性顺序
1
2
3
4
5class
id
src等原生属性 for, type, href, value, max-length, max, min, pattern
placeholder, title, alt
aria-*, role, required, readonly, disabled如果可以做一个温暖的开发者,多给点时间给aria-*和role
- 多使用H5语义化标签
1
2
3
4
5
6<section>
<nav>
<article>
<aside>
<header>
<main>
更多新标签可参考H5标签列表
CSS
- 避免
!important
的使用 - 避免通配符
*
的使用 - 小数点前的0省略,
font-size: .4rem;
- 属性值0后的单位省略,
margin: 0 auto;
- 字体系列名称中必须含有通用族,且禁止重复字体系列
- 颜色值使用十六进制小写,且使用短模式
- 禁止重复规则和空规则
空格
需要空格的地方
- 冒号后,逗号后
: ,
- 选择器
> , + , ~
前后 - 属性前
- 大括号前后
{
- 注释之间,
/* css 注释 */
- 冒号后,逗号后
不需要空格的地方
- 小括号前后
- 分号:每个属性声明末尾都要使用分号
- 引号:单引号,
background-image: url('../logo.png');
- 注释,只在特殊情况处添加注释,其他时候避免注释,注释之前建议空行
- 属性简写
属性简写需要你非常清楚属性值的正确顺序,而且在大多数情况下并不需要设置属性简写中包含的所有值,所以建议尽量分开声明会更加清晰;
其中 margin 和 padding 相反,需要使用简写,减少浏览器的重排
常见简写属性:font, background, transform, transition, animation, margin, padding 属性书写顺序
常见属性书写顺序,分组见添加空行,完整版请戳css属性推荐书写顺序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25.declaration-order {
display: block;
float: right;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 100;
border: 1px solid #e5e5e5;
border-radius: 3px;
width: 100px;
height: 100px;
font: normal 13px "Helvetica Neue", sans-serif;
line-height: 1.5;
text-align: center;
color: #333;
background-color: #f5f5f5;
opacity: 1;
}
JavaScript
空格
需要空格的地方
- 二元和三元运算符前后
- 代码块
{
前 - 模块引入
import
值之间,例如import { users } from './login';
- 属性名的冒号后
- 大括号前
{
- 部分关键词后:
if, else, for, while, do, switch, case, try, catch, finally, with, return, typeof
- 函数的入参之间
- 函数声明或函数表达式的
{
前 - for循环条件中的分号和逗号后
- 单行注释
//
后,行内单行注释前,多行注释的星号后
不需要空格的地方
- 一元运算符前后,
++i
- 对象属性名后
- 函数声明或函数表达式的
(
前 - 运算符的
(
后和)
前 - 对象的
{
后和}
前 - 数组的
[
后和]
前
- 一元运算符前后,
分号
以下情况必须使用分号1
2
3
4
5
6
7
8变量声明
表达式
import
return
throw
break
continue
do-while引号,使用单引号,使用模板字符串(template string)代替双引号的使用场景
- switch的falling through和default以及if等控制语句必须添加注释
- 如果出现对上下文this的引用,统一使用’self’代替,多使用箭头函数避免引用的场景
- 用’===’, ‘!==’代替’==’, ‘!=’
- 避免var的使用,变量声明紧跟在变量的使用处
- 使用构造函数后需要赋值给某个变量
- 不使用未声明变量
- 变量声明后必须使用
- 缩短变量的生命周期,减少全局变量的使用
- 做好异常的分类处理,避免一把抓的catch;对外部数据保持怀疑,必须做好数据验证以及容错处理
- 函数保持功能的单一性,一个函数只做负责一个功能
- 函数入参不能超过3个,超出考虑声明一个类或者使用对象
- 构造函数中不能加入业务逻辑
注释
工具、类、接口、全局变量、枚举变量等必须有注释,逻辑转折处必须有注释,特殊逻辑或者难以理解代码必须有注释
注释只在必要处出现,且保证注释的准确和精简,过多或错误的注释只会造成开发阻碍,一旦代码逻辑或者类型更改,记得及时更新注释1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42if (condition) {
// if you made it here, then all security checks passed
callback();
}
const user = {
name: 'youzi', // one space after code
age: 18,
};
/**
* @let {object}
* @property {string} a - 属性a
* @property {string} b - 属性b
*/
let foo = {
a: 'a',
b: 'b'
}
/**
* @func foo
* @desc 一个带参数的函数
* @param {string} a - 参数a
* @param {number} b=1 - 参数b默认值为1
* @param {string} c=1 - 参数c有两种支持的取值</br>1—表示x</br>2—表示xx
* @param {object} d - 参数d为一个对象
* @param {string} d.e - 参数d的e属性
* @param {string} d.f - 参数d的f属性
* @param {object[]} g - 参数g为一个对象数组
* @param {string} g.h - 参数g数组中一项的h属性
* @param {string} g.i - 参数g数组中一项的i属性
* @param {string} [j] - 参数j是一个可选参数
*/
function foo(a, b, c, d, g, j) {}
/**
* @func
* @desc 一个带若干参数的函数
* @param {...string} a - 参数a
*/
function bar(a) {}其他更详细注释标准参考JSDoc Guide
Vue
- 自定义组件命名需要两个单词以上
props原子化,尽量只使用原始类型,避免对象类型
1
2
3
4
5
6
7
8
9
10
11
12<!-- good -->
<range-slider
:values="[10, 20]"
:min="0"
:max="100"
:step="5"
@on-slide="updateInputs"
@on-end="updateResults">
</range-slider>
<!-- not good -->
<range-slider :config="complexConfigObject"></range-slider>验证组件的props,且props必须提供默认值、声明类型和必要的注释
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21<template>
<input type="range" v-model="value" :max="max" :min="min">
</template>
<script type="text/javascript">
export default {
props: {
max: {
type: Number, // 这里添加了数字类型的校验
default() { return 10; },
},
min: {
type: Number,
default() { return 0; },
},
value: {
type: Number,
default() { return 4; },
},
},
};
</script>模块化组件需要提供API文档和demo
更多建议参考vue组件规范
更多建议杂项
- 不在视图模板中添加复杂逻辑处理
- 条件判断如果有复杂逻辑,提前赋值给有意义的布尔变量,提高可读性
- 对于类的属性和方法确认好访问权限,全面开放状态不利于后期的重构
- 用户个人页面或功能都进行权限校验
- 用户的敏感数据不直接展示
- 用户请求的任何参数都要做有效性校验
- 禁止对HTML页面输出未经转义或安全过滤的用户数据
- 对用户操作做好防重复措施或平衡高频操作,例如发送验证码,即时通信等
- 防止NPE(空指针异常)场景,常见场景:网络请求返回空对象直接使用;链式操作等
- 异常捕获后必须处理,保证程序的正常运行
- 异常操作不要置于流程、条件控制或循环中
- 谨慎记录日志,日志要确保必需性与全面性
- 谨慎删除代码,但也需要及时清理垃圾代码
- 坚持注释的准确和同步的特点;避免注释的滥用,合理的命名和代码结构是会说话的,当你需要大篇幅的注释时可以考虑如何优化你的代码了
- 合理利用
// TODO
并及时完成,TODO信息中必须留下作者、时间以及待办事项、原因、初步方案等 - 系统设计时尽量依赖抽象类和接口,对扩展开放,对修改闭合,底层设计需要评审通过后沉淀为文档