不管有多少人共同参与同一项目,一定要确保每一行代码都像是同一个人编写的。
通用规范
命名
常见命名格式:
- camelCase(驼峰命名、小驼峰)
- PascalCase(帕斯卡命名、大驼峰)
- snake_case(蛇形命名、下划线命名)
- kebab-case(脊柱命名、中划线命名)
- StUdLyCaPs(匈牙利命名)
- lowercase(纯小写命名)
- UPPERCASE(纯大写命名)
命名规范
- 文件夹的命名: 纯小写(如果不能, 就采用小驼峰)
- 普通文件: 小驼峰
- 组件名、组件文件名: 大驼峰
- javascript里变量、方法名和view/page文件名: 小驼峰
- javascript里类、构造函数: 大驼峰
- javascript里的全局常量: 纯大写
- css中的class、id: 中划线命名
- 图片资源: 下划线命名(强制), 同时尽量带上倍数(非强制), (例如: pop_icon_show@2x.png)
- 其它多媒体资源(音视频资源或其他资源): 下划线命名
缩进
所有类型文件统一采用2个space作为缩进
HTML
标签使用必须符合标签嵌套规则
1 | <!-- good --> |
元素属性使用双引号语法
1 | <!-- good --> |
注释写法
1 | <!-- 代码注释 --> |
类型属性
不需要为 CSS、JS 指定类型属性,HTML5 中默认已包含1
2
3
4
5
6
7<!-- good -->
<link rel="stylesheet" href="" >
<script src=""></script>
<!-- avoid -->
<link rel="stylesheet" type="text/css" href="" >
<script type="text/javascript" src="" ></script>
JAVASCRIPT
语言规范
- 不可变动的引用采用
const
, 否则使用let
- 对象和数组, 使用字面量方式来创建
使用对象方法的简写方式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17// good
const item = {
value: 1,
addValue (val) {
return item.value + val
}
}
// avoid
const item = {
value: 1,
addValue: function (val) {
return item.value + val
}
}使用对象属性值的简写方式
1 | const job = 'FrontEnd' |
- 对象属性值的简写方式要和声明式的方式分组
1 | const job = 'FrontEnd' |
- 使用拓展运算符
...
复制数组
1 | // good |
- 解构赋值
1 | // good |
- 请使用函数声明,而不是函数表达式
1 | // good |
- 不要使用
arguments
,可以选择使用...
1 | // good |
- 禁止使用
eval()
,with()
代码规范
基本遵循 StandardJS 的规范
详情请参考 StandardJS 细则
以下仅罗列最常见最重要的规范
- 两个空格缩进
- 无分号风格
- 单引号
- 使用严格等于
===
!==
- 多行注释参考
jsdoc
, 单行注释//
- 逗号后面空格, 前面无空格; 逗号放置在当前行的末尾
- 不要省去小数点前面的
0
- 检查 NaN 的正确姿势是使用
isNaN()
- 嵌套的代码块中禁止再定义函数
避免在
return
语句中出现赋值语句1
2
3
4// avoid
function sum (a, b) {
return result = a + b
}对于三元运算符 ? 和 : 与他们所负责的代码处于同一行
1
2
3
4
5
6
7
8
9
10
11
12// good
const location = env.development ? 'localhost' : 'www.api.com'
// good
const location = env.development
? 'localhost'
: 'www.api.com'
// avoid
const location = env.development ?
'localhost' :
'www.api.com'如果有更好的实现,尽量不要使用三元表达式
1
2
3
4// good
let score = val || 0
// avoid
let score = val ? val : 0finally
代码块中不要再改变程序执行流程1
2
3
4
5
6
7
8// aovid
try {
// ...
} catch (e) {
// ...
} finally {
return 42
}函数调用时, 禁止使用空格
1
2
3
4// good
fn()
// avoid
fn ()禁止使用链式赋值
1
2
3
4
5
6
7// good
var a = 1
var b = 1
var c = 1
// avoid
var a = b = c = 1一个声明只能有一个变量
1
2
3
4
5
6
7// good
var a
var b
var c
// avoid
var a, b, c要加空格的几种情况
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16// 代码块前要添加空格
if (a) {
b()
}
function a () {}
// 函数声明括号前要加空格
function func (x) {
// ...
}
// 操作符前后都需要添加空格
var sum = 1 + 2
// 关键字后面加空格
if (condition) { ... }
CSS
统一采用expand
展开模式
1 | /* good */ |
选择器
- 不使用 ID 选择器
- 控制选择器层级数, 选择器要尽可能短, 并且尽量限制组成选择器的元素个数, 建议不要超过 3
代码风格
- 以组件为单位组织代码段
- 每个属性声明末尾都要加分号;
左括号与类名之间一个空格,冒号与属性值之间一个空格
1
2
3
4
5
6
7
8
9/* good */
.dialog-wrap {
width: 100%;
}
/* avoid */
.dialog-wrap{
width: 100%;
}逗号分隔的取值,逗号之后一个空格
1
2
3
4
5
6
7
8
9/* good */
.dialog-wrap {
box-shadow: 1px 1px 1px #333, 2px 2px 2px #ccc;
}
/* avoid */
.dialog-wrap{
box-shadow: 1px 1px 1px #333,2px 2px 2px #ccc;
}为单个css选择器或新申明开启新行
属性值十六进制数值能用简写的尽量用简写
1
2
3
4
5
6
7
8
9
10
11/* good */
.dialog-header,
.dialog-body,
.dialog-bottom {
color: #fff;
}
/* avoid */
.dialog-header, .dialog-body, .dialog-bottom {
color: #ffffff;
}不要为
0
指明单位1
2
3
4
5
6
7
8
9/* good */
.dialog-body {
margin: 0 20px;
}
/* avoid */
.dialog-body {
margin 0px 20px;
}属性值引号: css属性值需要用到引号时,统一使用单引号
1
2
3
4
5
6
7
8
9/* good */
.dialog-body {
font-family: 'Hiragino Sans GB';
}
/* avoid */
.dialog-body {
font-family: "Hiragino Sans GB";
}
推荐属性书写顺序
- 布局定位属性:display / position / float / clear / visibility / overflow
- 自身属性:width / height / margin / padding / border / background
- 文本属性:color / font / text-decoration / text-align / vertical-align / white- space / break-word
- 其他属性(CSS3):content / cursor / border-radius / box-shadow / text-shadow / background:linear-gradient …
CSS3浏览器私有前缀写法
浏览器私有前缀在前,标准前缀在后
1 | .dialog-wrap { |
注释规范
- 注释以字符
/*
开始,以字符*/
结束 - 注释内容第一个字符和最后一个字符都是一个空格字符,单独占一行,行与行之间相隔一行
SASS & LESS
遵循css的基础上,此外还有如下规范
选择器嵌套避免层级过深、过于复杂, 从html的结构上开始精简, 合理规划html结构
变量 - 可复用属性尽量抽离为页面变量,易于统一维护
小程序Taro-最佳实践
- 遵循上述js规范
- JSX中采用单引号包裹属性, 如果出现双引号, 可能会导致编译错误
- 组件传递函数属性名以
on
开头 - 组件中不要在
state
与props
上用同名的字段 子类的构造器中一定要调用 super
1
2
3
4
5
6
7
8
9
10
11
12
13// good
class Dog extends Mammal {
constructor () {
super()
}
}
// avoid
class Dog {
constructor () {
super()
}
}使用 this 前请确保 super() 已调用
对齐方式-多个属性,多行书写,每个属性占用一行,标签结束另起一行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19// good
<Foo
superLongParam='bar'
anotherSuperLongParam='baz'
/>
// avoid
<Foo superLongParam='bar'
anotherSuperLongParam='baz' />
// 如果组件的属性可以放在一行就保持在当前一行中
<Foo bar='bar' />
// 多行属性采用缩进
<Foo
superLongParam='bar'
anotherSuperLongParam='baz'
>
<Quux />
</Foo>当标签没有子元素时,始终使用自闭合标签
终始在自闭合标签前面添加一个空格
1
2
3
4
5
6// good
<Foo className='stuff' />
// avoid
<Foo className='stuff'></Foo>
<Foo className='stuff'/>属性名称始终使用小驼峰
- 用括号包裹多行
JSX
标签 map
循环时请给元素加上key
属性, 避免使用index
, 如果只有index
可以这么使用String(index)
- 避免在
componentDidMount
中调用this.setState
, 因为在componentDidMount
中调用this.setState
会导致触发更新 - 不要在
componentWillUpdate/componentDidUpdate/render
中调用this.setState
this.setState
能一次调用的, 就不要多次调用, 除非逻辑控制需要- 不要定义没有用到的
state
ScrollView
里避免包裹Video/Canvas/Textarea/Map
, 涉及到层级问题- 书写顺序
1
2
3
4
5
6
7
8
9
10
11
12
13在 Taro 组件中会包含类静态属性、类属性、生命周期等的类成员,其书写顺序最好遵循以下约定(顺序从上至下)
1 static 静态方法
2 constructor
3 componentWillMount
4 componentDidMount
5 componentWillReceiveProps
6 shouldComponentUpdate
7 componentWillUpdate
8 componentDidUpdate
9 componentWillUnmount
10 点击回调或者事件回调 比如 onClickSubmit() 或者 onChangeDescription()
11 render
图片
格式选择
- GIF: 动图
- PNG8、PNG24: 带透明通道, 纯色块线条图标,优先考虑使用 PNG8 格式, 图像颜色丰富而且图片文件不太大的(40KB 以下)或有半透明效果的优先考虑 PNG24 格式
- JPEG: 大图, 用于展示内容的图, 图像颜色丰富而且文件比较大的(40KB - 200KB)优先考虑 JPEG 格式
- WEBP: 兼容性差, 仅条件允许时使用, 可带透明通道
大小限制
PC平台单张的图片的大小不应大于 200KB。
移动平台单张的图片的大小不应大于 100KB。
图片质量
控制在60-80.
CODE REVIEW
- 规则: 所有影响到以往流程的功能需求更改发版前都需要 code review
- 执行者: 初级程序员可由中级程序员的执行 code review , 中级程序员可由高级程序员执行 code review, 以此类推
- 反馈: 每次code review都需要有反馈,要对本次code review负责, 反馈内容基本如下
1 | 功能:本次主要是修改了什么功能或者bug |
版本管理
git-flow 备忘清单
采用 git-flow
方式进行代码的版本管理master
: 主分支, 线上生产环境跑的分支develop
: 开发分支, 功能开发完毕后集成到此分支feature
: 功能分支, 每个小功能单独开一个功能分支, 尽可能避免无依赖关系的功能在同一个分支上release
: 发布分支, 功能开发完毕集成到develop分支之后, 从develop拉取的预发布分支, 在发布分支上进行测试, finish之后会同时合并到master分支和develop分支hotfix
: 修复分支, 线上出现bug之后,拉取的修复分支,finish之后和release一样会同时合并到master分支和develop分支