前端代码规范

最近组内经常进行CodeReview,于是参考一些大厂规范以及一些开源的优秀源码,整理了一些前端代码规范,帮助我们后续可以写出更好维护的代码。有什么不对的地方,欢迎大家指出,一起学习进步!

先来看下下面这张思维导图:

前端代码开发规范思维导图 (1).jpg

下面会就几个方面展开来说。

命名规范

驼峰式命名法介绍

  • Pascal Case大驼峰式命名法:首字母大写。eg:PersonInfo
  • Camel Case小驼峰式命名法:首字母小写。eg:PersonInfo

文件命名

  • 所有文件名统一使用小写,首页命名为index.xxx,文件名禁止特殊字符比如空格、$等。统一使用英文单词或拼音缩写,必须小写。( 为了醒目,某些说明文件的文件名,可以使用大写字母,比如README、LICENSE。 )
  • 文件名包含多个单词时,单词之间建议使用半角的连词线 ( – ) 分隔。
  • 文件目录结构嵌套层级不要过深

变量命名

命名方式 : 小驼峰式命名方法命名规范 : 类型+对象描述的方式,如果没有明确的类型,就可以使前缀为名词

表头 表头
array a
boolean b
function fn
int i
object o
regular r
string s

函数命名

命名方式 : 小驼峰方式 ( 构造函数使用大驼峰命名法 ) 命名规则 : 前缀为动词

动词 含义 返回值
can 判断是否可执行某个动作 ( 权限 ) 函数返回一个布尔值。true:可执行;false:不可执行
has 判断是否含有某个值 函数返回一个布尔值。true:可执行;false:不可执行
is 判断是否为某个值 函数返回一个布尔值。true:可执行;false:不可执行
get 获取某个值 函数返回一个非布尔值
set 设置某个值 无返回值、返回是否设置成功或者返回链式对象

例子:

// 是否可跳舞
function canDance(){
  return true;
}
​
// 获取工作
function getWork{
  return this.work
}

常量命名

命名方法 : 全部大写命名规范 : 使用大写字母和下划线来组合命名,下划线用以分割单词。

例子:

const PATH = "xxxx" 

类命名

  • 公共属性和方法 : 同变量命名方式
  • 私有属性和方法 : 前缀为下划线(_或#)后面跟公共属性和方法一样的命名方式

注释规范

单行注释和多行注释的空格保存代码时eslint会帮我们处理,不用手动加空格。

单行注释 ( // )

  • 单独一行://(双斜线)与注释文字之间保留一个空格
  • 在代码后面添加注释://(双斜线)与代码之间保留一个空格,并且//(双斜线)与注释文字之间保留一个空格。
  • 注释代码://(双斜线)与代码之间保留一个空格

多行注释 ( / 注释说明 / )

  • 若开始(/*和结束(*/)都在一行,推荐采用单行注释
  • 若至少三行注释时,第一行为/*,最后行为*/,其他行以*开始,并且注释文字与*保留一个空格。

函数(方法)注释

函数(方法)注释也是多行注释的一种,但是包含了特殊的注释要求

/** 
* 函数说明 
* @关键字 
*/

常用注释关键字

注释名 语法 含义 示例
@param @param 参数名 {参数类型} 描述信息 描述参数的信息 @param name {String} 传入名称
@return @param 参数名 {参数类型} 描述信息 描述返回值的信息 @param name {String} 传入名称
@author @author 作者信息 [附属信息:如邮箱] 描述返回值的信息 @author 李四 2022/12/16
@version @version XX.XX.XX 描述此函数的版本号 @version 1.1.1
@example @example 示例代码 描述此函数的版本号

文件目录结构

同功能放在同一个文件目录下,目录结构不要嵌套过深,文件名语义化一些,方便后续维护。

  • 文件夹名称全部采用小写+”-” 来隔开;
  • 避免多层嵌套,单个项目中的目录嵌套控制在最多三到四个层级内;

例子:

   - src 开发目录
      - pages 视图
          - module-a 模块A
            - components 私有组件
              - ComA.vue
              - ComB.vue
            - index.vue
          - module-b 模块B
      - components 公共组件
        - index.vue 导出所有组件
        - header
          - index.vue
      - utils 这里是以utils为后缀,JS工具库
        - index.js
        - a.utils.js
        - b.utils.js
      - hooks 这里是以hooks为后缀
        - index.js
        - a.hooks.js
        - b.hooks.js
      - service api请求,这里是以api为后缀
        - a.api.js 按照后端微服务进行划分
        - b.api.js
      - constans 常量

通过对工具函数、hooks、api等加上后缀,更加容易区分引入的文件。

代码规范

JS

JS/TS主流的大致有这几种:

可以参考star最多的进行配置,几乎覆盖了JavaScript的每一项特性。

下面会就代码层面作出阐述。

名称 说明
命名规范 1. 普通命名采用小驼峰式命名
2. 命名是复数的时候需要加s
3. 命名需要符合语义化,尽量减少缩写的情况发生,做到见名知意,如果函数命名,可以采用加上动词前缀
变量规范 1. ​​变量定义​尽量使用const、let
2. ​变量兜底
字符串 1. ​统一使用单引号而不是双引号,配置安装eslint后,保存会自动格式化处理
2. ​用字符串模板而不是’+’来拼接字符串
3. ​不要使用不必要的转义字符
4. ​不要在字符串中用eval(),漏洞太多
数组 1. 用扩展运算符(…)做数组浅拷贝
2. ​使用数组解构
对象 1. ​ES6 使用属性值缩写,​将属性的缩写放在对象声明的开头
2. ​对象浅拷贝时,更推荐使用扩展运算符 …使用对象解构
函数 1. ​函数参数使用默认值替代使用条件语句进行赋值
2. 函数参数越少越好,如果参数超过两个,要使用 ES6 的解构语法,不用考虑参数的顺序。把默认参数赋值放在最后
3. ​尽量使用箭头函数
4. ​用命名函数表达式而不是函数声明,​函数声明作用域会提升,降低了代码可读性和可维护性
5. ​不要改参数,不要对参数重新赋值
6. ​功能函数使用纯函数,输入一致,输出结果永远唯一
7. ​优先使用函数式编程
for循环 使用for循环过程中,数组的长度,使用一个变量来接收, ​有利于代码执行效率得到提高,而不是每走一次循环,都得重新计算数组长度

Vue

遵循vue.js官方风格指南,https://vuejs.bootcss.com/style-guide/

组件

名称 说明
组件命名 ​1. 组件名为多个单词,命名为组件用途,完整单词的组件名(倾向于完整单词而不是缩写)
​2. 文件名应该要么始终是单词大写开头 (PascalCase),要么始终是横线连接 (kebab-case),例如:todo-item或TodoItem
3. ​基础组件名, 应用特定样式和约定的基础组件 (也就是展示类的、无逻辑的或无状态的组件) 应该全部以一个特定的前缀开头,比如Base、App或V
4. ​单例组件名,只应该拥有单个活跃实例的组件应该以The前缀命名,以示其唯一性
5. ​紧密耦合的组件名, ​和父组件紧密耦合的子组件应该以父组件名作为前缀命名
6. 组件名中的单词顺序, 组件名应该以高级别的 (通常是一般化描述的) 单词开头,以描述性的修饰词结尾
7.模板中的组件名大小写,​对于绝大多数项目来说,在单文件组件和字符串模板中组件名应该总是PascalCase的——但是在DOM模板中总是kebab-case的
8. ​JS/JSX中的组件名大小写,JS/JSX 中的组件名应该始终是 PascalCase 的,尽管在较为简单的应用中只使用Vue.component进行全局组件注册时,可以使用kebab-case字符串
组件数据 ​组件的data必须是一个函数
props定义 ​​1. prop定义应该尽量详细 ​
2. prop名大小写,​在声明prop的时候,其命名应该始终使用camelCase,而在模板和JSX中应该始终使用kebab-case。
v-for使用 1. 为v-for设置键值,尽量避免使用index作为key ​
2. 避免v-if和v-for用在一起
样式 ​​为组件样式设置作用域,使用scoped属性,使用BEM约定
私有property名 1. Vue使用前缀来定义其自身的私有 property
2. 推荐使用$
,作为一个用户定义的私有property的约定,以确保不会和Vue自身相冲突
自闭合组件 在单文件组件、字符串模板和JSX中没有内容的组件应该是自闭合的——但在DOM模板里永远不要这样做
attribute 1. 多个attribute的元素应该分多行撰写,每个attribute一行 ​
2. 带引号的attribute值
模板中简单的表达式 组件模板应该只包含简单的表达式,复杂的表达式则应该重构为计算属性或方法
简单的计算属性 ​应该把复杂计算属性分割为尽可能多的更简单的property,计算属性不能产生副作用
指令 指令缩写 (用:表示 v-bind:、用@表示 v-on: 和用#表示 v-slot:)
组件通信 应该优先通过prop和事件进行父子组件之间的通信,而不是this.$parent或变更prop
事件、定时器 清除定时器或者事件监听
代码文件 开发过程中单个文件不允许超过600行,特别复杂的功能,文件不允许超过1000行

模板中的组件名大小写

PascalCase相比kebab-case有一些优势:

  • 编辑器可以在模板里自动补全组件名,因为PascalCase同样适用于JavaScript
  • 视觉上比 更能够和单个单词的HTML元素区别开来,因为前者的不同之处有两个大写字母,后者只有一个横线
  • 如果你在模板中使用任何非Vue的自定义元素,比如一个Web Component,PascalCase确保了你的Vue组件在视觉上仍然是易识别的

由于HTML是大小写不敏感的,在DOM模板中必须仍使用kebab-case。

例子:

<!-- 在单文件组件和字符串模板中 -->
<MyComponent/>
​
<!-- 在DOM模板中 -->
<my-component></my-component>
​
<!-- 在所有地方 -->
<my-component></my-component>

Prop名大小写

我们单纯的遵循每个语言的约定。在JavaScript中更自然的是camelCase。而在HTML中则是kebab-case。

文件目录

名称 说明
资源 资源统一放置在 assets 文件夹下,资源以文件夹组织,文件夹名称即模块名称
公共方法 放置在utils内部
样式 BEM命名规范

CSS

CSS检查代码规范

使用stylelint插件,规范则推荐使用stylelint-config-standard

下面简单说下stylelint-config-standard使用

1. 安装
yarn add -D stylelint stylelint-config-standard
​
2. 在项目的根目录中创建一个配置文件.stylelintrc.json,内容如下:
{
  "extends": "stylelint-config-standard"
}
​
3. 解决与prettier配置的冲突:
​
yarn add -D stylelint-config-prettier
​
4. 将下面配置复制到.stylelintrc.json中:
{
  "extends": ["stylelint-config-standard", "stylelint-config-prettier"]
}
​
5. 在 git commit 阶段进行检测:
 "lint-staged": {
    "**/*": "prettier --write --ignore-unknown", // 格式化
    "src/**.{js,jsx,ts,tsx}": "eslint --ext .js,.jsx,.ts,.tsx", // 对js文件检测
    "**/*.{less,css}": "stylelint --fix" // 对css文件进行检测
  },

BEM命名原则

  • block:模块,名字单词间用-连接
  • element:元素,模块的子元素,以__与block连接
  • modifier:修饰,模块的变体,定义特殊模块,以–与block连接

有效使用css选择器

有效使用css选择器,需遵循以下原则:

  • 保持简单,不要使用嵌套过多过于复杂的选择器,选择器嵌套应少于3级;
  • 通配符和属性选择器效率最低,需要匹配的元素最多,尽量避免使用;
  • 避免使用CSS表达式;
  • 慎重选择高消耗的样式(高消耗属性在绘制前需要浏览器进行大量计算),避免重绘重排;
  • ​css选择器中避免使用标签名;
  • ​尽量使用缩写属性;
  • ​使用子选择器;
  • 0后面不带单位;
  • id和class,命名​名称语义化,不要过于简单,防止模块之间样式互相影响;​​合理的使用id,​​一般情况下id不应该被用于样式,并且id的权重很高,所以不使用id解决样式的问题,而是使用class;

CodeReview常见代码问题汇总

类别 描述 说明
文件 命名 1. 组件命名规范,尽量不要和现有组件或远程组件重合,比如页面里使用组件时直接使用Table
2. 文件命名尽量语义化,如果没有定制化的,文件命名不要太定制化,比如文件命名直接是fifth-floor
3. 文件中变量/方法命名语义化,方法名格式统一
UI规范 删除按钮颜色 删除类的操作按钮颜色使用红色
vue 代码问题 1. 组件数据共享: 嵌套调用的组件声明一个方法,直接返回当前模块的数据,不要层层嵌套,通过$refs获取,比如:组件里定义一个getValues方法获取数据
2. 生命周期钩子:vue生命周期如果没有依赖关系的话,尽量不要用async/await,可以把请求封装成一个方法,生命周期中直接调用方法;如果有依赖关系的话就用,看场景
3. v-for中key值绑定,尽量不要绑定index,使用id,如果没有id且不涉及添加删除操作时,可以绑定index
4. 使用vue/composition-api时,相同变量以及方法考虑是否放在一起,方便看,看场景及个人习惯
5. 引入第三方工具包时尽量使用小的包,比如moment包换成dayjs
6. 使用动态路由(id)
7. 不建议this传递,问题排查容易出问题,即在其他页面修改this里的变量
JS 代码问题 1. map/forEach: 注意区分两者使用场景,不要随便使用
2. 常量:页面里使用多次的字符统一使用常量映射,不要直接在页面中使用字符
3. 代码简洁性:避免使用多次循环列表,如果列表数据很多会有性能问题,比如filter和map嵌套使用
4. 三元表达式: 使用时根据场景可以换成或
5. 否定前置
6. 空数据:接口返回数据为空兼容判断
7. 数组遍历for循环修改为for/of
8. dayjs/moment可以转换一切时间形式为format,不止是时间戳还有标准时间
9. 空值合并运算符(??)使用: 当左侧的操作数为 null 或者 undefined 时,返回其右侧操作数,否则返回左侧操作数
10. dayjs().format(‘YYYY-MM-DD HH:mm:ss’)无参数时默认取的当前时刻; 有参数时可以考虑把参数提取出来
11. toString()可以写为join(‘,’)
12. 数据为空兼容:用或、?.表示
13. if switch可以考虑转换为json map形式
14. a或b或c改为 [].includes()
15. try/catch捕获错误异常console.dir(error);
ES6 代码问题 1. map循环中可以使用解构的话换成解构,避免多层嵌套
2. 解构:能解构尽量解构,边界值兼容处理
CSS 代码问题 1. 类名:类名注意不要太简单,直接取name/title/desc之类的,容易和其他人写的类名冲突,比如别人写了同名的类名没有设置scoped或者全局类名,会影响自己的样式

map/forEach说明

比如:

# demo1
arr.map(({value = {}, ...item})=>{    
  return {        
    ...item,        
    ...value    
}})
​
# demo2
const type = this.alarmType?.map(item => ({alarmTypeId: item})) || [];
​
# demo3 push行为修改为map
this.evidence.printScreen = data.printScreen?.map(
  ({ id, title, value }) => ({
    id,
    title,
    value,
    url: `${imgUrlPre}${id}`,
  })
);

dayjs.format(str)说明

dayjs.format(str) ,str抽离成下面形式
const DATE_FORMAT_TYPE = {
  date: 'YYYY-MM-DD',
  time: 'HH:mm:ss',
  dateTime: 'YYYY-MM-DD HH:mm:ss',
};
© 版权声明
THE END
喜欢就支持一下吧
点赞6 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容