1. 布尔值(Boolean)命名
Boolean值是两种逻辑状态的变量,它包含两个值:真和假。在JavaScript中对应 true 和 false,在实践中通常使用数字1表示真值,0来表示假值。
虽然Boolean的状态只有两种但是在命名时可以进一步分类,这里给出几种场景:
场景一:表示可见性、进行中的状态
解释:
- 可见性在通常指页面中的元素、组件是否显示(或者组件挂载到DOM上,但并不可见)。
- 进行中主要是说明某种状态是处于持续进行中。
推荐命名方式为is + 动词(现在进行时)/形容词,同时这种方式也可以直接不写is,但是为了更好的作区分,建议还是加上。
{
isShow: '是否显示',
isVisible: '是否可见',
isLoading: '是否处于加载中',
isConnecting: '是否处于连接中',
isValidating: '正在验证中',
isRunning: '正在运行中',
isListening: '正在监听中'
}
场景二:属性状态类
解释:通常用来描述实体(例如:HTML标签、组件、对象)的功能属性,而且定法比较固定。
{
disabled: '是否禁用',
editable: '是否可编辑',
clearable: '是否可清除',
readonly: '只读',
expandable: '是否可展开',
checked: '是否选中',
enumberable: '是否可枚举',
iterable: '是否可迭代',
clickable: '是否可点击',
draggable: '是否可拖拽'
}
场景三:配置类、选项类
解释:主要是指组件功能的开启与关闭,功能属性的配置。
这是一种比较常见的情景,目前命名方式也有很多种,但是归纳起来也不多。推荐使用 withXx 来表示组件在基本功能形态外的其它功能,比如组件的基础功能到高级功能的开启;使用 enableXx 来表示组件某些功能的开启;使用 allowXx 来表示功能属性的配置;使用 noXx 用于建议功能使用者这个不建议开启。
{
withTab: '是否带选项卡',
withoutTab: '不带选项卡',
enableFilter: '开启过滤',
allownCustomScale: '允许自定义缩放',
shouldClear: '是否清除',
canSelectItem: '是否能选中元素',
noColon: '不显示label后面的冒号',
checkJs: '检查Js',
emitBOM: 'Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files.'
}
注意:如果嫌分类太多,可以只使用其中一种方式,比如在Typescript中使用了
allownXx和noXx。
除了上面这些带有特定的前置介词、动词方式外还有一些在语义上带有疑问性质的组合通常也是作为Boolean命名的一种参考。
{
virtualScroll: '是否启用虚拟滚动模式',
unlinkPanels: '在范围选择器里取消两个日期面板之间的联动',
validateEvent: '输入时是否触发表单的校验'
}
2. 函数命名
函数在不同的上下文中的叫法也不一样,在对象中称为方法,在类中有构造函数、在异步处理时有回调函数,还有立即执行函数、箭头函数、柯里函数等。
函数命名的方式常常是和业务逻辑耦合在一起的,通常根据其功能或目的进行命名。但是在命名规则上也有一些常见的模式可以遵循。
场景一:事件处理
事件处理函数是前端平时用到最多的,包括浏览器原生事件、异步事件和组件自定义事件。在写法上最常见的两种命名分别为 onXx、onXxClick和handleXx、handleXxChange。
这里如何在二者之间选择,可以从二方面来归类。
- 原生事件采用
onXx,而自定义事件使用handleXx。 - 事件主动监听采用
onXx,被动处理使用handleXx。
从实践及三大主流框架的文档关于事件部分的内容来看,推荐使用 handleXx 这种方式,而在表单提交的时候通常采用 onSubmit 函数。
其实,在实际项目中很少严格这样来命名事件处理函数,因为这种方式有一定的局限性,比如点击按钮打开一个对话框,使用 handleOpenDlg 和 onOpenDlg 都没有直接写 openDlg 方便,如果页面有多个不同功能的对话框采用这种方式会显得变量名过长,而handle和on就显得没有必要了,比如 hanldeOpenCommentDlg 就没有 openCommentDlg 直白。
下面列出了一些约定成俗的适用例子:
{
onSubmit: '提交表单',
handleSizeChange: '处理分页页数改变',
handlePageChange: '处理分页每页大小改变',
onKeydown: '按下键'
}
场景二:异步处理
这里主要是指在写数据层服务、状态管理中的Action命名,以及Ajax回调的命名规则。
{
getUsers: '获取用户列表',
fetchToken: '取得Token',
deleteUser: '删除用户',
removeTag: '移除标签',
updateUserInfo: '更新用户信息',
addUser: '添加用户',
createAccount: '创建账户'
}
命名主要围绕数据的增删查找来划分,获取数据通常是 getXx 和 fetchXx,在作者看来两者在使用上的区分在于 getXx 的数据来源不一定直接取自异步的原始数据,可能是加工处理后的,而 fetchXx 是直接拿的原始数据。当然在实际项目中并没有区分,看个人喜好。
deleteXx 主要用于数据删除,而 removeXx 在语义上是移除数据,通常情况数据是还存在的,只是没有显示或数据假删除。updateXx 是指数据更新操作,addXx 是在已有列表数据中添加新的子项、而createXx 主要是创建新的实例,比如新建一个账户。
场景三: 跳转路由
在实际开发过种中,比如在使用react-router/vue-router时,在模板或者JSX中可以直接在标签中写上目标地址,但有些时候跳转的目标地址是经过判断或者组合后的,并且通过事件触发跳转的,这个时候就需要一个函数来处理,那么在函数命名的时候可以考虑使用。
{
toTplDetail: '跳转到模板详情页面',
navigateToHome: '导航到首页',
jumpHome: '跳转首页',
goHome: '跳转首页',
redirectToLogin: '重定向到登录页',
switchTab: '切换Tab选项卡',
backHome: '回到主页'
}
推荐使用 toXx 和 goXx 这两种方式。
场景四:数据的加工
这类场景在处理列表的时候经常会碰到,比如排序、过滤、添加额外的字段、根据ID和索引获取特定数据等。
情形一:根据特定属性获取属性
这里可以参考DOM方法的命名,比如:getElememtById()、getElementsByTagName()、getElementsByClassName() 和 getElementsByName(),然后提炼出一个比较实用的模板:getXxByYy()。
其中 Xx 可以是:element, item, option, data, selection, list, options 以及一些特定上下文的名字,比如:user(s), menu(s) 等。Yy 相对来说比较固定,经常用到的就是 id, index, key, value, selected, actived 等。
除了使用 get,还可以使用 query 和 fetch,但是需要注意和上面提到的异步数据处理作一个区分。
{
getItemById: '根据ID获取数据元素',
getItemsBySelected: '根据传入的已选列表ID来获取列表全部数据',
queryUserByUid: '根据UID查询用户'
}
注意:在 getItemsBySelected 这种情形下直接写成 getItemsSelected 更好,但只适用于 Yy 为形容词的场景
情形二:格式化数据
这里的格式化操作包括排序、调整数据结构、过滤数据、添加属性。命名通常使用 formatXx, convertXx, inverseXx, toggleXx, parseXx, flatXx, 也可以结合数组的一些操作方法来命名,比如 sliceXx, substrXx, spliceXx, sortXx, joinXx 等来命名。
{
formatDate: '格式化日期',
convertCurrency: '转换货币单位',
inverseList: '反转数据列表',
toggleAllSelected: '切换所有已选择数据状态',
parseXml: '解析XML数据',
flatSelect: '展开选择数据',
sortByDesc: '按降序排序'
}
3. 数组命名
数组的命名推荐使用复数形式来命名,还有就是名词和具有列表意思的单词组合。常见的词汇有 options, list, maps, nodes, entities, collection 等。
{
users: '用户列表',
userList: '用户列表',
tabOptions: '选项卡选项',
stateMaps: '状态映射表',
selectedNodes: '选中的节点',
btnGroup: '按钮组',
userEntities: '用户实体'
}
4. 选项元素、下拉元素命名
主要针对的是在下拉选择框、选项卡元素、Radio、Checkbox等数据源每个选项数据的命名。
常见的词汇有:title, name, key, label, field, value, id, children, index, nodes 等。
基中 title/name/key/label/field 作为选项显示名, value/id 用于唯一标识选项,children/nodes 用于包含子节点内容。如果选项元素的语义很明确的情况下也可以直接使用特定单词来代替提到的这些泛指的词汇,例如菜单列表就可以使用 menu 来作为显示名。
// 最常见组合
{
title: '标题',
value: 'ID值'
}
// 组合二
{
label: '标签名',
value: 'ID值'
}
// 组合三
{
name: '元素名',
id: 'ID值'
}
// 组合四
{
field: '字段',
value: '标识',
index: '索引'
}
5. 临时数据、比对数据命名
针对在代码中有时会使用一些临时的变量来存储数据、保存数据快照的场景下的命名。
{
swapData: '临时交换数据',
tempData: '临时数据',
dataSnapshot: '数据快照'
}
6. 数据循环语句中变量命名
在使用 for 循环时,多层嵌套请依次使用 i/j/k,超过 3 层可以使用 x/y/z,m/n 来命名。
使用 forEach, map, filter 等方法时,每一个元素命名可以根据不同语境下的特殊名字来命名,比如遍历 menus,那么每个元素可以命名为 menu,不然则使用上下文无关的词汇,比如:item, option, data, key, object 等。至于索引通常使用 index,如果多层可以使用 index + 数字 的形式,也可以直接使用 i/j/k 来作为索引,甚至还可以使用 subIndex/grandIndex 这种方式来命名。
对于在使用 for 循环时数组长度如果需要单独命名的话,可以使用 xxlength/xxLens,或者 xxCount。
在循环的过程中通常还会统计某个条件下数据匹配的次数、重复元素数量、记录中间结果等情况。这里推荐使用 count 表示次数,skipped 表示跳过的数量,result 表示结果。
// for 循环
for (let i = 0; i < 10; i++) {
for (let j = 0; j < 10; j++) {
for (let k = 0; k < 10; k++) {
// do something
}
}
}
for (let i = 0, lens = this.options.length; i < lens; i++) {
// do something
}
// forEach
users.forEach((item, index) => {
// do something
})
menus.forEach((menu, index) => {
if (menu.children) {
menu.children.forEach((subMenu, subIndex) => {
if (subMenu.children) {
subMenu.children.forEach((grandMenu, grandIndex) => {
// 一个不常用的示例
})
}
})
}
})
7. 方法参数命名
方法的参数名称和数量在不同的方法中各不相同,但是还是有一些固定的模式可以参考,比如在 Vue 中监听属性变化的新值和旧值;reduce 方法的上一个值,当前值;回调函数的命名、剩余参数的命名等。
场景一:新值、旧值
常见于 Vue 中watch 对像中的属性监听回调函数,推荐使用
{
oldVal: '旧值',
newVal: '新值'
}
场景二:上一个值、下一个值和当前值
这种情形见于路由的钩子方法,Object.assign 数据拷贝的参数。
// 组合一
{
from: '从...',
to: '到...'
}
// 组合二
{
prev: '上一个...',
next: '下一个...',
cur: '当前'
}
// 组合三
{
source: '源',
target: '目标'
}
// 组合四
{
start: '开始',
end: '结束'
}
场景三:异步数据返回
用于 Promise 的then方法参数,await 的返回的 Promise 等。可选择的词汇有:result,res, data, json, entity,推荐使用 result。
demoPromise
.then(result => {
// do something
})
.catch(err => {
//
})
场景四:其它情况
一些使用不多,但是在编程时约定成俗的命名方式。例如 ch 表示单个字符,str 表示字符串, n 代表次数, reg 表示正则, expr 表示表达式, lens 表示数组长度, count 表示数量, p 表示数据的精度, q 表示查询(query), src 表示数据源(source), no 表示数字(number), rate 表示比率, status 表示状态, bool 表示布尔值, arr 表示数组值, obj 表示对象值, x 和 y 表示坐标两轴, func 表示函数, size 表示大小, unit 表示单位, hoz 表示水平方向, vert 表示垂直方向, radix 表示基数,根。
// 传入单个字符
function upper(ch) {}
// 数量重复
function repeat(str, n)
// 正则
'abab'.replace(reg, 'bb')
8. 状态管理命名
如果在项目中用到了状态管理(redux/vuex/ngrx),下面给出一些 ActionType,Mutation, Action 的命名参考。
// Redux 的 actionType
LOAD_SUCCESS
LOAD_FAIL
TOGGLE_SHOW_HISTORY
ON_PLAY
ON_LOAD_START
FETCH_SONGS_REQUEST
RECEIVE_PRODUCTS
// ngrx
const SET_CURRENT_USER = '[User] Set current';
const ADD_THREAD = '[Thread] Add';
const UPDATE_TRIP_SUCCESS = 'Update [Trip] Success';
9. 其它命名
// 日期、时间
// --------------------------------------------------------
sentAt: '发送时间'
addAt: '添加时间'
updateAt: '更新时间'
startDate: '开始日期'
endDate: '结束日期'
startTime: '开时时间'
endTime: '结束时间'