一、统一要求

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公共组件可以使用大驼峰形式或者小写单词命名文件夹,内部诸多文件可以采用小写单词命名。也可以直接使用大驼峰命名文件。例如:

前端代码规范_选择器

前端代码规范_选择器_02

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中,建议事件和属性分开一堆放,不要穿插,不方便阅读。

前端代码规范_选择器_03


四、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()