前端代码规范 --代码规范篇

4,898 阅读11分钟
版本修改时间修改人修改内容
v1.02022/09/19Tao出版创建

引言

1.1 目的

规范的目的是为了编写高质量的代码,提高代码质量和可读性,增强团队协作开发效率,统一编码风格规范

1.2 文档说明

本文旨在统一团队前端代码规范,参考腾讯、百度、字节跳动等前端规范,结合团队日常业务需求以及团队日常开发过程中的总结而制定,如果发现错误敬请指正~

HTML规范

2.1 用法规范

  1. 语义化标签

标签语义化,切忌清一色的 div 元素。列表可以使用 ul li,文字使用 p 标签,标题使用 h* 标签,等等。 HTML5 推出了语义化的标签,建议使用:section,aside,header,footer,article,等 HTML5 布局标签。

  1. 自定义标签

使用自闭标签的写法,如下

<my-owner-components />
  1. 多特性分行写

为提高可读性,组件应用时换行,按照ref、class、传入、传出顺序书写,如下:

<template>
  <scroll
    ref="scrollWrap"
    class="home-scroll-warp"
    :data="homeData"
    :pullDownRefresh="true"
    :pullUpLoad="true"
    @pullingDown="pullingDownGetNewData"
    @pullingUp="pullingUpGetMore"
  />
</template>
  1. 使用表达式

在模版中使用表达式,复杂情况使用计算属性或函数,如下:

<template>
  <div v-show="getLimitData(data)">
   ...
  </div>
</template>

methods: {
  /**
  * ***显示判断
  * @param data **
  */
	getLimitData(data) {
    return data.type !== 'dir' && ...
  }
}
<template>
  <div v-show="data.type !== 'dir' && dzqz && hasBtn  && attrs.mode !== 'ended'">
   ...
  </div>
</template>
  1. 避免重复

避免过多重复代码,如果超过三行类似的代码,配置数据再循环遍历

  1. 代码嵌套

根据元素嵌套规范,每个块状元素独立一行,内联元素可选,如下:

<div>
  <h1></h1>
  <p></p>
</div>	
<p><span></span><span></span></p>
<div>
  <h1></h1><p></p>
</div>	
<p> 
  <span></span>
  <span></span>
</p>
  1. 活用v-show,v-if
  • v-show不会改变dom树,也就是说不会导致重排。
  • v-if会改变dom树,会导致重排。

2.7 注释规范

<!-- test注释 -->
<div class="test">
  <!-- 组件注释 -->
  <gdCustomTable ref="gdCustomTable"  />
  <!-- 其他注释 -->
	<div>...</div>
</div>
<div>...</div><!-- 注释1 -->	
	
<div><!-- 注释2 -->
    ...
</div>

CSS规范

css部分,因为样式有原生的 CSS 写法,也有使用预处理语言:Sass, Less,Stylus。所以情况比较多,也比较复杂。我们统一使用 Sass

3.1 用法规范

  1. 避免:
  • 避免使用标签选择器。因为在 Vue 中,特别是在局部组件,使用标签选择器效率特别低,损耗性能,建议需要的情况,直接定义 class;
  • 非特殊情况下,禁止使用 ID 选择器定义样式。有 JS 逻辑的情况除外;
  • 避免使用important选择器;
  • 避免大量的嵌套规则,控制在3级之内,对于超过4级的嵌套,考虑重写或新建子项;
  • 避免使用ID选择器及全局标签选择器防止污染全局样式;
  1. 推荐使用
  • 提取公用样式进assets文件styles里,按模块/功能区分;
|assets
|-- styles
|   |-- common          放置公用样式,如重置,混合,复写element样式等
|   |-- modules         放置模块样式
  • 推荐使用直接子选择器;
/* 推荐 */
.jdc {}
.jdc li {}
.jdc li p{}

/* 不推荐 */
*{}
#jdc {}
.jdc div{}
  • 使用 scoped 关键字,约束样式生效的范围
<style lang="scss" scoped>
.app-wrapper {
  ...
}
</style>
  • 使用变量

可复用属性尽量抽离为页面变量,易于统一维护

// CSS
.class-name {
    color: red;
    border-color: red;
}

// SCSS
$color: red;
.class-name {
    color: $color;
    border-color: $color;
}
  • 使用混合(mixin)

根据功能定义模块,然后在需要使用的地方通过 @include 调用,避免编码时重复输入代码段

// CSS
.jdc_1 {
    -webkit-border-radius: 5px;
    border-radius: 5px;
}
.jdc_2 {
    -webkit-border-radius: 10px;
    border-radius: 10px;
}

// SCSS
@mixin radius($radius:5px) { // 当前代码可写入公用样式库mixin文件中
    -webkit-border-radius: $radius;
    border-radius: $radius;
}
.jdc_1 {
    @include radius; //参数使用默认值
}
.jdc_2 {
    @include radius(10px);
}

3.2 书写顺序

CSS 属性书写顺序:先决定定位宽高显示大小,再做局部细节修饰,推荐顺序:

定位属性(或显示属性,display)->宽高属性->边距属性(margin, padding)->字体,背景,颜色等,修饰属性的定义,这样定义为了更好的可读性,让别人只要看一眼就能在脑海中浮现最终显示的效果。

    1. 布局定位属性:display / position / float / clear / visibility / overflow
    2. 自身属性:width / height / margin / padding / border / background
    3. 文本属性:color / font / text-decoration / text-align / vertical-align / white- space / break-word
    4. 其他属性(CSS3):content / cursor / border-radius / box-shadow / text-shadow / background:linear-gradient …

以下给出常用的定义示例:

.class-name {
  position: fixed;
  top: 100px;
  left: 0;
  right: 0;
  bottom: 0;
  display: block;
  width: 100%;
  height: 100%;
  margin: 10px;
  padding: 10px;
  font-size: 14px;
  color: #000;
  background-color: red;
  border-radius: 2px;
  line-height: 1.42;
}

3.3 样式覆盖

组件内部需要覆盖UI框架样式,必须在最外层组件加类名,如下:

<template>
  <div class="input-area-container">
    <el-input class="name-input"></el-input>
  </div>
</template>

<script>
export default {}
</script>

<style lang="scss">
.input-area-container {
  .name-input {
    .el-input__inner {
      font-size: 16px;
    }
  }
}
</style>

3.4 注释规范

以/ 注释内容 /格式注释,前后空格,嵌套子类需要一个回车分割开

/* 注释内容 */
.pha-element {
    width: 20px;
		/* 这里需要换行 */
    .pha-element-l {
      color: blue
    }
}

JS规范

4.1 用法规范

  1. 在vue-cli 脚手架使用架自带的指向 src 开发目录的 '@' 符号引入文件资源;
  2. 使用计算属性规避 v-if 和 v-for 用在一起;
  3. 统一使用单引号;
  4. 坚持单一原则,函数内仅做该函数应该做的,尽量避免通过传入标记控制不同行为;
  5. 优先考虑三目运算符,但谨记不要写超过3层的三目运算符;
  6. 对于无用代码必须及时删除,例如:一些调试的 console 语句、无用的弃用功能代码,如在开发分支可提交打印代码,但要注意打印格式,如下:
// 推荐
console.log('路由': 文件路由, '打印简述': 打印数据)

// 不推荐
console.log(打印数据, '1111')
  1. 条件语句避免负面条件,特指调用某一函数;
// 推荐
function isUserNotBlocked(user) {
  // ...
}

// 不推荐
if (!isUserNotBlocked(user)) {
  // ...
}
  1. 请求数据的方法,使用try catch 错误捕捉,注意执行回调;
/**
 * 接口请求
 * @param req 接口api
 * @param params 参数
 */
async httpInterface(req, params) {
  try {
    this.loading = true
    const res = await req(params)
    return Promise.resolve(res)
  } catch (e) {
    return Promise.reject(e)
  } finally {
    this.loading = false
  }
}

// 使用
this.httpInterface(req, {}).then((resove, reject) => {
  console.log(resove, reject)
})

4.2 组件选项

根据官方的推荐按照以下定义,按照一下顺序,每个组件推荐使用

<script>
  export default {
    name: 'ExampleName',  // 这个名字推荐:大写字母开头驼峰法命名。
    props: {},            // Props 定义。
    components: {},       // 组件定义。
    directives: {},       // 指令定义。
    mixins: [],           // 混入 Mixin 定义。
    data () {              // Data 定义。
      return {
        dataProps: ''     // Data 属性的每一个变量都需要在后面写注释说明用途,就像这样
      }
    },
    computed: {},         // 计算属性定义。
		watch: {},            // 属性变化监听器。
    created () {},         // 生命钩子函数,按照他们调用的顺序。
    mounted () {},         // 挂载到元素。
    activated () {},       // 使用 keep-alive 包裹的组件激活触发的钩子函数。
    deactivated () {},     // 使用 keep-alive 包裹的组件离开时触发的钩子函数。
    methods: {            // 组件方法定义。
      publicbFunction () {}  // 公共方法的定义,可以提供外面使用
      _privateFunction () {} // 私有方法,下划线定义,仅供组件内使用。多单词,注意与系统名字冲突!
    }
  }
</script>

4.3 注释规范

函数/方法注释必须包含函数说明,有参数和返回值时必须使用注释标识,它的作者, 依赖关系和兼容性信息。

  1. 单行注释:双斜线后应跟空格,且缩进与上下文的代码保持一致;或在行尾注释,在行尾依然需要左右空格;
 // 一些说明...
const userID = 24;
const userID = 12; // 一些说明
  1. 多行注释:一般用于注释难以理解的、可能存在错误的、逻辑强的代码,且缩进一致;
/*
 * 针对下方代码的说明
 * 第一行太长写第二行
 */
const a = 1
  1. 函数注释:写明传入参数名称,类型,推荐完整注释以下格式;
/**
 * @Description 加入购物车
 * @Author lint 
 * @Date 2020-09-08 
 * @param {Number} goodId 商品id
 * @param {Array<Number>} specs sku规格
 * @param {Number} amount 数量
 * @param {String} remarks 备注
 * @returns <Promise> 购物车信息
 */
apiProductAddCard = (goodId, specs, amount, remarks) => {
  return axios.post('***', { goodId, specs, amount, remarks })
}

/**
 * @Description 根据字典编码获取选项名称
 * @Author lint
 * @Date 2020-09-08
 * @param {String} key 编码
 * @param {String} val 值
 * @returns {String} 字典名称
 */
getDictText(key, val) {
  const item = this.dictData[key].find(k => k.dictKey === val)
  return item ? item.dictValue : ''
}
  1. 文件注释;
/**
 * @Description: 文件名称
 * @Author:	lint
 * @Date: 2020-09-08
 */

命名规范

6.1 目录命名

按照小驼峰命名,首字母小写

  • 项目文件夹:projectName
  • 样式文件夹:css / scss
  • 脚本文件夹:js

6.2 图片命名

图片使用img,图标使用icon

  • img_功能/类型_编号
  • icon_功能/类型_编号

6.3 文件命名

  1. 按照小驼峰命令,英文单词过长或超出2个以上,可缩略至前四位,如
// 业务统计
approvalStatistical

// 缩略
approvalStat
  1. 有复数含义,采用复数命名,如
pages, componets, filters, mixins ,images
  1. 存放 images, styles, icons 等静态资源,静态资源命名格式为小写+中划线,如
|assets
|-- icons
|   |-- icon-label-red.png
|-- images
|   |-- img_background-color.png
|   |-- img_company-logo.png
|-- styles
  1. 组件进行目录划分,目录命名为小驼峰,公用组件加上gd前缀,如
|components
|-- gdCustomCheck
|   |-- index.vue
|-- gdCustomTable
|   |-- index.vue

6.4 方法命名

method 方法命名不同于文件命名,尽量完整英文命名,语义表达需完整清楚

  1. 按照小驼峰命名法,可使用常见动词约定;
  • can 判断是否可执行某个动作,函数返回一个布尔值。true:可执行;false:不可执行
  • has 判断是否含有某个值, 函数返回一个布尔值。- true:含有此值;false:不含有此值
  • is: 判断是否为某个值,函数返回一个布尔值。true:为某个值;false:不为某个值
  • get: 获取某个之,函数返回一个非布尔值
  • set: 设置某个值,无返回值、返回是否设置成功或者返回链式对象 load 加载某些数据,无返回值或者返回是否加载完成的结果
  1. 语义化英文命名,仅组件内部使用方法前加上_(下划线)区分,如下
<script>
  export default {
    methods: {            // 组件方法定义。
      publicbFunction () {}  // 公共方法的定义,可以提供外面使用
      _privateFunction () {} // 私有方法,下划线定义,仅供组件内使用。多单词,注意与系统名字冲突!
    }
  }
</script>
  1. 引入组件:首字母大写的驼峰法命名。推荐使用 ES6 的方式引入
import Article from 'xxx'
import ArticleDetail from 'xxx'
  1. 变量:使用驼峰式命名,优先使用letconst、避免使用var
let userName = 'luffy'
const userInfo = {
  name: 'luffy'
}
  1. 常量:字母全部大写,以下横线_划分
const Api = {
  ITEMS_OFONE_TYPE = '***', // 获取事项分类
  SOLUTION_LIST = '***',, // 获取事项列表
}

6.5 样式命名

class命名以小写字母开头,小写字母、中划线和数字组成。不建议使用驼峰法命名 class 的属性。以下是一些常用到的 class的名字:

  • 包裹层: .xx-wrap;
  • 列表: .xx-list;
  • 列表项: .xx-list-item; 
  • 左边内容: .xx-left; 
  • 中间内容: .xx-middle; 
  • 右边内容: .xx-right; 
  • 某个页面: .xx-page;

6.6 常用词

  1. 常用动词
简写说明
get\set取值\给值
add\remove增加\移除
show\hide显示\隐藏
view查看
browse浏览
edit修改
save保存
delete删除
find查询
undo撤销
redo重做
clean清除
index索引
observe观察
send\receive发送\接收
refresh\synchronize刷新\同步
  1. 常用缩写
数据类型/标签简写后缀
objectobj
arrayarr
jsonjson
functionfn
messagemsg
buttonbtn

工程结构

7.1 思维导图

7.2 目录构建

|-- api                              所有api接口
|   |-- https                           封装的公用请求方法,除非必要不可修改,影响全局
|-- assets                           静态资源,images, icons, styles等
|   |-- images                       全局公用图片
|   |-- icons                        全局公用icons
|   |-- styles                       全局公用样式
|-- components                       公用组件
|   |-- base                           基础组件,导航,按钮,标签等组件
|   |-- business                       业务组件,封装可复用的页面或功能组件
|-- constants                        常量管理
|-- plugins                        	 插件管理
|-- router                           路由,统一管理
|-- store                            vuex, 统一管理
|-- utils                            工具管理
|   |-- utlis                          公共 JS 工具函数
|   |-- array                          数组类工具函数
|   |-- store                          存储类工具函数
|   |-- filters				                 过滤器工具函数
|   |-- ...				                 
|-- views                            视图目录(所有业务逻辑的页面)

7.3 文件说明

  1. views里每个模块文件夹,都建一个文件说明,说明该视图模块;
  2. api文件内采用ts写法,其中加入类型推断model,写清接口参数及参数类型;
  3. api中的方法名字要与后端api, url尽量保持语义高度一致;
/**
 * @desc 业务审批模块接口
 * @desc model文件定义类型检测
 * @desc get/post方式请求 url请求地址 prefix地址前缀-默认值 prefix
 * @desc Content-Type 配置json为true, 值为application/json, 配置text为true, 值为text/plain
 */
import { get, post } from '../https'
import model from './model.ts';

enum Api {
  MY_SOLUTIONS_API = '/task/mySolutions', // 事项查询
}

export const getMySolutionsData = (params) => get({ url: Api.MY_SOLUTIONS_API, params })
  1. 提交代码时候要把断点,打印等删除;
  2. 文件、变量命名要尽量与后端保持一致;
  3. 无特殊情况统一用以下插件/工具/库,如需引用其他库,统一放置plugins文件内,注意按需引入;
  • element UI框架
  • sass css预处理器

7.4 代码风格

Eslint是识别和报告模式匹配的工具,它的目标是保证代码的一致性和避免错误,说白了就是用来检测代码风格的。 在中大型项目中对维护项目的规范性、健壮性、可读性尤其有用。VueCLI 3 已经整合ESLint 与著名的Airbnb JavaScript Style Guide,只要跟着Vue CLI 3 的Wizard,我们也能轻易地将ESLint 与Airbnb 整进Vue 方案中。

  1. 依据以下三条原则,可以依据ESLint 所有的配置项,定制出了ESLint 配置,原则上是对开发有益的都要开启。
  • 能够帮助发现代码错误的规则,全部开启
  • 配置不应该依赖于某个具体项目,而应尽可能的合理
  • 帮助保持团队的代码风格统一,而不是限制开发体验
  1. 接入项目的方法
  • 在vscode中安装Eslint 和Prettier 两个插件
  • 执行npm install husky lint-staged eslint eslint-plugin-vue

Git规范

目前按照我们正常开发的项目,master分支作为主干分支,及生产环境,多人协同开发时一定要按照分支规范去建立和提交分支,具体如下:

8.1 分支说明

  • master分支:主干分支,与线上正式版本保持一致
  • dev分支:开发分支,始终与master分支保持一致
  • feature分支:版本开发分支(多个)
  • test分支:版本测试分支(多个,对应feature)
  • release分支:预发布分支
  • bug分支

8.2 分支关系

8.3 使用说明

  • 多人在同一个分支上开发时,分支名称可按照版本号命名,注意记录版本号对应功能点;
  • dev分支可提交打印说明,注意打印说明格式,其他分支不可提交;
  • 提交时尽量书写提交代码修改的地方或功能,不要提交无用信息;

8.4 附件