前端编码规范(web和小程序)-2019

不管有多少人共同参与同一项目,一定要确保每一行代码都像是同一个人编写的。

通用规范

命名

常见命名格式:

  • camelCase(驼峰命名、小驼峰)
  • PascalCase(帕斯卡命名、大驼峰)
  • snake_case(蛇形命名、下划线命名)
  • kebab-case(脊柱命名、中划线命名)
  • StUdLyCaPs(匈牙利命名)
  • lowercase(纯小写命名)
  • UPPERCASE(纯大写命名)

命名规范

  1. 文件夹的命名: 纯小写(如果不能, 就采用小驼峰)
  2. 普通文件: 小驼峰
  3. 组件名、组件文件名: 大驼峰
  4. javascript里变量、方法名和view/page文件名: 小驼峰
  5. javascript里类、构造函数: 大驼峰
  6. javascript里的全局常量: 纯大写
  7. css中的class、id: 中划线命名
  8. 图片资源: 下划线命名(强制), 同时尽量带上倍数(非强制), (例如: pop_icon_show@2x.png)
  9. 其它多媒体资源(音视频资源或其他资源): 下划线命名

缩进

所有类型文件统一采用2个space作为缩进

HTML

标签使用必须符合标签嵌套规则

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!-- good -->
<div>
<p>hello wrold</p>
</div>

<!-- avoid -->
<p>
<div>hello wrold</div>
</p>

<!-- avoid -->
<p>
<h1>hello wrold</h1>
<h2>hello wrold</h2>
<h3>hello wrold</h3>
<h4>hello wrold</h4>
</p>

元素属性使用双引号语法

1
2
3
4
5
<!-- good -->
<p class="label-name">hello wrold</p>

<!-- avoid -->
<p class='label-name'>hello wrold</p>

注释写法

1
2
<!-- 代码注释 -->
<h1>hello wrold</h1>

类型属性

不需要为 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
2
3
4
5
6
7
8
9
10
11
const job = 'FrontEnd'

// bad
const item = {
job: job
}

// good
const item = {
job
}
  • 对象属性值的简写方式要和声明式的方式分组
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const job = 'FrontEnd'
const department = 'JDC'

// good
const item = {
job,
department,
sex: 'male',
age: 25
}

// bad
const item = {
sex: 'male',
job,
age: 25,
department
}
  • 使用拓展运算符 ... 复制数组
1
2
3
4
5
6
7
8
9
10
11
12
13
// good
itemsCopy = [...items]

// bad
const items = []
const itemsCopy = []
const len = items.length
let i

// bad
for (i = 0; i < len; i++) {
itemsCopy[i] = items[i]
}
  • 解构赋值
1
2
3
4
5
6
7
8
9
10
11
// good
function (user) {
const { firstName, lastName } = user
return `${firstName} ${lastName}`
}
// avoid
function (user) {
const firstName = user.firstName
const lastName = user.lastName
return `${firstName} ${lastName}`
}
  • 请使用函数声明,而不是函数表达式
1
2
3
4
5
6
7
8
9
// good
function foo () {
// do something
}

// avoid
const foo = function () {
// do something
}
  • 不要使用 arguments ,可以选择使用 ...
1
2
3
4
5
6
7
8
9
// good
function test (...args) {
return args.join('')
}
// avoid
function test () {
const args = Array.prototype.slice.call(arguments)
return args.join('')
}
  • 禁止使用 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 : 0
  • finally 代码块中不要再改变程序执行流程

    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
2
3
4
5
6
7
/* good */
.dialog-wrap {
display: block;
}

/* avoid */
.dialog-wrap { display: block; }

选择器

  • 不使用 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";
    }

推荐属性书写顺序

  1. 布局定位属性:display / position / float / clear / visibility / overflow
  2. 自身属性:width / height / margin / padding / border / background
  3. 文本属性:color / font / text-decoration / text-align / vertical-align / white- space / break-word
  4. 其他属性(CSS3):content / cursor / border-radius / box-shadow / text-shadow / background:linear-gradient …

CSS3浏览器私有前缀写法

浏览器私有前缀在前,标准前缀在后

1
2
3
4
5
6
7
.dialog-wrap {
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
-o-border-radius: 10px;
-ms-border-radius: 10px;
border-radius: 10px;
}

注释规范

  • 注释以字符 /* 开始,以字符 */ 结束
  • 注释内容第一个字符和最后一个字符都是一个空格字符,单独占一行,行与行之间相隔一行

SASS & LESS

遵循css的基础上,此外还有如下规范

  • 选择器嵌套避免层级过深、过于复杂, 从html的结构上开始精简, 合理规划html结构

  • 变量 - 可复用属性尽量抽离为页面变量,易于统一维护

小程序Taro-最佳实践

Taro 规范

最佳实践

性能优化实践

  • 遵循上述js规范
  • JSX中采用单引号包裹属性, 如果出现双引号, 可能会导致编译错误
  • 组件传递函数属性名以 on 开头
  • 组件中不要在 stateprops 上用同名的字段
  • 子类的构造器中一定要调用 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
2
3
4
功能:本次主要是修改了什么功能或者bug
模块:本次发版影响的模块
代码问题:code review 过程中发现的代码问题,比如代码性能,写法,代码风格等等
业务问题:比如发现了某某影响到其他模块的逻辑问题,如果没有发现就写。无

版本管理

git-flow 备忘清单
采用 git-flow 方式进行代码的版本管理
master: 主分支, 线上生产环境跑的分支
develop: 开发分支, 功能开发完毕后集成到此分支
feature: 功能分支, 每个小功能单独开一个功能分支, 尽可能避免无依赖关系的功能在同一个分支上
release: 发布分支, 功能开发完毕集成到develop分支之后, 从develop拉取的预发布分支, 在发布分支上进行测试, finish之后会同时合并到master分支和develop分支
hotfix: 修复分支, 线上出现bug之后,拉取的修复分支,finish之后和release一样会同时合并到master分支和develop分支

编码规范
凹凸实验室-前端代码规范
前端小团队建设(实用前端开发规范,推荐收藏)

坚持原创技术分享,您的支持将鼓励我继续创作!