提交可交付的代码
本文不是代码规范,但也可能会限制您的代码风格
如果你想要为这个清单做贡献或觉得有不合理的地方,请访问New Issue 。
任何时刻都要检查数据存在
// bad
const { firstName , age , addresses } = params
submit ({
firstName ,
age ,
addresses ,
... secondaryInfo ,
})
// good
const { firstName , age , addresses } = params
if ( ! firstName ) {
// 提示错误
return
}
if ( addresses . length === 0 ) {
// 提示错误
return
}
submit ({
firstName ,
age ,
... secondaryInfo ,
})
任何时刻都要检查数据类型
// bad
const { firstName , age , addresses } = params
submit ({
firstName ,
age ,
addresses ,
... secondaryInfo ,
})
// good
const { firstName , age , addresses } = params
if ( ! firstName || typeof firstName !== ' string ' ) {
// 提示错误
return
}
if ( ! Array . isArray ( addresses ) || addresses . length === 0 ) {
// 提示错误
return
}
submit ({
firstName ,
age ,
... secondaryInfo ,
})
// 注:以下为 lua 代码,没有检查 b 变量的类型是 2021.07.13 B站宕机事故的主要原因
// 具体可看 https://cloud.tencent.com/developer/article/2251012
local _gcd
_gcd = function ( a , b )
if b == 0 then
return a
end
return _gcd ( b , a % b )
end
任何时刻都要基于业务进行输入验证
// bad
const { phone } = params
if ( ! phone || typeof phone !== ' string ' ) {
// 提示错误
return
}
submit ({
phone
})
// good
const isValidPhone = ( phone ) => {
if ( ! phone || typeof phone !== ' string ' ) {
return false
}
return /^ (?:[ () .+- ] * \d + ) + (?:[ ]? ext [ ]?\d + )? $/ . test ( phone )
}
const { phone } = params
if ( isValidPhone ( phone )) {
// 提示错误
return
}
submit ({
phone
})
任何时刻都需要在输入框内添加 max 最大长度等限制
// bad
< el - input
type = " textarea "
v - model = " inputForm.contents "
/>
// good
< el - input
type = " textarea "
v - model = " inputForm.contents "
: rules = " [{required: true, message: '请输入工单内容', trigger: 'blur'}] "
: rows = " 12 "
: maxlength = " 4000 "
/>
编写函数时注意宽入严出,对接受的数据要宽容,对输出的数据要严格
const OBJECT_TYPE = ' [object Object] '
const isRealObject = ( val ) => getType ( val ) === OBJECT_TYPE
// bad
const getOwnKeysForObj = ( val ) => {
if ( ! val ) {
return
}
if ( ! isRealObject ( val )) {
return
}
return Object . keys ( val ). filter ( key => val . hasOwnProperty ( key ))
}
// good
const getOwnKeysForObj = ( val ) => {
if ( ! val ) {
return []
}
if ( ! isRealObject ( val )) {
return []
}
return Object . keys ( val ). filter ( key => val . hasOwnProperty ( key ))
}
优先处理异常情况,以方便真正业务处理
// bad
const getService = ( code ) => {
if ( isRealServiceByCode ( code )) {
// do something
if ( isXXX ()) {
// do something
return services
}
}
return []
}
// good
const getService = ( code ) => {
if ( ! isRealServiceByCode ( code )) {
return []
}
// do something
if ( ! isXXX ()) {
return []
}
// do something
return services
}
条件判断和循环最多三层(同上)
// bad
const getService = ( code ) => {
if ( isRealServiceByCode ( code )) {
// do something
if ( isXXX ()) {
// do something
return services
}
}
return []
}
// good
const getService = ( code ) => {
if ( ! isRealServiceByCode ( code )) {
return []
}
// do something
if ( ! isXXX ()) {
return []
}
// do something
return services
}
不断进行函数拆分,直到用一句话能够表明意义(一个函数只完成一个功能)
// bad
const initial = async () => {
// 获取数据信息
// ...
// 验证过滤并修改数据信息
// ...
// 设置渲染
// ...
// 其他操作
}
// good
initial = async () => {
// 在初始化时候获取数据
const data = await this . getDataWhenInitial ();
// 验证以及格式化当前数据
this . validateAndNormalizeData ( data )
// 比对然后同步当前数据
this . diffThenSyncData ( data )
}
不要设计面面俱到的函数,开发者只会编写两种代码,一种是有 bug 的,另外一种是将来有 bug 的
无论何时优先使用解构
// bad
if ( this . props . dialogVisible ) {
}
// good
const { dialogVisible } = this . props
if ( dialogVisible ) {
}
不要在一个语句中同时处理同步数据和异步数据
// bad
let time = 1
time = time + await getTime ()
// good
let time = 1
const oldTime = await getTime ()
time = time + oldTime
函数返回值要,清楚,明了,统一,千万不要出现在一个函数中存在异步和同步两种结果
// bad
const getInfo = ( key ) => {
const cache = sessionStorage . getItem ( key )
if ( cache ) {
return cache
}
return api ( ' xxx ' ). then ( res => {
sessionStorage . setItem ( key , res )
return res
})
}
// good
const getInfo = ( key ) => {
const cache = sessionStorage . getItem ( key )
if ( cache ) {
return Promise . resolve ( cache )
}
return api ( ' xxx ' ). then ( res => {
sessionStorage . setItem ( key , res )
return res
})
}
钩子函数中只写调用,而不写具体逻辑代码
// bad
async componentDidMount () {
// 获取数据信息
// ...
// 验证过滤并修改数据信息
// ...
// 设置渲染
// ...
// 其他操作
}
// good
componentDidMount () {
this . initial ()
// 其他操作,抽取后不回彼此干扰,上面的 return 不回影响其他操作
}
initial = async () => {
// 在初始化时候获取数据
const data = await this . getDataWhenInitial ();
// 验证以及格式化当前数据
this . validateAndNormalizeData ( data )
// 比对然后同步当前数据
this . diffThenSyncData ( data )
}
不要轻易的封装重复的业务代码,有可能是一种巧合而并非重复
注释要有侧重点,数据结构的注释是非常重要的,其次是不合理的业务逻辑然后才是正常函数
变量命名缩写必须能够的到团队认可,否则使用完整单词
// bad
bgImgSrc
// good
backgroundImgSrc
常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚
函数命名使用 动词 + 名词的形式,如 发送短信 sendSms,如果是在模板或者 jsx 中,使用 handle + 名词 + 动词,如 处理短信发送,handle 也有具柄的意义
通过代码上通过 for, by, from, when,then 等单词添加函数的意图,提供有用的额外信息
减少没有必要的数据类型默认转换与强制转换(分析为什么当前数据不是该数据类型,而并不是进行转换)
考虑在布尔运算的过程中,false 0 '' 是否和 null,undefined 意义相同
在进行判断的过程中,先判断范围大的,在进行小范围判断,如: 权限判断 -> 数据权限判断 -> 业务判断
if, else, for, while, do, switch, try, catch, finally 等语句的执行语句部分无论多少都要加括号 { }
添加定时器,以及事件等,记住清除,否则可能引发内存泄漏或者错误
处理异步时候,多考虑异常,同时 Promise 必须使用 resolve 或 reject 进入下一个状态,避免代码执行卡死
避免大数组进行查询等运算,使用 Object、Map 或者 Set 进行优化
HTML 标签和属性操作,必须限定/过滤传入变量值
永远不要在渲染函数中创建随机值(Math.random() Date.now())
永远不要在渲染中创造新的组件,这将导致 React 反复销毁并重新创建子组件树
轻易不要复制代码,如果必需的话,请手敲一遍,确保需要执行的每一行代码都是可用的
结构的设计要尽量考虑向前兼容和以后的版本升级,并为某些未来可能的应用保留余地
解决 bug 不能只考虑 bug 本身,要分析产生的原因
不要在提示用户的信息的中添加语气助词以及网络用语,使用陈述句
建议不要在 package.json 依赖项中使用 ^ ~ 等,最好直接使用当前的版本号,以避免依赖项升级导致项目问题
尽量不使用行内样式,即使使用 props 传递,在一定范围内也要传递 class 类
注重语意,操作数组不需要返回值时使用 forEach,而不是 map,同时 map 会比 forEach 慢
多使用可以终止的循环,如 some,every,find 等(空数组使用 some 时返回 false,every 返回 true)
不要使用 setTimeout 解决异步问题,这将会成为一个不易重现(更加复杂)的 bug
在符合逻辑的情况下,尽量大的提升系统的容错,增强健壮性
注重事物生命周期,严格遵循初始化时候创建,结束前清理