# 目录:
- 命名规范
- 文件结构命名
- 项目命名
- 目录命名
- 文件命名
- CSS类命名
- JavaScript命名
- 变量命名
- 函数命名
- 文件结构命名
- 代码风格
- 文件
- 缩进
- 空格
- 控制结构
- 分号
- 数组、对象
- 编码原则
- HTML
- JavaScript
- ES6
- Vue
- 注释规范
- JavaScript
- CSS
- HTML
# 一、命名规范
# 1、文件结构命名
# a. 项目命名
# 全部采用小写方式, 以横线分隔。(例:my-project-name)
# b. 目录命名
# 参照项目命名规则:有复数结构时,要采用复数命名法。(例:scripts, styles, images,components,libs)
# c. 文件命名
# 使用驼峰命名法。(例:searchForm.html、searchForm.css、searchForm.js、searchForm.vue)
# 2、CSS类命名
# a. 类名使用小写字母,以中划线分隔
# b. id采用驼峰式命名
# c. less、sass、【stylus】中的变量、函数、混合、placeholder采用驼峰式命名
/* class */
.element-content {
...
}
/* id */
#myDialog {
...
}
/* 变量 */
$colorBlack: #000;
/* 函数 */
@function pxToRem($px) {
...
}
/* 混合 */
@mixin centerBlock {
...
}
/* placeholder */
%myDialog {
...
}
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
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
# 3、JavaScript命名
# a. 变量命名
- 标准变量采用驼峰式命名(除了对象的属性外,主要是考虑到res返回的数据)
# 【强制】:普通变量的命名,应以变量的类型名开头
bVar //Boolean 布尔类型
nVar //Number 整型
strVar //String 字符串
aVar //Array 数组
objVar //Object 对象
数组、对象内的属性名key和类成员属性不必加类型前缀,如示例中的name、address
let objList = {
name: '张三',
address: '北京'
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
- 常量全大写,用下划线连接
- 对上下文this的引用只能使用'_this'
# b. 函数命名
- 使用驼峰命名法
- 语义化,且单个函数的代码量不易过长,尽量切分到最小单元函数
# 例:ajax请求-ajaxGetNodeList;事件操作-handleChangeName;
# 二、编码风格
# 1、文件
# 所有 .vue / .less(css) / .js / .html文件必须以一个空行结束(空行可以用来改善可读性和区分相关的代码块)
# 2、缩进
# 每个缩进的单位约定是4个空格的缩进,并且不可使用制表符作为缩进,需每个参与项目的开发人员在编辑器中进行强制设定将TAB转化为4个空格,以防在编写代码时遗忘而造成格式上的不规范
# 3、空格
# 使用空格:① 二元运算符前后,② 三元运算符'?:'前后,③ 代码块'{'前 ,④ if, else, for 等关键字后,⑤ 对象属性值前
# 不需要使用空格:① 对象的属性名后,② 一元运算符前后,③ 数组的'['后和']'前、对象的'{'后和'}'前、运算符'('后和')'前,④ 无论是函数声明还是函数表达式,'('前不要空格,⑤ 函数调用括号前
// 使用空格
z = x ? 1 : 2; // 三元运算符?: 前后,使用空格
for (i = 0; i < 6; i++) { // 二元运算符前后、代码块{前,使用空格
x++;
}
//不使用空格
let a = {
b: 1 // 对象属性名后,不使用空格;对象属性值前,使用空格
};
++x; // 一元运算符前后,不使用空格
let a = [1, 2]; // 数组[]前后,不使用空格
let a = (1 + 2) * 3; // 运算符()前后,不使用空格
let doSomething = function(a, b, c) { // 函数声明、或是表达式,括号( 前不使用空格
// do something
};
doSomething(); // 函数调用括号前,不使用空格
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 4、控制结构
# if/while等结构体,即时只有一行,也必须加上左右花括号,不允许写成一行。
if (a > b) {
...
}
1
2
3
2
3
# 5、分号
# css中:每个属性声明末尾都要加分号
# js中:语句结束后,必须要分号(变量声明、表达式、return、break、continue、do-while等等
# 6、数组、对象
- 数组、对象最后一条不要有逗号
- 数组对象属性名不需要加引号
- 对象以缩进的形式书写,不要写在一行
// not good
let a = {
'b': 1
};
let a = {b: 1};
let a = {
b: 1,
c: 2,
};
// good
let a = {
b: 1,
c: 2
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 三、编码原则
# a. HTML
# 1. 语法
· 缩进使用 tab(4 个空格);
· 嵌套的节点应该缩进;
· 在属性上,使用双引号,不要使用单引号;
· 属性名全小写,用中划线(-)做分隔符;
· 要在自动闭合标签结尾处使用斜线;
1
2
3
4
5
2
3
4
5
# 2. 标准模式
# 在开头规定 doctype,来启动标准模式,doctype 要大写。
# 3. 规定字符编码
# 通过声明一个明确的字符编码,让浏览器快速的确定适合网页内容的渲染方式,通常指定为'UTF-8'。
例:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Page title</title>
</head>
<body>
<img src="images/company_logo.png" alt="Company" />
<!-- 属性名全小写,用中划线(-)做分隔符 -->
<h1 class="hello-world">Hello, world!</h1>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# 4. IE 兼容模式
用 meta 标签指定页面应该使用什么版本的 IE 来渲染。
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
</head>
...
</html>
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 5. 减少标签数量
###### 在编写 HTML 代码时,需要尽量避免多余的父节点;
<!-- good -->
<img class="avatar" src="..." />
1
2
3
2
3
# 6. 自定义属性
<ol data-ui-type="Select"></ol>
1
# b. JavaScript
- 在执行for循环之前确定最大循环数,不要每循环一次都计算最大值。
let nLength = objTableList.length;
for (let i = 0; i < nLength ; i++) {
x++;
}
1
2
3
4
2
3
4
- 最外层统一使用单引号
// not good
var x = "test";
// good
var y = 'foo',
z = '<div id="test"></div>';
1
2
3
4
5
6
2
3
4
5
6
- 永远不要直接使用undefined进行变量判断,使用typeof和字符串'undefined'对变量进行判断
// not good
if (person === undefined) {
...
}
// good
if (typeof person === 'undefined') {
...
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
- 用'===', '!=='代替'==', '!='【建议】
- for-in里一定要有hasOwnProperty的判断
- 不要超过 100,但如果编辑器开启 word wrap 可以不考虑单行长度
- 不允许存在多层嵌套的条件判断和循环(最多三层)
条件判断能使用三目运算符和逻辑运算符解决的,就不要使用条件判断,但是谨记不要写太长的三目运算符。
例:
// bad
if (x === 10) {
return 'valid';
} else {
return 'invalid';
}
// good
return x === 10 ? 'valid' : 'invalid';
// bad
if (!x) {
if (!y) {
x = 1;
} else {
x = y;
}
}
// good
x = x || y || 1;
简单解释一下逻辑运算符,逻辑运算符主要有两种,一个是 || 逻辑或,一个是 && 逻辑与。
· 逻辑或 ||:当前一个为真时,返回前一个值,前一个为假时返回后一个值。
var x = 1;
console.log(x || 2); // 1
var y = 0;
console.log(y || 2); // 2
· 逻辑与 &&:当前一个为真时,返回后一个值,前一个为假时返回前一个值。
var x = 1;
console.log(x && 2); // 2
var y = 0;
console.log(y && 2); // 0
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
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
# c. ES6
- 使用 let,const 代替 var
- 使用对象属性值的简写
const params = {
name:"张三"
};
// bad
const obj = {
params: params,
};
// good
const obj = {
params,
};
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
- 使用拓展运算符 ... 复制数组
// bad
const len = items.length;
const itemsCopy = [];
let i;
for (i = 0; i < len; i++) {
itemsCopy[i] = items[i];
}
// good
const itemsCopy = [...items];
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
- 使用 Array#from 把一个类数组对象转换成数组
const foo = document.querySelectorAll('.foo');
const nodes = Array.from(foo);
1
2
2
- 使用解构存取和使用多属性对象
// bad
function getFullName(user) {
const firstName = user.firstName;
const lastName = user.lastName;
return `${firstName} ${lastName}`;
}
// good
function getFullName(obj) {
const { firstName, lastName } = obj;
return `${firstName} ${lastName}`;
}
// best
function getFullName({ firstName, lastName }) {
return `${firstName} ${lastName}`;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- 对数组使用解构赋值
const arr = [1, 2, 3, 4];
// bad
const first = arr[0];
const second = arr[1];
// good
const [first, second] = arr;
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
- 程序化生成字符串时,使用模板字符串代替字符串连接
// bad
function sayHi(name) {
return 'How are you, ' + name + '?';
}
// bad
function sayHi(name) {
return ['How are you, ', name, '?'].join();
}
// good
function sayHi(name) {
return `How are you, ${name}?`;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- 当你必须使用函数表达式(或传递一个匿名函数)时,使用箭头函数符号
// bad
[1, 2, 3].map(function (x) {
const y = x + 1;
return x * y;
});
// good
[1, 2, 3].map((x) => {
const y = x + 1;
return x * y;
});
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
- 如果一个函数适合用一行写出并且只有一个参数,那就把花括号、圆括号和 return 都省略掉。如果不是,那就不要省略
// good
[1, 2, 3].map(x => x * x);
// good
[1, 2, 3].reduce((total, n) => {
return total + n;
}, 0);
1
2
3
4
5
6
7
2
3
4
5
6
7
- 使用 class。避免直接操作 prototype
// bad
function Queue(contents = []) {
this._queue = [...contents];
}
Queue.prototype.pop = function() {
const value = this._queue[0];
this._queue.splice(0, 1);
return value;
}
// good
class Queue {
constructor(contents = []) {
this._queue = [...contents];
}
pop() {
const value = this._queue[0];
this._queue.splice(0, 1);
return value;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
- 方法可以返回 this 来帮助链式调用
// bad
Jedi.prototype.jump = function() {
this.jumping = true;
return true;
};
Jedi.prototype.setHeight = function(height) {
this.height = height;
};
const luke = new Jedi();
luke.jump(); // => true
luke.setHeight(20); // => undefined
// good
class Jedi {
jump() {
this.jumping = true;
return this;
}
setHeight(height) {
this.height = height;
return this;
}
}
const luke = new Jedi();
luke.jump()
.setHeight(20);
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
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
- 使用高阶函数例如 map() 和 reduce() 替代 for-of
const numbers = [1, 2, 3, 4, 5];
// bad
let sum = 0;
for (let num of numbers) {
sum += num;
}
sum === 15;
// good
let sum = 0;
numbers.forEach((num) => sum += num);
sum === 15;
// best (use the functional force)
const sum = numbers.reduce((total, num) => total + num, 0);
sum === 15;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# d. Vue
- 使用 name 属性。可以借助于 vue devtools 可以让你更方便的测试
- 组织结构:按照name、extends、component、props、data、computed、watche 和 methods 、生命周期函数 等顺序显示内容对象【强制】
- 表达式尽量简单,若较复杂的表达式,使用“计算属性computed”保存
# 四、注释规范
# a. JavaScript
- 单行注释:单独另起一行用双反斜杠”//“注释,斜线后边要加一个空格
- 多行注释:多行注视以”/”或“/**”符号开头,以”/ “符号作为注释结束符。需要生成文档的注释必须是以“/**”开头,以“*/”结尾。
- 方法注释
复杂的函数,所有类,都必须进行函数注释,函数注释使用业界统一的规范,方便后续使用 jsdoc 生成文档。
例:
/**
* 获取任务的名称
* @param id {Number} 传入需要获取名称的人物id
* @return {String} 返回的姓名
* @author shi 2019/09/01 可以不写
* @version 1.1.0 可以不写
* @example 示例代码,可以不写
*/
function getTaskName(id) {
let name = "test";
return name;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
- 有param和return的函数,必须通过标记指明其参数和返回值
(建议) 描述性内容尽量简明扼要,尽可能使用短语而非句子
# b. CSS
- 注释统一用'/* */'(scss中也不要用'//'); 缩进与下一行代码保持一致; 可位于一个代码行的末尾,与代码间隔一个空格
/* Modal header */
.modal-header {
...
}
/*
* Modal header
*/
.modal-header {
...
}
.modal-header {
/* 50px */
width: 50px;
color: red; /* color red */
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# c. HTML
<!-- 调用组件时需要加单行注释 -->
<component-a></component-a>
<!-- start html内容过多时,需要加入开始/结束注释 -->
<div>
<ul>
<li></li>
……
</ul>
</div>
<!-- end html内容过多时,需要加入开始/结束注释 -->
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11