前端开发规范基础汇总
命名规范
常用的命名规范
- camelCase(小驼峰式命名法 —— 首字小写)
- PascalCase(大驼峰式命名法 —— 首字大写)
- snake_case(下划线命名法)
- kebab-case(短横线命名法)
项目文件命名
项目命名
全部采用小写方式,以短横线分隔。例:my-project-name
。
- 全部小写,单词之间用中划线隔开
- 不能以数字开头
- 不能包含特殊字符(除了中划线)
目录命名
参照项目命名规则,有复数结构时,要采用复数命名法。例:docs
、assets
、components
、directives
、mixins
、utils
、views
。
图像文件命名
全部采用小写方式,优先选择单个单词命名,多单词名以短横线分隔。例:my-image-name.png
。
banner_sina.gif
menu_aboutus.gif
menutitle_news.gif
logo_police.gif
logo_national.gif
pic_people.jpg
pic_TV.jpg
HTML 文件命名
全部采用小写方式,优先选择单个单词命名,多单词名以短横线分隔。例:my-html-name.html
。
error_report.html
success_report.html
CSS 文件命名
全部采用小写方式,优先选择单个单词命名,多单词名以短横线分隔。例:my-css-name.css
。
normalize.less
base.less
date-picker.scss
input-number.scss
JavaScript 文件命名
全部采用小写方式,优先选择单个单词命名,多单词名以短横线分隔。例:my-js-name.js
。
app.js
utils.js
date-util.js
collapse-transition.js
Vue 组件命名
单文件组件名
文件扩展名为.vue
的单文件。组件名应该始终是单词大写开头 (PascalCase)。
components/
|- MyComponent.vue
单例组件名
只拥有单个活跃实例的组件应该以 The 前缀命名,以示其唯一性。
这不意味着组件只可用于一个单页面,而是每个页面只使用一次。这些组件永远不接受任何 prop
,因为它们是为你的应用定制的。如果你发现有必要添加 prop
,那就表明这实际上是一个可复用的组件,只是目前在每个页面里只使用一次。
比如,头部
和侧边栏
组件几乎在每个页面都会使用,不接受prop
,该组件是专门为该应用所定制的。
components/
|- TheHeader.vue
|- TheSidebar.vue
基础组件名
不包含业务,独立、具体功能的基础组件.
比如日期选择器
、模态框
等。这类组件作为项目的基础控件,会被大量使用,因此组件的API
进行过高强度的抽象,可以通过不同配置实现不同的功能。
应用特定样式和约定
的基础组件(也就是展示类的、无逻辑的或无状态、不掺杂业务逻辑的组件) 应该全部以一个特定的前缀开头 —— Base
。基础组件在一个页面内可使用多次,在不同页面内也可复用,是高可复用组件。
components/
|- BaseButton.vue
|- BaseTable.vue
|- BaseIcon.vue
业务组件
它不像基础组件只包含某个功能,而是在业务中被多个页面复用的(具有可复用性),它与基础组件的区别是,业务组件只在当前项目中会用到,不具有通用性,而且会包含一些业务,比如数据请求;而基础组件不含业务,在任何项目中都可以使用,功能单一,比如一个具有数据校验功能的输入框。
掺杂了复杂业务的组件(拥有自身 data、prop 的相关处理)即业务组件应该以Custom
前缀命名。业务组件在一个页面内比如:某个页面内有一个卡片列表,而样式和逻辑跟业务紧密相关的卡片就是业务组件。
components/
|- CustomCard.vue
紧密耦合的组件名
和父组件紧密耦合的子组件应该以父组件名作为前缀命名
。 因为编辑器通常会按字母顺序组织文件,所以这样做可以把相关联的文件排在一起。
components/
|- TodoList.vue
|- TodoListItem.vue
|- TodoListItemButton.vue
组件名中单词顺序
组件名应该以高级别的 (通常是一般化描述的) 单词开头,以描述性的修饰词结尾。 因为编辑器通常会按字母顺序组织文件,所以现在组件之间的重要关系一目了然。如下组件主要是用于搜索和设置功能。
components/
|- SearchButtonClear.vue
|- SearchButtonRun.vue
|- SearchInputQuery.vue
|- SearchInputExcludeGlob.vue
|- SettingsCheckboxTerms.vue
|- SettingsCheckboxLaunchOnStartup.vue
还有另一种多级目录的方式,把所有的搜索组件放到“search”目录,把所有的设置组件放到“settings”目录。
完整单词的组件名
组件名应该倾向于完整单词而不是缩写。编辑器中的自动补全已经让书写长命名的代价非常之低了,而其带来的明确性却是非常宝贵的。不常用的缩写尤其应该避免。
components/
|- StudentDashboardSettings.vue
|- UserProfileOptions.vue
变量和方法
变量命名
变量命名方法应遵循camelCase
(小驼峰式命名法)。命名规范遵循:类型 + 对象描述或属性的方式
// bad
var getTitle = "LoginTable"// good
let tableTitle = "LoginTable"
let mySchool = "我的学校"
常量命名
常量命名方法应遵循全部大写下划线分割
。命名规范遵循:使用大写字母和下划线来组合命名,下划线用以分割单词。
const MAX_COUNT = 10
const URL = 'http://test.host.com'
方法命名
方法命名方法应遵循camelCase
(小驼峰式命名法)。命名规范遵循:动词
或者 动词 + 名词
的方式。
// 1、普通情况下,使用动词 + 名词形式
// bad
go、nextPage、show、open、login// good
jumpPage、openCarInfoDialog// 2、请求数据方法,以 data 结尾
// bad
takeData、confirmData、getList、postForm// good
getListData、postFormData// 3、单个动词的情况
init、refresh
动词 | 含义 | 返回值 |
---|---|---|
can | 判断是否可执行某个动作 (权 ) | 函数返回一个布尔值。true:可执行;false:不可执行; |
has | 判断是否含有某个值 | 函数返回一个布尔值。true:含有此值;false:不含有此值; |
is | 判断是否为某个值 | 函数返回一个布尔值。true:为某个值;false:不为某个值; |
get | 获取某个值 | 函数返回一个非布尔值 |
set | 设置某个值 | 无返回值、返回是否设置成功或者返回链式对象 |
自定义事件
自定义事件应始终使用 kebab-case
的事件名,事件名应全部小写,且使用短横线命名。
this.$emit('my-event')<MyComponent @my-event="handleDoSomething" />
- 原生事件参考列表
<div@blur="toggleHeaderBlur"@focus="toggleHeaderFocus"@click="toggleMenu"@keydown.esc="handleKeydown"@keydown.enter="handleKeydown"@keydown.up.prevent="handleKeydown"@keydown.down.prevent="handleKeydown"@keydown.tab="handleKeydown"@keydown.delete="handleKeydown"@mouseenter="hasMouseHoverHead = true"@mouseleave="hasMouseHoverHead = false">
</div>
而为了区分原生事件和自定义事件在 Vue 中的使用,建议除了多单词事件名使用 kebab-case 的情况下,命名还需遵守为 on + 动词
的形式,如下:
<!-- 父组件 -->
<div@on-search="handleSearch"@on-clear="handleClear"@on-clickoutside="handleClickOutside">
</div>// 子组件
export default {methods: {handleTriggerItem () {this.$emit('on-clear')}}
}
事件方法
事件方法命名应遵循camelCase
(小驼峰式命名法)。命名规范遵循:handle + 名称(可选)+ 动词
的方式。
<div@click.native.stop="handleItemClick()"@mouseenter.native.stop="handleItemHover()">
</div>export default {methods: {handleItemClick () {// 业务逻辑...},handleItemHover () {// 业务逻辑...}}
}
编码规范
HTML/Template 编码规范
语法
1. 缩进使用两个空格代替 Tab
- 前端代码层级较深,使用短缩进有利于利用屏幕空间,提升效率。
- 使用两个空格代替 Tab 可以保证在所有环境下获得一致展现。
<!-- not good -->
<div><div>bar</div>
</div><!-- good -->
<div><div>bar</div>
</div>
2. 嵌套元素应当缩进一次(即两个空格),同层级缩进应保持一致
<!-- not good -->
<div>
<div>bar</div><div>bar</div>
</div><!-- good -->
<div><div>bar</div><div>bar</div>
</div>
3. 对于属性的定义,使用双引号,不要使用单引号
<!-- not good -->
<input class='a' type=text><!-- good -->
<input class="a" type="text">
4. 不要省略可选的结束标签(closing tag)(如 或 )
<!-- not good -->
<h1>h1 text<h2>h2 text<!-- good -->
<h1>h1 text</h1>
<h2>h2 text</h2>
5. 特殊符号使用 HTML 字符实体(实体名称对大小写敏感),常用如下:
符号 | 实体编码 |
---|---|
空格 | |
© | © |
¥ | ¥ |
® | ® |
> | > |
< | < |
& | & |
6. td / th 要在 tr 里面,li 要在 ul / ol 里面
<!-- not good -->
<table><td>test</td>
</table><!-- good -->
<table><tr><td>test</td></tr>
</table>
7. ul / ol 的直接子元素只能是 li,不能包含其他元素
<!-- not good -->
<ul><span>123</span><li>a</li><li>b</li>
</ul>
8. 行内元素里面不可使用块级元素
a 标签是一个行内元素,行内元素里面套了一个 div 的标签,这样可能会导致 a 标签无法正常点击。
<!-- not good -->
<a href="../test"><div></div>
</a>
可以使用如下代码进行修复:
<a href="../test" style="display: block"><div></div>
</a>
9. 不使用重复属性,重复的属性只会取第一个
<!-- error -->
<input class="a" type="text" class="b"><!-- good -->
<input class="a b" type="text">
10. 不要在自闭合(self-closing)元素的尾部添加斜线( HTML5 规范中说明这是可选的)
<!-- not good -->
<img src="logo.png" alt /><!-- good -->
<img src="logo.png" alt>
11. 尽量不使用属性设置样式(img, table等元素)
<!-- not good -->
<img src="test.jpg" alt width="400" height="300"><!-- good -->
<img src="test.jpg" style="width:400px;height:300px;">
11.自定义属性要以data-开头 自己添加的非标准的属性要以data-开头,否则w3c validator会认为是不规范的
<!-- not good -->
<div count="5"></div><!-- good -->
<div data-count="5"></div>
HTML5 doctype
为每个 HTML 页面添加标准模式(standard mode)的声明,确保在每个浏览器中拥有一致的展现。
<!DOCTYPE html><html>...
语言属性
为每个 HTML 页面根元素添加 lang 属性。
根据 HTML5 规范:
强烈建议为 html 根元素指定 lang 属性,从而为文档设置正确的语言。这将有助于语音合成工具确定其所应该采用的发音,有助于翻译工具确定其翻译时所应遵守的规则等等。
<html lang="zh-CN"><!-- ... -->
</html>
字符编码
通过声明一个明确的字符编码,让浏览器轻松、快速的确定网页内容渲染方式,通常指定为’UTF-8’
<html><head><meta charset="UTF-8"></head>...
引入CSS和JavaScript文件
根据 HTML5 规范,在引入 CSS 和 JavaScript 文件时不需要指定 type 属性,因为 text/css 和 text/javascript 分别是它们的默认值。
<!-- External CSS -->
<link rel="stylesheet" href="code_guide.css"><!-- In-document CSS -->
<style>...
</style><!-- External JS -->
<script src="code_guide.js"></script><!-- In-document JS -->
<script>...
</script>
减少标签的数量
建议编写 HTML 代码时,条件满足的情况下尽量避免多余的层级。
<!-- not good -->
<span class="avatar"><img src="...">
</span><!-- good -->
<img class="avatar" src="...">
属性顺序
仅做参考:属性应该按照特定的顺序出现以保证易读性。
1. class
2. id
3. name
4. data-*
5. src, for, type, href, value , max-length, max, 7. min, pattern
8. placeholder, title, alt
9. aria-*, role
10. required, readonly, disabled
语义化
尽量遵循 HTML 标准和语义,但是不要以牺牲实用性为代价;任何时候都要尽量使用最少的标签并保持最小的复杂度。
CSS/Less编码规范
命名
1. 类名使用小写字母,以中划线分隔
<div class="user-info"><div class="user-info-name"><span>张三</span></div>
</div>
2. id 采用驼峰式命名
<div id="userInfo"><div class="user-info-name"><span>张三</span></div>
</div>
3. less 中的变量、函数、混合等采用驼峰式命名
@mainFontColor: #444;#companyName,
.company-name {color: @mainFontColor;
}
语法
1. 所有声明语句都应当以分号结尾
最后一条声明语句后面的分号是可选的,但是,如果省略这个分号,你的代码可能更易出错
/* error */
.selector {font-size: 15pxcolor: red
}/* not good */
.selector {font-size: 15px;color: red
}/* good */
.selector {font-size: 15px;color: red;
}
2. 避免为 0 值指定单位
例如:用 margin: 0; 代替 margin: 0px;
/* not good */
.selector {margin: 0px;
}/* good */
.selector {margin: 0;
}
3. 为选择器中的属性添加双引号,例如,input[type=“text”];
某些情况下是可选的,但是,为了代码的一致性,建议都加上双引号。
/* not good */
.selector[type=text] {/* ... */
}/* good */
.selector[type="text"] {/* ... */
}
4. 十六进制值应该全部小写
例如,#f3f6fa 而不是 #F3F6FA
/* not good */
.selector {color: #F3F6FA;
}/* good */
.selector {color: #f3f6fa;
}
5. 不出现空的规则(声明块中没有声明语句)
/* not good */
.selector {
}/* good */
.selector {color: #f3f6fa;
}
6. 不要设置太大的z-index
一个正常的系统的层级关系在 10 以内就能完成。
/* not good */
.selector {z-index: 9999;
}/* good */
.selector {z-index: 10;
}
7. 多写注释,且多使用句子进行描述而不是词语
/* 为了去除输入框和表单点击时的灰色背景 */
input,
form {-webkit-tap-highlight-color: rgba(255, 255, 255, 0);
}
8. 非特殊情况下,不要使用*选择器
9. 适当使用:before和:after来画页面的一些视觉上的辅助性元素,如三角形、短的分隔线、短竖线等,可以减少页面上没有用的标签
10. 选择器不要超过4层(在 Less 中避免嵌套超过 4 层)
11. 用 border: 0; 代替 border: none;
/* not good */
.selector {border: none;
}/* good */
.selector {border: 0;
}
12. 使用简写形式的十六进制值
例如:用 #fff
代替 #ffffff
。
13. 对于属性值或颜色参数,省略小于 1 的小数前面的 0
例如:.5
代替 0.5
;-.5px
代替 -0.5px
选择器权重
权重判断基本规则:
- 相同的权重:以后面出现的选择器为最后规则;
- 不同的权重,权重值高则生效;
设置规范:
- 非通用样式使用嵌套方式进行编写,避免影响其他自己不了解样式,造成样式覆盖;
- Vue 中样式合理使用
scoped
,会影响样式选择器性能,请使用第一点进行特有样式编写; - 样式需要修改时,尽量找到原样式声明进行修改;
- 无法修改原样式声明时,应通过权重关系,编写权重更高的样式进行覆盖;
- 不使用
!important
,除非原样式使用内联样式或!important
且无法直接修改;
声明简写
1. 当你不确定自己写的属性会否影响到其他属性时,应避免使用简写
/* error */
.element {margin: 0 0 10px;background: red;background: url("image.jpg");border-radius: 3px 3px 0 0;
}/* good */
.element {margin-bottom: 10px;background-color: red;background-image: url("image.jpg");border-top-left-radius: 3px;border-top-right-radius: 3px;
}
2. 当你确定自己的声明不会影响到其他属性时,请使用简写提升代码简洁性
/* not good */
.element {padding-top: 10px;padding-right: 20px;padding-bottom: 15px;padding-left: 20px;
}/* good */
.element {padding: 10px 20px 15px;
}
JavaScript编码规范
命名
1. 标准变量采用驼峰式命名
考虑与后台交换数据的情况,对象属性可灵活命名。
let userName = '张三';
let userAge = 18;
2.常量全大写,用下划线连接
const USER_NAME = '张三';
const USER_AGE = 18;
3. 变量名并非越短越好
变量名不应过短,要能准确完整地描述该变量所表述的事物。
不好的变量名 | 好的变量名 |
---|---|
inp | input, priceInput |
day1, day2, param1 | today, tomorrow |
id | userId, orderId |
obj | orderData, houseInfos |
tId | removeMsgTimerId |
handler | submitHandler, searchHandler |
4. 变量名不要使用计算机术语
如texareaData
,应该取和业务相关的名字,如 leaveMsg
。
5. 变量名的对仗要明确
如 up/down
、begin/end
、opened/closed
、visible/invisible
、scource/target
。
6. 变量名使用正确的语法
不要使用中文拼音,如 shijianchuo
应改成 timestamp
; 如果是复数的话加 s
,或者加上 List
,如 orderList
、menuItems
; 而过去式的加上 ed
,如 updated/found
等; 如果正在进行的加上 ing
,如 calling
;
7.使用临时变量时请结合实际需要进行变量命名
有些喜欢取temp
和obj
之类的变量,如果这种临时变量在两行代码内就用完了,接下来的代码就不会再用了,还是可以接受的,如交换数组的两个元素。但是有些人取了个temp
,接下来十几行代码都用到了这个temp
,这个就让人很困惑了。所以应该尽量少用temp
类的变量。
// not good
let temp = 10;
let leftPosition = currentPosition + temp,topPosition = currentPosition - temp;// good
let adjustSpace = 10;
let leftPosition = currentPosition + adjustSpace,topPosition = currentPosition - adjustSpace;
语法
1. 变量不要先使用后声明
a = 10;
let a;
2. 不要声明了变量却不使用
let a = 10;
let b;
a = 15;
3. 不要在同个作用域下声明同名变量
let a = 10;
let a = 15;
4. 一个函数作用域中所有的变量声明尽量提到函数首部,可根据代码进行分组,但不允许出现两个连续的变量声明
// not good
let registerForm = null;
let question = "";
let calculateResult = 0;// good
let registerForm = null,question = "",calculateResult = 0;
5. 为了快速知晓变量类型,声明变量时要赋值
// not good
let registerForm,question,calculateResult;// good
let registerForm = null,question = "",calculateResult = 0;
6. 单一函数的返回值类型要确定
如下无法确定该函数的最终返回类型:
// not good
function calculatePrice(seatCount){if (seatCount <= 0) {return "";} else {return seatCount * 79;}
}
7. 建议使用===
代替==
,!==
代替!=
==
会自动进行类型转换,可能会出现奇怪的结果。
null == undefined //true
'' == '0' //false
0 == '' //true
0 == '0' //true
' \t\r\n ' == 0 //true
new String("abc") == "abc" //true
new Boolean(true) == true //true
true == 1 //true
8. 使用三目运算代替简单的 if-else
// not good
let seatDiscount = 100;
if (seat < 5) {seatDiscount = 90;
} else if(seat < 10) {seatDiscount = 80;
} else {seatDiscount = 70;
}// good
let seatDiscount = seat < 5 ? 90 : seat < 10 ? 80 : 70;
9. 使用let定义变量,const定义常量
let userName = '张三';
const USER_NAME = '张三';
10. 使用箭头函数取代简单的函数
// not good
let _this = this;
setTimeout(function() {_this.foo = "bar";
}, 2000);// good
setTimeout(() => this.foo = "bar", 2000);
11. 建议在必要的地方添加非空判断以提高代码的稳健性
12. 建议将复杂的函数分解成多个子函数,方便维护和复用
代码风格
该部分一般采用代码格式化工具进行统一维护,不再表述。