前端团队代码规范

前言

代码的最终归宿都是屎山罢了,而一份适用于团队的代码规范,可以极大延缓屎山的堆积速度。

文中部分标注了删除线的,代表eslint已开启了相关配置,vscode会自动做出提示。

本文在线 思维导图 地址

项目工程规范

在这里插入图片描述
上图是整体项目目录,对于有点经验的正常前端开发人员,讲道理看文件名字应该都能基本理清用途。所以对我们团队内部的项目工程规范来说,将着重于文件命名规范和存在位置。

1、项目文件命名统一使用短横线分隔

2、对于.vue文件要求使用关注点分离,对页面进行拆分

使用 vue-generate-component 插件,在控制台执行ovgc demo-page,将自动创建如下文件
插件地址 fork自 地址

无css样式时,删除scss文件,无单元测试时,删除spec文件。
在这里插入图片描述

3、针对所有项目中涉及到的请求,统一封装成服务,按照功能模块命名,放在src/api文件目录下

在这里插入图片描述

  • 对于服务命名要求词尾统一加Serivce
  • 统一在src / api / index.ts文件中 export
  • 统一从 ‘@/api’ 下 import
    在这里插入图片描述

4、公共的过滤器和指令放在src文件下对应的文件夹中,按功能进行命名,中间以短横线分隔,在index.ts文件中统一 export (在main.ts中会统一注册)

5、公共的mixin放在src/mixins中,按功能进行命名,中间以短横线分隔,特殊业务下的mixin可放在具体使用的位置,后缀加mixin用来做区分

6、特殊工具类放在src/utils文件夹下,公共工具类放在src/utils/index中

使用时,公共方法统一从 '@/utils’中 import

import { fuzzyQueryStr } from '@/utils';

而特殊工具类,从各自所属位置import

import { axiosRequest } from '@/utils/axios-request';

7、路由按照模块进行区分,放在src/router/modules文件夹中

8、vuex按照大模块进行拆分,放在src/store/modules文件夹中,另外仓储服务输出时,要求使用大驼峰命名,与一般的服务类进行区分。

export const PermissionModule = getModule(Permission);

9、i18n翻译文件,以资源对象进行分割,该对象所有相关的文案都放在该对象下,不允许有重复的文案出现

以项目为例,所有与项目相关的文案都放在project 对象内。
在这里插入图片描述

10、所有业务相关的页面存放在views文件夹下,按大模块建立对应的文件夹

在这里插入图片描述

11、 声明的每个属性、方法之间要间隔一行

在这里插入图片描述

js规范

1、命名

1.1、变量和方法名使用小驼峰命名,禁止使用短横线或下划线
1.2、对于复杂的事件回调处理,方法名前统一使用handle前缀,如果功能单一,可以酌情使用功能用途命名
// 单一功能 
<button @click="goBack"> 返回上一页 </button>
// 复杂功能 - 需要对子组件emit的change事件做出响应
<xxx-page @change="handleXXXChange"></xxx-page>
1.3、一个好的命名,应该是能让别人一眼就看出用途的,所以请根据你的目的进行命名,如果转化为英文后名字过长,可酌情使用简写

2、注释

对于注释,我的理解是注释在于而精不在于多,注释并不是越多越全就越好,因为写注释会耗费部分时间,且后续逻辑出现变化,还需要对注释进行维护更新,如果只更新了逻辑而忘记更新注释,那将是毁灭性的灾难,后面其他人看到这段驴头不对马嘴的代码和注释,一头雾水还要根据git记录跑来问你,这会耗费更多的时间。

因此对于一部分不太复杂的逻辑,完全可以通过优秀的变量或方法命名,让人在阅读时迅速理解这段代码的用途。当你自己在写这块代码时,都觉得业务难易理解或代码难以组织时,请务必加上注释

2.1、对于逻辑较复杂的代码,首先应在复杂代码块初始位置,写出本段逻辑处理的目的,然后针对复杂点逐行写出逻辑处理原因
2.2、当写有注释的代码发生变化时,务必要检查对应的注释,并同步修改
2.3、对于代码行的注释使用双斜 // 即可,对于方法务必使用 /**/,并对出入参和出参做出注释
  /**
   * 检查项目名称是否重复
   * @param name 项目名称
   * @param customerId 客户主键
   * @param id 项目主键(修改项目时需要传入该参数)
   * @returns 返回true则代表重复
   */
  public checkProjectName(name: string, customerId: number, id?: number): Promise<boolean> {}

3、变量声明

3.1、禁止使用var,用let和const替代

对于数组和对象或其他引用类型,后续不影响引用地址的情况下,允许使用const定义

3.2、非必要情况下,不要定义临时变量
3.3、定义对象时,请使用对象属性值的简写方式
const job = 'FrontEnd'
// bad
const item = {
  job: job
}
// good
const item = {
  job
}
3.4、变量不要进行链式赋值,会污染全局变量
// bad
(function example() {
  // let 关键字只适用于变量 a; 变量 b 和 c 变为全局变量
  let a = b = c = 1
}())
console.log(a) // ReferenceError
console.log(b) // 1
console.log(c) // 1

// good
(function example() {
  let a = 1
  let b = a
  let c = a
}())
console.log(a) // ReferenceError
console.log(b) // ReferenceError
console.log(c) // ReferenceError
3.5、不允许出现未被使用的变量

4、模块化

4.1、请使用标准的 ES6 模块语法 import 和 export
4.2、同个文件每个模块只允许 import 一次,有多个 import 请书写在一起
// bad
import foo from 'foo'
// … some other imports … //
import { named1, named2 } from 'foo'
// good
import foo, { named1, named2 } from 'foo'

5、function

5.1、禁止修改传入的参数
5.2、一个方法的参数不能超过三个,当你发现参数过多时,应考虑拆分方法
5.3、禁止声明无用参数
5.4、可能为空的参数必须放在最后面
5.5、 不要使用 arguments,使用 剩余运算符
// bad
function test () {
  const args = Array.prototype.slice.call(arguments)
  return args.join('')
}
// good
function test (...args) {
  return args.join('')
}
5.6、当一个方法内的代码量很大时,可以考虑根据逻辑块进行拆分,每个逻辑块拆分成私有的小方法,以逻辑块的目的作为方法名

这样拆分后,别人看到的方法是非常干净的,且根据每个小方法的名字就可以快速的理解代码用途。

6、其他

6.1、句尾使用分号
6.2、拼接字符串时禁止使用+号,请使用模板字符串
6.3、判断时请使用( === )而非( == )
6.4、对象属性访问请使用obj.xxx,除非属性名是变量才允许使用obj[xxx]
6.5、尽量减少代码层级嵌套,当嵌套大于等于三层时,就该考虑优化代码逻辑了
// bad
if(xxx){
  do something1;
} else {
  do something2;
  if(xxx) {
    do something3;
  } else {
    do something4;
  }
}
// good
if(xxx){
  do something1;
  return;
}
do something2;
if(xxx) {
  do something3;
  return;
}
do something4;
6.6、优先使用promise,若非绝对必要,禁止使用回调函数
6.7、使用async和await语法糖时,必须使用try catch

ts规范

1、访问修饰符

1.1、在声明变量或方法时,针对该方法的目的,设置访问权限

使用方式参考 ts 官方文档

1.2、私有方法一般放在公有方法后面,属性声明放在公有方法前
  public selectedRows: Array<ProjectList> = [];
  
  private queryForm: Partial<ProjectListQuery> = {};
  
  public created(): void {
    
  }

  private clearSelection(): void {
  
  }
1.3、对于vue的prop,或inject,请使用readonly修饰

2、类型声明

2.1、类型声明文件后缀名为.d.ts,统一放在项目src/resource下面
2.2、类型统一使用大驼峰命名
2.3、要求以每个对象和具体功能为基础,建立该对象的相关操作的实体类,统一导出

以项目对象project为例,功能包含

  1. 列表页 ProjectList
  2. 分页查询条件检索 ProjectListQuery
  3. 新增、编辑 CreateProject,如果编辑只需要对少部分字段进行修改,则建立 UpdateProject
  4. 详情页展示 ProjectInfo

以上类型一般基于一个较为全面的基础类型,改造而来。ts提供了诸如使用Omit,Pick,Partial,Required关键字,对类型进行修改,从而获得一个新的类型。这样当字段发生变化时,只需使用vscode重构功能,对基础类型进行修改后,即可同步影响到所有相关的类型。

可根据实际情况,选择ProjectInfo或ProjectList作为基类,当都不满足条件时,可以选择声明ProjectBase类型抽取公共字段。

2.4、对于每个类型和属性声明,必须具有注释
2.5、对于数组的定义,使用泛型方式
// good 
const arr: number[] = [1, 2, 3];
// best
const arr: Array<number> = [1, 2, 3];

3、function

3.1、必须具有返回类型
3.2、参数必须具有类型声明
3.3、必须具有访问修饰符
 public xxx(): void {
   do something;
 }
 protected xxx(): boolean {
   return true;
 }
 private xxx(): string {
   return 'xxxxxx';
 }
 public xxx(): 其他支持的类型 {
    return 其他支持的类型
 }

4、其他

4.1、若非必要,禁止使用any类型
4.2、枚举必须具有注释,且后缀名必须为Enum

枚举对应的i18n翻译,一般以枚举名,去掉Enum后缀,然后以小驼峰命名,例如ProjectStatusEnum,代表项目状态枚举类

/**
 * 项目状态
 */
export enum ProjectStatusEnum {
  /**
   * 新建
   */
  new = 1,
  ....
}

i18n文案为

projectStatus: {
    new: '新建',
    ...
  }

vue

1、模板文件

1.1 、组件模板应该只包含简单的表达式,复杂的表达式则应该重构为计算属性或方法。
// bad
<el-button size="small" @click="detailsVisible = false">关闭</el-button>

// good
<el-button size="small" @click="close">关闭</el-button>

// bad
 <span>{{ totalMoney * 2 }}</span>

// good 
 <span>{{ doubleMoney }}</span>

public close ():void {
  this.detailsVisible = false
}

public get doubleMoney(): number {
 return this.doubleMoney * 2
}

2、命名问题

2.1 、组件命名采用短横线命名法
2.2 、emit 事件单词之间使用 - 分隔,禁止使用驼峰
2.3 、组件传参时,标签上需要对使用了驼峰命名的prop,使用短横线命名

假如 B组件接收一个totalMoney,A组件传参时如下

// good
<b :totalMoney="123"></b>

// best
<b :total-money="123"></b>

// error
<b totalMoney="123"></b>

3、vuex

3.1、Mutation使用小驼峰命名,Action使用大驼峰

因为很多情况下,两者会因为目的相同,从而导致命名容易冲突,所以使用不同的命名方式作为区分
在这里插入图片描述

3.2、仓储的属性必须声明对应接口文件,且必须做出详细注释

在这里插入图片描述

4、其他

4.1 、设置prop时,必须填写options
  @Prop({ type: String, required: true })
  public readonly msg!: string;

  @Prop({ type: String, required: false, default:'' })
  public readonly msg!: string;
4.2 、生命周期函数统一放在业务代码前面
4.3 、更多请参照 vue风格指南

css

1、命名

1.1、使用短横线进行class命名

2、其他

2.1、多页面都用到的公共样式,禁止复制粘贴,必须放在src/style/index.scss中
2.2、注释使用单行注释

注释内容第一个字符和最后一个字符都是一个空格字符,单独占一行,行与行之间相隔一行

/* Comment Text */
.jdc{}

/* Comment Text */
.jdc1{}
2.3、scss可复用属性尽量抽离为变量,易于统一维护

…未完待续

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值