很多大厂都在用的前端代码规范(来自凹凸实验室)

1,113 阅读5分钟

code View

高质量代码的三大要素:可读性、可维护性和可变更性

  • 可读性

编码风格一致、代码清晰表达意图、代码清晰表达意图、评估取舍、避免简单的功能写出复杂的代码

  • 可维护性

谨慎使用全局变量,模块化开发

保持方法的原子性,提高代码内聚,能使某处修改的影响降到最低

不能把代码写死。例如配置文件、数据库连接字符串、资源文件、日志等

  • 可写性/可变更性

设计模式、RDD、TDD(测试驱动开发)、DDD(领域驱动开发) 等。使用设计模式可以显著提高代码的可写性

命名规范

目录命名

  • 项目文件夹:projectname
  • 样式文件夹:css
  • 脚本文件夹:js
  • 样式类图片文件夹:img

图片命名

图片业务(可选) +(mod_)图片功能类别(必选)+ 图片模块名称(可选) + 图片精度(可选)

  • 图片业务:
    • pp_:拍拍
    • wx_:微信
    • sq_:手Q
    • jd_:京东商城
  • 图片功能类别:
    • mod_:是否公共,可选
    • icon:模块类固化的图标
    • logo:LOGO类
    • spr:单页面各种元素合并集合
    • btn:按钮
    • bg:可平铺或者大背景
  • 图片模块名称:
    • goodslist:商品列表
    • goodsinfo:商品信息
    • userava tar:用户头像
  • 图片精度:
    • 普清:@1x
    • Retina:@2x | @3x

HTML/CSS文件命名

确保文件命名总是以字母开头而不是数字,且字母一律小写,以下划线连接且不带其他标点符号,如:

<!-- HTML -->
jdc.html
jdc_list.html
jdc_detail.html

<!-- SASS -->
jdc.scss
jdc_list.scss
jdc_detail.scss

ClassName命名

尽量精短、明确,必须以字母开头命名,且全部字母为小写,单词之间统一使用下划线 “_” 连接

基于姓氏命名法(继承 + 外来)

JS 规范

语言规范

// bad
const a = new Object{}

// good
const a = {}
// bad
const item = {
  value: 1,

  addValue: function (val) {
    return item.value + val
  }
}

// good
const item = {
  value: 1,

  addValue (val) {
    return item.value + val
  }
}
const job = 'FrontEnd'

// bad
const item = {
  job: job
}

// good
const item = {
  job
}
  • 只对非法标识符的属性使用引号,eslint: quote-props
// bad
const bad = {
  'foo': 3,
  'bar': 4,
  'data-blah': 5
}

// good
const good = {
  foo: 3,
  bar: 4,
  'data-blah': 5
}
// bad
function getFullName (user) {
  const firstName = user.firstName
  const lastName = user.lastName

  return `${firstName} ${lastName}`
}

// good
function getFullName (user) {
  const { firstName, lastName } = user

  return `${firstName} ${lastName}`
}

// better
function getFullName ({ firstName, lastName }) {
  return `${firstName} ${lastName}`
}
  • 字符串统一使用单引号的形式 '',eslint: quotes
// bad
const department = "JDC"

// good
const department = 'JDC'
const test = 'test'

// bad
const str = ['a', 'b', test].join()

// bad
const str = 'a' + 'b' + test

// good
const str = `ab${test}`
const f = function(){}
const g = function (){}
const h = function() {}

// good
const x = function b () {}
const y = function a () {}
  • 调用可变参数函数时建议使用展开运算符 ...., eslint: prefer-spread
// bad
const x = [1, 2, 3, 4, 5]
console.log.apply(console, x)

// good
const x = [1, 2, 3, 4, 5]
console.log(...x)

// bad
new (Function.prototype.bind.apply(Date, [null, 2016, 8, 5]))

// good
new Date(...[2016, 8, 5])
  • 如果函数体只包含一条没有副作用的返回表达式的语句,可以省略花括号并使用隐式的 return, 否则保留花括号并使用 return 语句,eslint: arrow-parens, arrow-body-style
// bad
[1, 2, 3].map(number => {
  const nextNumber = number + 1
  `A string containing the ${nextNumber}.`
})

// good
[1, 2, 3].map(number => `A string containing the ${number}.`)

// good
[1, 2, 3].map((number) => {
  const nextNumber = number + 1
  return `A string containing the ${nextNumber}.`
})

// good
[1, 2, 3].map((number, index) => ({
  index: number
}))

// No implicit return with side effects
function foo(callback) {
  const val = callback()
  if (val === true) {
    // Do something if callback returns true
  }
}

let bool = false

// bad
foo(() => bool = true)

// good
foo(() => {
  bool = true
})
// bad
class Foo {
  bar () { return 1 }
  bar () { return 2 }
}

// good
class Foo {
  bar () { return 1 }
}

// good
class Foo {
  bar () { return 2 }
}
  • 同个文件每个模块只允许 import 一次,有多个 import 请书写在一起,eslint: no-duplicate-imports
// bad
import foo from 'foo'
// … some other imports … //
import { named1, named2 } from 'foo'

// good
import foo, { named1, named2 } from 'foo'

// good
import foo, {
  named1,
  named2
} from 'foo'
  • 不要使用 iterators,建议使用 JS 更高优先级的函数代替 for-in 或 for-of 循环,除非迫不得已,eslint: no-iterator no-restricted-syntax
const numbers = [1, 2, 3, 4, 5]

// bad
let sum = 0
for (let num of numbers) {
  sum += num
}

// good
let sum = 0
numbers.forEach(num => sum += num)

// better
const sum = numbers.reduce((total, num) => total + num, 0)

代码规范

  • 在单行代码块中使用空格
function foo () { return true }
if (foo) { bar = 0 }
  • 当命名变量时,主流分为驼峰式命名(constiableName)和下划线命名(constiable_name)两大阵营。

React&JSX 书写规范

  • 每个文件只包含一个 React 类组件,但是多个函数式组件可以放到一个文件中,eslint: react/no-multi-comp
  • React 组件使用 PascalCase,组件实例使用 CamelCase,eslint: react/jsx-pascal-case
// bad
import reservationCard from './ReservationCard'

// good
import ReservationCard from './ReservationCard'

// bad
const ReservationItem = <ReservationCard />

// good
const reservationItem = <ReservationCard />
// bad
<Foo superLongParam='bar'
     anotherSuperLongParam='baz' />

// good
<Foo
  superLongParam='bar'
  anotherSuperLongParam='baz'
/>

// if props fit in one line then keep it on the same line
<Foo bar='bar' />

// children get indented normally
<Foo
  superLongParam='bar'
  anotherSuperLongParam='baz'
>
  <Quux />
</Foo>

// bad
{showButton &&
  <Button />
}

// bad
{
  showButton &&
    <Button />
}

// good
{showButton && (
  <Button />
)}

// good
{showButton && <Button />}
// bad
<Foo/>

// very bad
<Foo                 />

// bad
<Foo
 />

// good
<Foo />
// bad
<Foo
  hidden={true}
/>

// good
<Foo
  hidden
/>

// good
<Foo hidden />
// bad
render () {
  return <MyComponent className='long body' foo='bar'>
           <MyChild />
         </MyComponent>
}

// good
render () {
  return (
    <MyComponent className='long body' foo='bar'>
      <MyChild />
    </MyComponent>
  )
}

// good, when single line
render () {
  const body = <div>hello</div>
  return <MyComponent>{body}</MyComponent>
// bad
<Foo className='stuff'></Foo>

// good
<Foo className='stuff' />
// bad
render () {
  (<div />)
}

// good
render () {
  return (<div />)
}

HTML 规范

代码规范

  • 所有具有开始标签和结束标签的元素都要写上起止标签,某些允许省略开始标签或和束标签的元素亦都要写上。空元素标签都不加 “/” 字符
<div>
  <h1>我是h1标题</h1>
  <p>我是一段文字,我有始有终,浏览器能正确解析</p>
</div>

<br>
  • HTML标签名、类名、标签属性和大部分属性值统一用小写
<div class="demo"></div>
  • 统一使用四个空格进行代码缩进,使得各编辑器表现一致(各编辑器有相关配置)

注释规范

  • 单行注释:一般用于简单的描述,如某些状态描述、属性描述等。注释内容前后各一个空格字符,注释位于要注释代码的上面,单独占一行
<!-- Comment Text -->
<div>...</div>
  • 模块注释:一般用于描述模块的名称以及模块开始与结束的位置。注释内容前后各一个空格字符, 表示模块开始, 表示模块结束,模块与模块之间相隔一行
<!-- S Comment Text A -->	
<div class="mod_a">
    ...
</div>
<!-- E Comment Text A -->
	
<!-- S Comment Text B -->	
<div class="mod_b">
    ...
</div>
<!-- E Comment Text B -->
  • 嵌套模块:当模块注释内再出现模块注释的时候,为了突出主要模块,嵌套模块注释写在模块结尾标签底部,单独一行。
<!-- S Comment Text A -->
<div class="mod_a">
		
    <div class="mod_b">
        ...
    </div>
    <!-- /mod_b -->
    	
    <div class="mod_c">
    	...
    </div>
    <!-- /mod_c -->
		
</div>
<!-- E Comment Text A -->

摘抄自:guide.aotu.io/docs/index.…