1.概述
1.1简述
此JavaScript编程规范的目的是确保代码的一致性、健壮性以便易于阅读和维护。<br /> 首先阐述下为什么代码规范是重中之重的问题。代码规范并非因为存在而重要,他的主要目的是确保代码对于开发者而言易于阅读和理解。好的代码,并非仅仅对其作者来说易于阅读和理解,而是其他的开发者也能够快速清晰地理解这些代码。高质量的代码能够帮助我们降低维护和更新成本,确保代码是符合项目要求的。
1.2目标群体
此文档的目标群体是为侃度从事JavaScript项目开发和维护的软件工程师。
1.3范围
此文档适用于所有侃度的以JavaScript为编程语言开发的软件项目。
1.4约束性
此规范的约束性用语言描述如下:
-Must: 必须遵守该规范。该规范针对的的内容将接受检查和审核。
-Should:应该遵守该规范。该规范针对的内容将接受检查。
-Can: 这些规范旨在提高质量,无强制的标砖。该规范针对的内容将不接受检查。
1.5质量标准
代码质量的评判标准如下:
-易读性: 对于开发人员的阅读和理解代码的要求应保持最低。
-可维护性:对于开发人员理解代码更新的要求应保持最低。
-稳定性: 软件能够在特定环境下维持性能水平
-高效性: 软件具有高性能水平。
-受测试性:一语惊醒软件的功能性测试。
-受支持性:维护代码能够快速的追踪错误和其产生的原因。
以下是额外的常规性要求:
可审查性: 代码必须格式化并且结构合理,以符合最低限度的审核要求。
符合手工审查要求:代码需要通过手工审查。
符合自动审查要求:代码需通过 代码审查工具的检验。
2.项目规范
2.1文件夹、组件命名规范,组件结构规范
2.1.1文件夹:
文件夹名称应统一格式,小写开头,见名知意,page页面下的文件夹名称统一以page结尾,
例如:homePage,loginPage。其余文件夹名称统一按照项目结构目录命名规范统一命名。
2.1.2.组件:
| 约束性 | 规范 | 质量标准 | 审查 |
|---|---|---|---|
| Should | 当多个单词拼写成的组件时,采用驼峰式命名规则。一般是多个单词全拼,减少简写的情况,这样增加可读性。 | 可读性 易维护性 |
手工 |
| Should | 组件应该都放到components文件夹下,单个页面独立一个文件夹,用来放相对应的vue文件以及页面相关的样式文件,样式少可直接写到页面组件里边,这样更符合组件化的思想。 公用组件应该统一放到public文件下。 |
可读性 易维护性 |
手工 |
2.1.3基础组件:
| 约束性 | 规范 | 质量标准 | 审查 |
|---|---|---|---|
| Should | 当项目中需要自定义比较多的基础组件的时候,比如一些button,input,icon,建议以一个统一的单词Base开头,或者放到base文件夹统一管理,这样做的目的是为了方便查找。 | 稳定性 可读性 易维护性 |
手工 |
| Should | 页面级组件应该放到相对应页面文件夹下,比如一些组件只有这个页面用到,其他地方没有用到的,可以直接放到页面文件夹,然后以父组件开头命名,例如:HomeHeader.vue,HomeNav.vue。 | 稳定性 可读性 易维护性 |
手工 |
| Should | 项目级组件一般放到公共文件夹public下给所有的页面使用。 | 稳定性 可读性 易维护性 |
手工 |
2.1.4.组件结构:
组件结构遵循从上往下template,script,style的结构。
<template><!--view代码--></template><script>export default {/*sript代码*/};</script><style scoped>/*css代码*/</style>
3.组件样式
单个组件样式一般可直接写到组件下style标签下,为了防止样式污染,可添加scoped 属性,也可以通过设置作用域来防止样式污染,写样式的时候尽量少写元素选择器,为了提高代码查找速度,可以用类选择器。
4.文件格式
5.Template模板文件
| 约束性 | 规范 | 质量标准 | 审查 |
|---|---|---|---|
| Must | 尽量使用以.vue结束的单文件组件,方便管理,结构清晰。 | 易读性 | 手工 |
| Should | 标签语义化,避免清一色的div元素 | 易读性 | 手工 |
| Should | .多特性,分行写,提高可读性。即一个标签内有多个属性,属性分行写。 | 易读性 | 手工 |
| Must | 自定义标签:使用自闭标签的写法。如果自定义标签中间需要传入slot,则写开始标签和结束标签,结束标签必须加/。 | 易读性 可维护性 稳定性 |
手工+自动 |
| Should | 组件/实例选项中的空行。便于阅读和代码架构清晰。 | 易读性 | 手工 |
| Must | 不得在标签中写入style属性 | 可维护性 稳定性 |
手工 |
6.Script
在 script 标签中,应该遵守Js的规范和ES6规范。
| 约束性 | 规范 | 质量标准 | 审查 |
|---|---|---|---|
| Must | Props定义:提供默认值,使用type属性校验类型,使用props之前先检查prop是否存在 | 可维护性 受支持性 |
手工 |
| Must | 调试信息 console.log() debugger使用完及时删除。 | 可维护性 受支持性 稳定性 |
手工+自动 |
| Must | 为v-for设置Key值。 |
可维护性 受支持性 |
自动 |
| Should | 无特殊情况不允许使用原生API操作dom,谨慎使用this.$refs直接操作dom。 | 可维护性 受支持性 |
手工 |
| Must | 使用ES6风格编码源码,定义变量使用let,定义常量使用const,使用export,import模块化。 | 可维护性 受支持性 易读性 |
手工 |
| Must | 指令缩写:都用指令缩写 (用 : 表示 v-bind: 和用 @ 表示 v-on:)。 | 可维护性 受支持性 易读性 |
手工 |
| Must | 使用 data 里的变量时请先在 data 里面初始化。 | 可维护性 受支持性 易读性 |
自动 |
| Must | 函数中统一使用_this=this来解决全局指向问题。 | 可维护性 受支持性 易读性 |
自动 |
| Must | 能用单引号不用双引号。 | 可维护性 受支持性 易读性 |
自动 |
| Must | 尽量使用===而不是==。 | 可维护性 受支持性 易读性 |
自动 |
| Must | 声明变量必须赋值。 | 受支持性 | 自动 |
7.Style
| 约束性 | 规范 | 质量标准 | 审查 |
|---|---|---|---|
| Must | 使用 scoped关键字,约束样式生效的范围。 | 可维护性 受支持性 易读性 |
手工 |
| Must | 避免使用标签选择器(效率低、损耗性能)。 | 可维护性 受支持性 易读性 |
手工 |
| Must | 非特殊情况下,禁止使用 ID 选择器定义样式。有 JS 逻辑的情况除外。 CSS 属性书写顺序:先决定定位宽高显示大小,再做局部细节修饰!推荐顺序:定位属性(或显示属性,display)->宽高属性->边距属性(margin, padding)->字体,背景,颜色等,修饰属性的定义。 |
受支持性 | 手工 |
8.注释规范
8.1使用范围
8.2使用方法
a) 单行注释:// 所有全局变量 data() | vuex等属性 Must
b) 多行注释:/ / 所有函数非生命周期函数 Must
/** 所有函数非生命周期函数 Must*/
4.JS注释:
a) 行级注释(注意//后面空格):// 正确的注释
b) 变量声明注释:如果是在类似 Vue 项目的 data 属性中的变量,直接用行级样式跟在后面。
例如:rightExample: ‘yes’, // 注释直接写这里Must
c) 如果是在类,构造函数,或者常量定义中的变量,使用块级注释。Must
/** 错误码常亮定义* @type {number}*/
d) 复杂的业务逻辑处理说明、特殊情况的代码处理说明,对于特殊用途的变量、存在临界值、使用了某种算法思路进行注释说明Must
9.资源路径的配置、引入规则
1.路径配置
在build/webpack.base.conf.js文件中配置。alias: {‘@’: resolve(‘src’), // 默认配置,设置src目录别名‘childRouter’: resolve(‘src/pages/menuRouter’), // 子路由路径配置‘#’: resolve(‘src/assets’) // 配置assets文件夹路径}
2.路径导入
a) Js文件中导入实例:
| 约束性 | 规范 | 质量标准 | 审查 |
|---|---|---|---|
| Must | 导入node_modules模块中的文件,直接引入即可,不需要加文件后缀名。 | 受支持性 | 自动 |
| Must | 导入自定义文件的时候,使用相对路径或者使用路径配置别名,不许要加文件后缀名。 | 受支持性 | 自动 |
| Must | 导入node_modules模块:import Vue from ‘vue’ | 受支持性 | 自动 |
| Must | 导入自定义文件:import router from ‘./router’import scrollConfig from ‘#/js/vuescroll.config’ | 受支持性 | 自动 |
b) css或者stylus样式导入需要使用 ~@ 开头
@import ‘~common/stylus/variable’
10.数据中心
| 约束性 | 规范 | 质量标准 | 审查 |
|---|---|---|---|
| Should | 各个文件的命名根据上面的项目结构命名。 | 可维护性 易读性 |
手工 |
| Should | 应用层级的状态应该集中到单个 store 对象中。 | 可维护性 易读性 |
手工 |
| Should | action和mutation中的函数统一声明在mutation-type.js内。 | 可维护性 易读性 |
手工 |
| Should | mutation-types里面的常量、常量值全部用大写+英文单词配合下划线的形式:例如:export const UPDATE_USERINFO = “UPDATE_USERINFO”。 | 可维护性 易读性 |
手工 |
| Should | 提交 mutation 是更改状态的唯一方法,并且这个过程是同步的。 | 可维护性 易读性 |
手工 |
| Should | 异步逻辑都应该封装到 action 里面。 | 可维护性 易读性 稳定性 受支持性 |
手工 |
| Should | vuex 的dispatch和commit提交mutation的区别:dispatch=>actions用来触发异步操作,commit=>mutation用来触发同步操作的方法。当操作行为中含有异步操作,比如向后台发送请求获取数据,就需要使用action的dispatch去完成,其他使用commit即可。 | 可维护性 易读性 稳定性 受支持性 |
手工 |
11.路由
1.路由至少包含三个选项:path、name、component。path统一小写;name对应于组件中的name,大写开头驼峰;component组件名称大写开头的组件驼峰。
{path: '/',name: 'HelloWorld',component: HelloWorld}
2.一级路由统一使用相对路径的形式。二级路由可以配置,配置见资源路径的配置、引入规则。
{path: '/',name: 'HelloWorld',component: HelloWorld,children:[{path:'/detail',name:'Detail'component:Detail,}]}
12.axios
| 约束性 | 规范 | 质量标准 | 审查 |
|---|---|---|---|
| Must | 根据需要配置post、get请求,一个是取一个是贴,只需要读取文件,put(PUT 往服务器上上传文件)、delect(删除)直接对数据进行操作相对不安全 。 | 安全性 | 手工 |
| Should | axios的挂载:Vue.prototype.$http = axios; | 可维护性 易读性 稳定性 受支持性 |
自动 |
| Should | axios使用封装后的get/post请求。 | 可维护性 易读性 稳定性 受支持性 |
自动 |
| Should | ajax的判断 首先 ajax 请求可以写在 actions也可以直接写在 .vue 页面里。 我们判断的依据是回调是否需要调用页面结构来区分, 比如在.vue页面中发送完请求后需要调用 this.$refs.element等,或者需要利用组件的独立性的效果时 后,那就写在.vue页面,否则就写在 actions 里。 |
可维护性 易读性 稳定性 受支持性 |
自动 |
13.api管理
- 新建src/ network/api.js
放置api路径,要注意 axios已经有了前缀,所以这里的 api 值需要写前缀之后的路径。当路径较多时可以再多建几个文件,分类放置。
例如:// 统一管理接口export default {manage: {fertilizerStation: '/api/AllFertSiteNameList', // 获取列表userLogin: '/api/Login' // 用户登录}}
2.挂载
在main.js中引入:import api from ‘./request/api’。
使用Vue.prototype.api = api挂载到原型链上即可处处使用。
14.依赖规范
- 在package.json里增加包依赖
“dependencies”: {"axios": "^0.18.0"}
15.Web字体规范
| 约束性 | 规范 | 质量标准 | 审查 | | —- | —- | —- | —- | | Should | 优先使用框架中的字体图标,比如element ui中的 | 稳定性 | 手工 | | Should | 使用iconfont字体图标代替图片
woff: WOFF (Web Open Font 格式)
ttf: TrueType
ttf, otf: OpenType
eot: 嵌入式 OpenType
svg, svgz: SVG 字体 | 稳定性 | 手工 | | Must | 字体规则
a) 为了防止文件合并及编码转换时造成问题,建议将样式中文字体名字改成对应的英文名字,如:黑体(SimHei)、宋体(SimSun)、微软雅黑(Microsoft Yahei)。
b) 字体粗细采用具体数值,粗体bold写成700,正常normal写成400。
c) font-size必须以px为单位。
为了对font-family取值进行统一,更好的支持各个操作系统上各个浏览器的兼容性,font-family不允许在业务代码中随意设置。 | 稳定性 | 手工 |
16.各类符号规范
双引号“ “ 中用单引号 ‘ ‘ 可以不用加反斜杠,例如:
var x="my name 'is' xxx" // 此处不需要加反斜杠
双引号“ “ 中用双引号 “ “ 需要加反斜杠,例如:
var x="my name \"is\" xxx" // 此处需要在两个上引号前各加一个加反斜杠
单引号 ‘ ‘ 中用双引号“ “ 不需要加反斜杠,当然加了也可以,例如:
var x1 ='my name "is" xxx' // 此处不需要加反斜杠(推荐)var x2 ='my name \"is\" xxx' // 添加反斜杠效果也一样(不推荐)
反引号:ES6 模板字符串(Template String)是增强版的字符串,用反引号(`)标识,它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量。
// 字符串中嵌入变量var name = "Bob", time = "today";`Hello ${name}, how are you ${time}?`
| 约束性 | 规范 | 质量标准 | 审查 |
|---|---|---|---|
| Shuold | 左大括号前不换行有空格; | 易读性 受支持性 |
手工 |
| Shuold | 左大括号后换行 | 易读性 受支持性 |
手工 |
| Shuold | 右大括号前换行 | 易读性 受支持性 |
手工 |
| Shuold | 右大括号后还有else等代码则不换行 | 易读性 受支持性 |
手工 |
| Shuold | 表示终止的右大括号后必须换行。 | 易读性 受支持性 |
手工 |
| Shuold | 左右小括号与中间字符之间不出现空格 | 易读性 受支持性 |
手工 |
| Shuold | 逗号:同行逗号后面加空格以隔开 | 易读性 受支持性 |
手工 |
17.命名规范
17.1组件命名
- 有意义的: 不过于具体,也不过于抽象
- 简短: 2 到 3 个单词
- 具有可读性: 以便于沟通交流
注意事项
<!-- 推荐 --><app-header></app-header><user-list></user-list><range-slider></range-slider><!-- 避免 --><btn-group></btn-group> <!-- 虽然简短但是可读性差. 使用 `button-group` 替代 --><ui-slider></ui-slider> <!-- ui 前缀太过于宽泛,在这里意义不明确 --><slider></slider> <!-- 与自定义元素规范不兼容 -->
17.2命名规则
- 常量大写
- 避免单字母命名。命名应具备描述性。
【强制】代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式。
// badfunction q() {// ...stuff...}// goodfunction query() {// ..stuff..}
使用驼峰式命名对象、函数和实例。
// badconst OBJEcttsssss = {};const this_is_my_object = {};function c() {}// goodconst thisIsMyObject = {};function thisIsMyFunction() {}
17.3函数注释规范
函数描述使用
description- 参数使用
param - 注明返回的类型和值
- 公共组件使用说明
- 各组件中重要函数或者类说明
- 复杂的业务逻辑处理说明
- 特殊情况的代码处理说明,对于代码中特殊用途的变量、存在临界值、函数中使用的 hack、使用
- 了某种算法或思路等需要进行注释描述
- 多重 if 判断语句
- 注释块必须以/(至少两个星号)开头/
- 单行注释使用//
```javascript
/**
- @description post请求不进行result过滤
- @param {string} url 请求的url
- @param {string} body 请求体
- @param {boolean} isUserId 是否需要userid
- 返回rxjs流
*/
postRxNormal(url?: string, body: any = {}, isUserId: Boolean = true ): Observable
{ if (isUserId) { body[‘user_id’] = this.storage.getStorage(‘user_id’); } return this.httpClient.post(url, body); }
/**
- @description 设置 localStorage
- @param value 需要存的值
- @param key 需要存key名字
*/
setStorage(value: any, key: string) {
try {
// 把里面的值转换成json对象
value = JSON.stringify(value);
} catch (e) {
// 抛出一个错误
value = value;
}
this.store.setItem(key, value);
}
```
17.4 变量命名
- 对所有的引用使用 const ;不要使用 var。
- 如果你一定需要可变动的引用,使用 let 代替 var。
17.5对象
17.5.1使用字面值创建对象。
// badconst item = new Object();// goodconst item = {};
17.5.2使用对象方法的简写。
// badconst atom = {value: 1,addValue: function (value) {return atom.value + value}};// goodconst atom = {value: 1,addValue(value) {return atom.value + value},}
17.5.3使用对象值的简写
const lukeSkywalker = 'Luke Skywalker'// badconst obj = {lukeSkywalker: lukeSkywalker,}// goodconst obj = {lukeSkywalker}
17.6.字符串
- 字符串连接使用模板字符串
// badfunction sayHi(name) {return 'How are you, ' + name + '?';}// badfunction sayHi(name) {return ['How are you, ', name, '?'].join();}// goodfunction sayHi(name) {return `How are you, ${name}?`;}
17.7函数
- 全部函数 第一个名称全部是动词
- 使用函数声明代替函数表达式。
// badconst foo = function () {};// goodfunction foo() {}
17.8构造器
- 总是使用 class。避免直接操作 prototype
// badfunction Queue(contents = []) {this._queue = [...contents]}Queue.prototype.pop = function() {const value = this._queue[0]this._queue.splice(0, 1)return value}// goodclass Queue {constructor(contents = []) {this._queue = [...contents]}pop() {const value = this._queue[0]this._queue.splice(0, 1)return value}}
18 设计规范
严格遵循阿里 Ant Design 设计规范 建议使用 Ant Design For Vue Should
