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 规范
语言规范
- 请使用字面量值创建对象,eslint: no-new-object
// bad
const a = new Object{}
// good
const a = {}
- 请使用对象方法的简写方式,eslint: object-shorthand
// bad
const item = {
value: 1,
addValue: function (val) {
return item.value + val
}
}
// good
const item = {
value: 1,
addValue (val) {
return item.value + val
}
}
- 请使用对象属性值的简写方式,eslint: object-shorthand
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
}
- 当需要使用对象的多个属性时,请使用解构赋值,eslint: prefer-destructuring
// 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'
- 程序化生成字符串时,请使用模板字符串,eslint: prefer-template template-curly-spacing
const test = 'test'
// bad
const str = ['a', 'b', test].join()
// bad
const str = 'a' + 'b' + test
// good
const str = `ab${test}`
- 在函数签名中使用空格,eslint: space-before-function-paren space-before-blocks
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
})
- 避免类成员重复,eslint: no-dupe-class-members
// 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 />
- 遵循以下JSX语法的对齐风格,eslint: react/jsx-closing-bracket-location
// 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 />}
- 自闭合的标签前要加一个空格,eslint: no-multi-spaces, react/jsx-tag-spacing
// bad
<Foo/>
// very bad
<Foo />
// bad
<Foo
/>
// good
<Foo />
- 当属性值为true时可以省略, eslint: react/jsx-boolean-value
// bad
<Foo
hidden={true}
/>
// good
<Foo
hidden
/>
// good
<Foo hidden />
- 当 JSX 标签超过一行时使用圆括号包裹, eslint: react/wrap-multilines
// 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>
- 没有子元素的标签请自闭合,eslint: react/self-closing-comp
// bad
<Foo className='stuff'></Foo>
// good
<Foo className='stuff' />
- 确保在 render 方法中存在返回值,eslint: require-render-return
// 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 -->