一、统一要求
1、基本规范
- 所有方法名等涉及到名称的,统一使用驼峰命名,命名要具有业务意义,语义化,简洁明了
- 代码中不得出现警告
- 代码中不得出现数字(插件除外)
2、基本原则
- 代码力求简洁,不要写大量重复的逻辑代码(公共方法需封装,公共样式提取到公共样式中)
- 代码要有可读性,函数和元素命名要具有业务意义,关键业务要有详细的注释
- 代码要有扩展性,要尽可能适应未来的业务变化,不得生搬硬套现有业务逻辑
- 代码要有通用性,一个方法只专注于该方法需要做的事情(对外暴露相应的参数),一个模块只专注于该模块范围内的事情(对外暴露相应的接口)
二、命名规范 + css规范
1、项目文件命名( js、css、scss、html、图片 )
全部采用小写单词组成, 多个单词以下划线分隔。或者统一使用 “ 小驼峰 ” 写法。例如:
下划线分隔:my_project_name
小驼峰:myProjectName
2、目录结构命名
规则和 “ 项目文件命名 ” 一致,但是有复数结构时,要采用复数命名法。例如:
scripts, styles, images, data_models, components, views
关于命名:除了组件可以使用大驼峰外,其他一律不准使用大驼峰
3、vue业务组件命名
vue业务组件一般采用大驼峰形式命名,vue文件里必须声明name。例如:CustomName
4、vue公共组件命名
vue公共组件可以使用大驼峰形式或者小写单词命名文件夹,内部诸多文件可以采用小写单词命名。也可以直接使用大驼峰命名文件。例如:
5、class类名
类名最好小写,多个单词以横线 ‘-’分割。例如: class="test-demo"
常用的类名后缀有:
外套 wrap ——————用于最外层
头部 header —————-用于头部
主要内容 main ————用于主体内容(中部)
左侧 main-left ————-左侧布局
右侧 main-right ———–右侧布局
导航条 nav —————–网页菜单
导航条内容 content —————用于网页中部主体
底部 footer —————–用于底部
6、选择器
- 尽量少用通用选择器 *
- 不使用 ID 选择器
- 不使用无具体语义定义的标签选择器
7、简洁性
使用属性缩写。不必要的值不用写。 如0 取代 0px, padding 取代 padding-top/right/bottom/left同时定义等。
8、动画
除了变形和改变透明度用animation,其他尽量使用transition。
9、行内样式
除了比较特殊的样式判断(如:根据某个字段判断显示哪个颜色),不要写行内样式
三、HTML代码规范
1、嵌套的节点按照结构,层层缩进,同时要注意 HTML的语义化;
2、在属性上,使用双引号,不要使用单引号;
3、自定义属性名全小写,用中划线做分隔符;
4、不要在自动闭合标签结尾处使用斜线( HTML5规范 指出他们是可选的);
5、不要忽略可选的关闭标签,例:</li> 和 </body>。
6、当单个元素的属性过多时,需要适当换行,方便查看,在Vue中,建议事件和属性分开一堆放,不要穿插,不方便阅读。
四、javascript 代码规范
1、变量命名
- 标准变量采用驼峰标识
- 使用的ID的地方一定全大写, 如userID
- 使用的URL的地方一定全大写, 比如说 reportURL
- 涉及Android的,一律大写第一个字母
- 涉及iOS的,一律小写第一个,大写后两个字母
- 固定使用的常量采用大写字母,下划线连接的方式,如CITY_CONFIG
- 构造函数,大写第一个字母
2、使用const和let代替var
const 和 let 都是块级作用域,var 是函数级作用域。对于只读的常量(指向的内存地址不变)使用const,变量声明使用let(复合类型的数据,如果不重新赋值,只更改内容,使用const声明)
3、变量声明
变量必须 即用即声明,不得在函数或其它形式的代码块起始位置统一声明所有变量。
4、对象或数组创建
使用字面量值创建对象, 如{}代替new Object{}, []代替new Array()
5、避免使用保留字作为对象的键值
如default、continue等等,在 IE8 下不会运行
6. 对象多个属性赋值优先使用Object.assign
// bad
const obj = {a: 1}
obj.a = 2
obj.b = 3
obj.c = 4
// good
const obj = {a: 1}
Object.assign(obj, {
a: 2,
b: 3,
c: 4
})
7. 请使用对象属性值的简写方式
const job = 'FrontEnd'
// bad
const item = {
job: job
}
// good
const item = {
job
}
8、将简写的对象属性分组后统一放到对象声明的开头
const job = 'tester'
const department = 'abc'
// bad
const item = {
sex: 1,
job,
age: 30,
department
}
// good
const item = {
job,
department,
sex: 1,
age: 30
}
9、不要直接使用 Object.prototype 的方法, 例如 hasOwnProperty, propertyIsEnumerable 和 isPrototypeOf
// bad
console.log(object.hasOwnProperty(key))
// good
console.log(Object.prototype.hasOwnProperty.call(object, key))
10、 灵活使用展开运算符...
// bad
const original = { a: 1, b: 2 }
const copy = Object.assign({}, original, { c: 3 })
delete copy.a
// good
const original = { a: 1, b: 2 }
const copy = { ...original, c: 3 } // copy => { a: 1, b: 2, c: 3 }
const { a, ...noA } = copy // noA => { b: 2, c: 3 }
11、数组方法return
使用数组的 map/reduce/filter/find 等方法时,请使用 return 声明,如果是单一声明语句的情况,可省略 return
12、 解构赋值
需要使用对象的多个属性或数组的多个值时,请使用解构赋值
const obj = {a: 1, b: 2, c: 3}
const arr = [1, 2, 3, 4]
// bad
const a = obj.a
const b = obj.b
const first = arr[0]
const second = arr[1]
// good
const {a, b} = obj
const [first, second] = arr
// 对象解构+赋值
let people = { name: null, age: null };
let result = { name: '张三', age: 16 };
{ name: people.name, age: people.age } = result;
console.log(people)
// 基础数据类型结构
const { length: a } = '1234';
console.log(a) // 4
// 对数组结构快速拿到最后一项
const arr = [1, 2, 3];
const { 0: first, length, [length - 1]: last } = arr;
first; // 1
last; // 3
length; // 3
13、 函数回传多个值或者方法多个可选入参时优先使用对象的结构
// bad
function doSomething () {
return [top, right, bottom, left]
}
// 如果是数组解构,那么在调用时就需要考虑数据的顺序
const [top, xx, xxx, left] = doSomething()
// good
function doSomething () {
return { top, right, bottom, left }
}
// 此时不需要考虑数据的顺序
const { top, left } = doSomething()
// bad
function doSomething (a, b, c, d) {
}
// 有默认参数也必须按顺序传入
doSomething(true, 1, 2, 3)
// good
function doSomething ({a = true, b, c = 1, d}) {
}
// 此时使用默认的参数就可以不传
doSomething({b: 1, d: 3})
14、模板字符串
变量与常量拼接尽量使用模板字符串,如`my name is ${name}`
15、谨慎给参数重新赋值
// bad
function f1 (a) {
a = 1
}
function f2 (a) {
if (!a) { a = 1 }
}
// good
function f3 (a) {
const b = a || 1
}
function f4 (a = 1) {
}
16、比较运算符
使用 === 和 !== 而非 == 和 !=
说明:使用 === 可以避免等于判断中隐式的类型转换
17、debugger
调试完成后请清理debugger和console.log
注意:在git提交时要把debugger和console.log全部清理掉,以防出现内存泄漏的问题
18、 布尔转换
避免不必要的布尔转换,
在if条件等情况中会自动转为布尔值,无需!!,而赋值仍需!!来强制转为布尔值
// bad
const status = 1
if (!!status) {
}
const isDelete = status > 0 ? true : false
// good
const status = 1
if (status) {
}
const isDelete = !!status // or const isDelete = Boolean(status)
19、三元表达式
二选一条件下 三元表达式与if…else是可以互换的
根据条件二选一给变量赋值的情况下,可使用三元表达式,其他复杂的逻辑处理不推荐
如果有更好的实现,尽量不要使用三元表达式
// bad
let score = val ? val : 0
// good
let score = val || 0
20、 循环
尽量避免嵌套循环
说明:额外增加很多次循环,影响效率,且堆叠代码影响可读性
尽量少用for-in和for-of
数组的遍历,虽然fori的性能优于其他,但很多场景下使用map、find、filter、reduce、every、some等更合适,语义清晰且代码简洁
const students= [
{key: 'p1', name: '张三', score: 99},
{key: 'p2', name: '李四', score: 98},
]
const nodes = [
{key: 'p1', checked: true},
{key: 'p2', checked: false},
]
// bad
for (let i = 0; i < nodes.length; i ++) {
const node = nodes[i]
for (let j = 0; j < students.length; j ++) {
const student = students[j]
if (student.key === node.key) {
// TODO
break;
}
}
}
// good
const studentKeyMap = {}
students.forEach(student => {
studentKeyMap[student.key] = student
})
nodes.forEach(node => {
if (studentKeyMap[node.key]) {
// TODO
}
})
21、类型检测
基本数据类型判断使用 typeof
引用类型检测可使用 instanceof
null 或 undefined 的检测使用 == null
Object.prototype.toString.call() 最为通用
注意:
typeof null === 'object'
检测有效数字: !isNaN(value) && typeof value === 'number'
数组检测推荐用 Array.isArray()