一般规范
命名规范
命名分类
camelCase
(驼峰式,也叫小驼峰命名,e.g. userInfo
)PascalCase
(帕斯卡命名式,也叫大驼峰命名,e.g. UserInfo
)kebab-case
(短横线连接式,e.g. user-info
)snake_case
(下划线连接式,e.g. user_info
)
变量命名
- 命名方式 : 小驼峰式命名方法
- 命名规范 : 类型+对象描述或属性的方式
// bad
var getTitle = "LoginTable"
// good
let tableTitle = "LoginTable"
函数命名
- 命名方式 : 小驼峰方式 ( 构造函数使用大驼峰命名法 )
- 命名规则 : 前缀为动词
动词 | 含义 | 返回值 |
---|---|---|
can | 判断是否可执行某个动作 (权 ) | 函数返回一个布尔值。true:可执行;false:不可执行 |
has | 判断是否含有某个值 | 函数返回一个布尔值。true:含有此值;false:不含有此值 |
is | 判断是否为某个值 | 函数返回一个布尔值。true:为某个值;false:不为某个值 |
get | 获取某个值 | 函数返回一个非布尔值 |
set | 设置某个值 | 无返回值、返回是否设置成功或者返回链式对象 |
推荐:
//是否可阅读
function canRead(){
return true;
}
//获取姓名
function getName{
return this.name
}
常量命名
- 命名方法 : 全部大写
- 命名规范 : 使用大写字母和下划线来组合命名,下划线用以分割单词。
推荐:
const MAX_COUNT = 10;
const URL = 'http://test.host.com';
类的成员命名
- 公共属性和方法 : 同变量命名方式
- 私有属性和方法 : 前缀为下划线(_)后面跟公共属性和方法一样的命名方式
推荐:
function Student(name) {
var _name = name; // 私有成员
// 公共方法
this.getName = function () {
return _name;
}
// 公共方式
this.setName = function (value) {
_name = value;
}
}
var st = new Student('tom');
st.setName('jerry');
console.log(st.getName()); // => jerry:输出_name私有变量的值
注释规范
单行注释
- 单独一行:
//
(双斜线)与注释文字之间保留一个空格 - 在代码后面添加注释:
//
(双斜线)与代码之间保留一个空格,并且//(双斜线)与注释文字之间保留一个空格。 - 注释代码:
//
(双斜线)与代码之间保留一个空格。
推荐 :
// 调用了一个函数 <= 1)单独在一行
setTitle();
var maxCount = 10; // 设置最大量 <= 2)在代码后面注释
// setName(); // <= 3)注释代码
多行注释 ( / 注释说明 / )
- 若开始(
/\*
)和结束(\*/
)都在一行,推荐采用单行注释 - 若至少三行注释时,第一行为
/\*
,最后行为\*/
,其他行以*
开始,并且注释文字与*
保留一个空格。
推荐 :
/*
* 代码执行到这里后会调用setTitle()函数
* setTitle():设置title的值
*/
setTitle();
函数 ( 方法 ) 注释
函数(方法)注释也是多行注释的一种,但是包含了特殊的注释要求,参照JavaDoc规范
语法:
/**
* 函数说明
* @关键字
*/
常用注释关键字:
注释名 | 语法 | 含义 | 示例 |
---|---|---|---|
@param | @param 参数名 {参数类型} 描述信息 | 描述参数的信息 | @param name {String} 传入名称 |
@return | @return {返回类型} 描述信息 | 描述返回值的信息 | @return {Boolean} true:可执行;false:不可执行 |
@author | @author 作者信息 [附属信息:如邮箱、日期] | 描述此函数作者的信息 | @author 张三 2015/07/21 |
@version | @version XX.XX.XX | 描述此函数的版本号 | @version 1.0.3 |
@example | @example 示例代码 | @example setTitle(‘测试’) |
需要添加注释的地方
代码注释在一个项目的后期维护中显的尤为重要,所以我们要为每一个被复用的组件编写组件使用说明,为组件中每一个方法编写方法说明。
以下情况,务必添加注释:
1. 公共组件使用说明
2. 各组件中重要函数或者类说明
3. 复杂的业务逻辑处理说明
4. 特殊情况的代码处理说明,对于代码中特殊用途的变量、存在临界值、函数中使用的hack、使用了某种算法或思路等需要进行注释描述
5. 多重 if 判断语句
Vue规范
Vue项目规范
结构化规范(webpack)
├── index.html 入口页面
├── favicon.ico 页面图标
├── .babelrc babel规则
├── .editorconfig 编辑器配置
├── .eslintignore eslint忽略规律
├── .eslintrc.js eslint规则
├── .gitignore git忽略规则
├── build 构建脚本目录
│ ├── build-server.js 运行本地构建服务器,可以访问构后的页面
│ ├── build.js 生产环境构建脚本
│ ├── dev-client.js 开发服务器热重载脚本,主要用来实现开发阶段的页面自动刷新
│ ├── dev-server.js 运行本地开发服务器
│ ├── utils.js 构建相关工具方法
│ ├── webpack.base.conf.js wabpack基础配置
│ ├── webpack.dev.conf.js wabpack开发环境配置
│ └── webpack.prod.conf.js wabpack生产环境配置
│ └── webpack.cdn.conf.js wabpack cdn配置
│ └── webpack.dll.conf.js wabpack dll配置
├── config 项目配置
│ ├── dev.env.js 开发环境变量
│ ├── index.js 项目配置文件
│ ├── prod.env.js 生产环境变量
│ └── test.env.js 测试环境变量
├── mock mock数据目录
│ └── hello.js
├── package.json npm包配置文件,里面定义了项目的npm脚本,依赖包等信息
├── readmd.md 项目描述文件
├── src 项目源码目录
│ ├── main.js 入口js文件
│ ├── App.vue 根组件
│ ├── components 公共组件目录
│ │ └── ComponentItem.vue
│ ├── assets 静态资源目录,这里的资源会被wabpack构建
│ │ ├── css 公共样式文件目录
│ │ ├── js 公共js文件目录(如帮助方法)
│ │ └── img 图片存放目录
| |── lib 外部引用的插件存放及修改文件
| |—— datas 模拟数据,临时存放
│ ├── routes 前端路由
│ │ └── index.js
│ ├── apis 接口,统一管理
│ │ └── index.js
│ ├── store vuex, 统一管理
│ │ └── index.js
│ └── views 视图模块名
│ ├── view-module 视图模块
| └── index.vue 视图模块的主页面
│ ├── hello.vue
│ └── notfound.vue
├── static 纯静态资源,不会被wabpack构建。
└── test 测试文件目录(unit&e2e)
└── unit 单元测试
├── index.js 入口脚本
├── karma.conf.js karma配置文件
└── specs 单测case目录
└── Hello.spec.js
目录、文件、组件命名规范
1. 目录
目录统一使用kebab-case
风格
2. views下的文件
- js类文件使用
PascalCase
,如UserInfo.js
- 其他资源文件统一使用
kebab-case
风格,如user-detail.js
,user-detail.css
,user-avatar.png
3. 组件文件
- 命名遵循
PascalCase
约定。
组件文件名除index.vue
之外,一律采用PascalCase
(大驼峰)写法。原因是引入组件时,组件的变量通常用PascalCase
格式,以区别于一般变量。组件文件名与变量名一致,方便对应。
import UserBook from './user/UserBook'
- 组件名应该始终是多个单词的,根组件 App 除外
html元素都是单个单词的(如<article>
,<header>
),为了区分组件和一般html元素,组件由多个单词组成,如BookItem.vue,单独的Book.vue不推荐。
- 组件使用遵循
kebab-case
约定
在页面中使用组件需要前后闭合,并以短线分隔,如:
<user-book></user-book>
Vue开发规范
Vue文件结构
- 基本结构
顺序:template
-> script
-> style
。一个组件尽量不要超过200行,页面包含独立部分时尽量分离成子组件。
<template>
<div>...</div>
</template>
<script>
export default {
components: {},
data() {
return {};
},
created(){},
methods: {},
};
</script>
<!-- 声明语言,并且添加scoped -->
<style lang="scss" scoped>...</style>
- 组件/实例的选项顺序
- name (全局引用)
- components (模板依赖)
- directives ...
- filters ...
- mixins (组合)
- props (接口)
- data (本地状态属性)
- computed ...
- watch (响应回调)
- created (生命周期函数)
- mounted ...
- methods (实例属性)
Vue Router Path规范
router path
采用kebab-case
格式。
用下划线(如:
/user_info
)或camelCase
(如:/userInfo
)的单词被当成一个单词,搜索引擎无法区分语义。
// bad
{
path: '/user_info', // user_info当成一个单词
name: 'UserInfo',
component: UserInfo,
meta: {
title: ' - 用户',
desc: ''
}
},
// good
{
path: '/user-info', // 能解析成user info
name: 'UserInfo',
component: UserInfo,
meta: {
title: ' - 用户',
desc: ''
}
},
组件开发规范
1. 注册组件
注册组件的时候,全部使用 PascalCase
格式。
import UserBook from './user/UserBook'
2. props 命名规范
- 在声明
prop
的时候,其命名应该始终使用camelCase
,而在模板中应该始终使用kebab-case
<!-- bad -->
<welcome-message greetingText="hi"></welcome-message>
<script>
props: {
'greeting-text': String
}
</script>
<!-- good -->
<welcome-message greeting-text="hi"></welcome-message>
<script>
props: {
greetingText: String;
}
</script>
- prop定义应该尽量详细
- 组件
props
原子化 - 提供默认值
- 使用
type
属性校验类型
- 组件
// bad 这样做只有开发原型系统时可以接受
props: ['status']
// good
props: {
status: {
type: String,
required: true,
validator: function (value) {
return [
'syncing',
'synced',
'version-conflict',
'error'
].indexOf(value) !== -1
}
}
}
3. methods 命名规范
- 驼峰式命名,统一使用动词或者动词+名词形式
//bad
go、nextPage、show、login、get_code
// good
jumpPage、openCarInfoDialog
- 请求数据方法,以 data 结尾
//bad
takeData、confirmData、getList、postForm
// good
getListData、postFormData
- 尽量使用常用单词开头(set、get、go、can、has、is)
附: 函数方法常用的动词:
get 获取/set 设置,
add 增加/remove 删除
create 创建/destory 移除
start 启动/stop 停止
open 打开/close 关闭,
read 读取/write 写入
load 载入/save 保存,
create 创建/destroy 销毁
begin 开始/end 结束,
backup 备份/restore 恢复
import 导入/export 导出,
split 分割/merge 合并
inject 注入/extract 提取,
attach 附着/detach 脱离
bind 绑定/separate 分离,
view 查看/browse 浏览
edit 编辑/modify 修改,
select 选取/mark 标记
copy 复制/paste 粘贴,
undo 撤销/redo 重做
insert 插入/delete 移除,
add 加入/append 添加
clean 清理/clear 清除,
index 索引/sort 排序
find 查找/search 搜索,
increase 增加/decrease 减少
play 播放/pause 暂停,
launch 启动/run 运行
compile 编译/execute 执行,
debug 调试/trace 跟踪
observe 观察/listen 监听,
build 构建/publish 发布
input 输入/output 输出,
encode 编码/decode 解码
encrypt 加密/decrypt 解密,
compress 压缩/decompress 解压缩
pack 打包/unpack 解包,
parse 解析/emit 生成
connect 连接/disconnect 断开,
send 发送/receive 接收
download 下载/upload 上传,
refresh 刷新/synchronize 同步
update 更新/revert 复原,
lock 锁定/unlock 解锁
check out 签出/check in 签入,
submit 提交/commit 交付
push 推/pull 拉,
expand 展开/collapse 折叠
begin 起始/end 结束,
start 开始/finish 完成
enter 进入/exit 退出,
abort 放弃/quit 离开
obsolete 废弃/depreciate 废旧,
collect 收集/aggregate 聚集
4. 多个属性的html元素规范
多个特性的元素,占据一行过长时,应该分多行撰写,每个特性一行。(增强更易读)
<!-- bad -->
<img src="https://vuejs.org/images/logo.png" alt="Vue Logo">
<my-component foo="fooattribute" bar="barattribute" baz="bazattribute"></my-component>
<!-- good -->
<img
src="https://vuejs.org/images/logo.png"
alt="Vue Logo"
>
<my-component
foo="fooattribute"
bar="barattribute"
baz="bazattribute"
>
</my-component>
5. 元素属性的顺序
原生属性放前面,指令放后面
- class
- id,ref
- name
- data-*
- src, for, type, href,value,max-length,max,min,pattern
- title, alt,placeholder
- aria-*, role
- required,readonly,disabled
- is
- v-for
- key
- v-if
- v-else-if
- v-else
- v-show
- v-cloak
- v-pre
- v-once
- v-model
- v-bind,:
- v-on,@
- v-html
- v-text
6. 指令规范
- 指令有缩写则一律采用缩写形式
// bad
v-bind:code="code"
v-on:click="getUserData"
// good
:code="code"
@click="getUserData"
- v-for 循环必须加上 key 属性,在整个 for 循环中 key 需要唯一
<!-- bad -->
<ul>
<li v-for="todo in todos">
</li>
</ul>
<!-- good -->
<ul>
<li v-for="todo in todos" :key="todo.id">
</li>
</ul>
- 避免
v-if
和v-for
同时用在一个元素上(性能问题) 出现这样的需求,有两种解决方案:
- 将数据替换为一个计算属性,让其返回过滤后的列表
<!-- bad -->
<ul>
<li v-for="user in users" v-if="user.isActive" :key="user.id">
</li>
</ul>
<!-- good -->
<ul>
<li v-for="user in activeUsers" :key="user.id">
</li>
</ul>
<script>
computed: {
activeUsers: function () {
return this.users.filter(function (user) {
return user.isActive
})
}
}
</script>
- 将 v-if 移动至容器元素上 (比如 ul, ol)
<!-- bad -->
<ul>
<li v-for="user in users" v-if="shouldShowUsers" :key="user.id">
</li>
</ul>
<!-- good -->
<ul v-if="shouldShowUsers">
<li v-for="user in users" :key="user.id">
</li>
</ul>
其他
- 避免
this.$parent
- 调试信息
console.log()
使用完及时删除 - 除了三目运算,
if
,else
等禁止简写 - 行尾分号可以加或不加,应统一风格,但建议都不加。分号的作用在现代ES脚本不会影响,如果你不懂分号的作用,该入的坑照样会入,没有分号的代码更加清爽。大部分Vue项目都去除了分号。
// bad
if (true)
alert(name);
console.log(name);
// bad
if (true)
alert(name);
console.log(name);
// good
if (true) {
alert(name)
}
console.log(name)
HTML规范
语义化
语义化是指:根据元素其被创造出来时的初始意义来使用它。 用正确的标签表达正确的内容,这也有利于SEO。
alt标签不为空
<img>
标签的 alt
属性指定了替代文本,用于在图像无法显示或者用户禁用图像显示时,代替图像显示在浏览器中的内容。 假设由于下列原因用户无法查看图像,alt
属性可以为图像提供替代的信息:
- 网速太慢
- src 属性中的错误
- 浏览器禁用图像
- 用户使用的是屏幕阅读器 从SEO角度考虑,浏览器的爬虫爬不到图片的内容,所以我们要有文字告诉爬虫图片的内容
结构、表现、行为三者分离
- 尽量在文档和模板中只包含结构性的 HTML;
- 将所有表现代码,移入样式表中;
- 将所有动作行为,移入脚本之中。
HTML只关注内容
- HTML只显示展示内容信息
- 不要引入一些特定的 HTML 结构来解决一些视觉设计问题,多考虑使用伪元素
:before
、:after
- 不要将
img
元素当做专门用来做视觉设计的元素 - 样式上的问题应该使用css解决
<!-- bad -->
<!-- We should not introduce an additional element just to solve a design problem -->
<span class="text-box">
<span class="square"></span>
See the square next to me?
</span>
css 代码:
.text-box > .square {
display: inline-block;
width: 1rem;
height: 1rem;
background-color: red;
}
<!-- good -->
<!-- That's clean markup! -->
<span class="text-box">
See the square next to me?
</span>
css 代码:
/* We use a :before pseudo element to solve the design problem of placing a colored square in front of the text content */
.text-box:before {
content: "";
display: inline-block;
width: 1rem;
height: 1rem;
background-color: red;
}
JS规范
一般规范
使用严格等===
总是使用 === 精确的比较操作符,避免在判断的过程中,由 JavaScript 的强制类型转换所造成的困扰。
this关键字
只在对象构造器、方法和在设定的闭包中使用 this 关键字。
this 的语义常容易被误导。它时而指向全局对象(大多数时),时而指向调用者的定义域(在 eval
中),时而指向 DOM 树中的某一节点(当用事件处理绑定到 HTML 属性上时),时而指向一个新创建的对象(在构造器中),还时而指向其它的一些对象(如果函数被 call() 和 apply() 执行和调用时)。
正因为它是如此容易地被搞错,请限制它的使用场景:
- 在构造函数中
- 在对象的方法中(包括由此创建出的闭包内)
三元操作符
用三元操作符分配或返回语句。在比较简单的情况下使用,避免在复杂的情况下使用。
// bad
if(x === 10) {
return 'valid';
} else {
return 'invalid';
}
// good
return x === 10 ? 'valid' : 'invalid'
不使用eval()函数
就如eval
的字面意思来说,恶魔,使用eval()
函数会带来安全隐患。 eval()
函数的作用是返回任意字符串,当作js代码来处理。
使用ES6编码规范
- 定义变量使用
let
,定义常量使用const
- 静态字符串一律使用单引号或反引号,动态字符串使用反引号
// bad
const a = 'foobar';
const b = 'foo' + a + 'bar';
// good
const a = 'foobar';
const b = `foo${a}bar`;
const c = 'foobar';
- 解构赋值
// 1. 数组解构赋值
const arr = [1, 2, 3, 4];
// bad
const first = arr[0];
const second = arr[1];
// good
const [first, second] = arr;
// 2. 对象解构赋值
// bad
function getFullName(user) {
const firstName = user.firstName;
const lastName = user.lastName;
}
// good
function getFullName(obj) {
const { firstName, lastName } = obj;
}
// best
function getFullName({ firstName, lastName }) {}
- 使用扩展运算符(…)拷贝数组。
const items = [1, 2, 3, 4, 5];
// bad
const itemsCopy = items;
// good
const itemsCopy = [...items];
- 箭头函数 需要使用函数表达式的场合,尽量用箭头函数代替。因为这样更简洁,而且绑定了 this
// bad
const self = this;
const boundMethod = function(...params) {
return method.apply(self, params);
};
// good
const boundMethod = (...params) => method.apply(this, params);
CSS规范
合理地使用ID
一般情况下ID不应该被用于样式,并且ID的权重很高,所以不使用ID解决样式的问题,而是使用class
css选择器中避免使用标签名
从结构、表现、行为分离的原则来看,应该尽量避免css中出现HTML标签,并且在css选择器中出现标签名会存在潜在的问题。
使用直接子选择器
使用后代选择器常可能导致设计问题和性能损耗,这是个不好的做法,应总是考虑直接子选择器
/* bad */
.content .title {
font-size: 2rem;
}
/* good */
.content > .title {
font-size: 2rem;
}
尽量使用缩写属性
尽量使用缩写属性对于代码效率和可读性是很有用的,比如font属性。
/* bad */
.user-box {
border-top-style: none;
font-family: palatino, georgia, serif;
font-size: 100%;
line-height: 1.6;
padding-bottom: 2em;
padding-left: 1em;
padding-right: 1em;
padding-top: 0;
}
/* good */
.user-box {
border-top: 0;
font: 100%/1.6 palatino, georgia, serif;
padding: 0 1em 2em;
}
0后面不带单位
/* bad */
.user-box {
padding-bottom: 0px;
margin: 0em;
}
/* good */
.user-box {
padding-bottom: 0;
margin: 0;
}
属性格式
- 为了保证一致性和可扩展性,每个声明应该用分号结束,每个声明换行。
- 属性名的冒号后使用一个空格。出于一致性的原因,
- 属性和值(但属性和冒号之间没有空格)的之间始终使用一个空格。
- 每个选择器和属性声明总是使用新的一行。
- 属性选择器或属性值用双引号(””),而不是单引号(”)括起来。
属性顺序
作为最佳实践,我们应该遵循以下顺序:
- 结构性属性: display position, left, top, right etc. overflow, float, clear etc. margin, padding
- 表现性属性: background, border etc. font, text
/* bad */
.box {
font-family: 'Arial', sans-serif;
border: 3px solid #ddd;
left: 30%;
position: absolute;
text-transform: uppercase;
background-color: #eee;
right: 30%;
isplay: block;
font-size: 1.5rem;
overflow: hidden;
padding: 1em;
margin: 1em;
}
/* good */
.box {
display: block;
position: absolute;
left: 30%;
right: 30%;
overflow: hidden;
margin: 1em;
padding: 1em;
background-color: #eee;
border: 3px solid #ddd;
font-family: 'Arial', sans-serif;
font-size: 1.5rem;
text-transform: uppercase;
}
作者:李一枫 链接:https://juejin.im/post/5e1abeede51d453c913c340e 来源:掘金 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。