前端代码规范(一个深度强迫症编写的小公司前端代码规范)

前端编码规范

前言之前:缩进必须规范!缩进必须规范!缩进必须规范!统一使用 Tab 进行缩进,且将制表符长度设置为 4

前言:

本文档包含 ES6 语法内容,虽然 ES6 语法已经比较成熟,而且基本前台项目的框架都是基于 Vue 框架,
良好支持 ES6 语法,但鉴于公司现有的 APP 项目等,需要向下兼容 ES5 语法,
所以本文档关于用于 ES6 语法的内容在 ES5 项目中仅作参考。
(提供一种解决办法,用 ES6 编写之后将 ES6 代码编译成 ES5 gulp方式 webpack方式 在线转换)
——本文档参考 google、网易、阿里、腾讯等前端编码规范

Ⅰ、HTML

1. 语法规范

  • 嵌套的节点应该缩进
  • 在属性上,使用双引号,不要使用单引号
  • 属性名全小写,用 -(中划线) 做分隔符
  • 不自动闭合标签必须闭合
  • 不要在自动闭合标签结尾处使用斜线(HTML5 规范 指出他们是可选的)
<!DOCTYPE html>
<html>
    <head>
        <title>Page title</title>
    </head>
    <body>
        <img src="/static/bg.png" alt="暂无图片">
        <h1 class="hello-world">Hello, world!</h1>
    </body>
</html>

2. 属性顺序

  • 标签属性应该按照特定的顺序出现以保证易读性(按以下顺序,但重点是前两条)
  1. class class属性是为高可复用组件设计的,所以应处在第一位
  2. id id属性更加具体且应该尽量少使用,所以将它放在第二位
  3. name
  4. data-*
  5. src , for , type , href , value , max-length , max , min , pattern
  6. placeholder , title , alt
  7. aria-* , role
  8. required , readonly , disabled

Ⅱ、CSS

1. 分号

  • 每个属性声明末尾一定加分号

2. 空格

无需空格

  • 属性名后
  • 多个规则的分隔符 , 前
  • !important 中的 ! 后
  • 属性值中 ( 后和 ) 前
  • 行末不要有多余的空格

需要空格

  • 属性值前
  • 选择器 > , + , ~ 前后
  • 代码块 { 前
  • !important 中的 ! 前
  • 属性值中的 , 后
  • 注释 /* 后和 */ 前
/*not good*/
.element {
    color :red! important;
    background-color: rgba(0,0,0,.5);
}

/* good */
.element {
    color: red !important;
    background-color: rgba(0, 0, 0, 0.5);
}

/* not good */
.element ,
.dialog{
    ...
}

/* good */
.element,
.dialog {

}

/* not good */
.element>.dialog{
    ...
}

/* good */
.element > .dialog{
    ...
}

3. 空行

} 后跟一个空行

/* not good */
.element {
    ...
}
.dialog {
    ...
}

/* good */
.element {
    ...
}

.dialog {
    ...
}

4. 换行

无需换行

  • { 前

需要换行

  • { 后, } 前
  • 每个属性独占一行
  • 多个规则的分隔符 , 后
/* not good */
.element
{color: red; background-color: black;}

/* good */
.element {
    color: red;
    background-color: black;
}

/* not good */
.element, .dialog {
    ...
}

/* good */
.element,
.dialog {
    ...
}

Ⅲ、JavaScript

1. 定义变量

1.1 基本规范

  • 尽量使用 let 进行定义且使用字面量创建对象,(除常量外)变量命名都以类型前缀 + 有意义的单词组成,单词首字母都需要大写,用 驼峰命名法(除第一个字母外,每个单词的首字母大写)
  • 每一个变量声明都应该只对应着一个变量。不应该出现像 let a = 1,b = 2; 这样的语句。

1.2 常量定义

  • 常量一般视为全局变量的一种,定义用 const 且全大写,一经定义不可修改,用 _(下划线) 进行分隔
const PI = 3.1415926; // const - 不可重定义 且 无法重新赋值
const BASE_URL = 'http://10.0.2.212:19110'

1.3 类的定义

  • 请使用 class 进行定义且使用 帕斯卡命名法(每个单词的首字母大写)
  • 尽量避免使用 ES5 老语法 function 定义类,易造成混淆

注: 关于 ES6 class类 的学习可以参考 —— MDN上的《 类 》这篇教程

class Rectangle {
    //...代码块
}

1.4 字符串定义相关

  • 定义字符串使用单引号 ‘’ (因为大多时候我们的字符串。特别是html会出现 " )
  • 减少字符串的换行和拼接,使用 ES6 语法的 `` 格式化字符串

1.5 特例

  • for 等循环语句中定义的 局部变量 ,使用 i, j, k
  • 作用域不大 临时变量 可以简写,例如:str, num, bol, obj, arr, fun

2. if 条件判断

  • 合理使用三目运算符减少 if 语句的使用
  • 避免 if 语句的深层次嵌套

2.1 switch 语句

  • switch 适用于条件的值等情况下

  • 如果条件较小的话选用 if else 比较合适

  • 条件数量较大建议选用 switch

  • 大多数的情况下 switch 比 if else 运行的更加快

    案例:滁州项目中通过 sos 字段返回值判断手环的状态

// if语句代码如下:

if (rowData.sos == 1) {
    return '进入围栏';
} else if (rowData.sos == 2) {
    return '出围栏';
} else if (rowData.sos == 3) {
    return '低电量';
} else if (rowData.sos == 5) {
    return 'sos告警';
} else if (rowData.sos == 14) {
    return '离线报警';
} else if (rowData.sos == 15) {
    return '开机报警';
} else if (rowData.sos == 16) {
    return '关机报警';
} else if (rowData.sos == 65) {
    return '脱落报警';
} else if (rowData.sos == 66) {
    return '蓝牙丢失报警';
} else if (rowData.sos == 104) {
    return '佩戴报警';
} else if (rowData.sos == 200) {
    return '温度心率超过阀值报警';
} else {
    return '-';
}

// 即便使用if语句,也建议把常用项放到第一位,减少判断次数,譬如rowData.sos == 5

// switch语句代码如下:

switch (rowData.sos) {
    case '1':
        return '进入围栏';
        break;
    case '2':
        return '出围栏';
        break;
    case '3':
        return '低电量';
        break;
    case '5':
        return 'sos告警';
        break;                        
    case '14':
        return '离线报警';
        break;
    case '15':
        return '开机报警';
        break;
    case '16':
        return '关机报警';
        break;
    case '65':
        return '脱落报警';
        break;
    case '66':
        return '蓝牙丢失报警';
        break;
    case '104':
        return '佩戴报警';
        break; 
    case '200':
        return '温度心率超过阀值报警';
        break;                         
    default :
        return '-';
}

// 可读性相对if语句更高

2.2 推荐解决方案

  • 针对日常开发中类似问题,推荐统一使用书写和阅读更为明了易懂的 数组 / 对象字面量方法
 // 例1:
 // 后台返回字段 fruit 该字段返一个数字 
 // 0 = 苹果, 1 = 梨子, 2 = 桔子, 3 = 柠檬, 4 = 芒果...
 let aFruit = ['苹果', '梨子', '桔子', '柠檬', '芒果'];
 let sFruit = aFruit[fruit];
 console.log(sFruit);

 // 例2:
 // 用对象方法解决上述的 if / switch 案例,后台传入rowData.sos前端体现状态
 let oWatchStatus = {
     "1": "进入围栏",
     "2": "出围栏",
     "3": "低电量",
     "5": "sos告警",
     "14": "离线报警",
     "15": "开机报警",
     "16": "关机报警",
     "65": "脱落报警",
     "66": "蓝牙丢失报警",
     "104": "佩戴报警",
     "200": "温度心率超过阀值报警"
 }
 return oWatchStatus[rowData.sos];

1、尽量使用 object[key] 的方式取 value 值,防止后台返回的 Key 值存在不符合规范格式的问题
2、如果后台返回数据需要前台做复杂操作,可要求后台返回需要格式的数据

3. 注释

3.1 注释原则

  • As short as possible(如无必要,勿增注释):尽量提高代码本身的清晰性、可读性
  • As long as necessary(如有必要,尽量详尽):合理的注释、空行排版等,可以让代码更易阅读、更具美感

3.2 单行注释

  • // 后跟一个空格,缩进与下一行被注释说明的代码一致,最好独占一行
  • 避免使用 // 这样的多行注释
  • 有多行注释内容时,请使用多个单行注释
1// not good:
map.centerAndZoom(point, 16); //初始化地图,设置中心点坐标和地图级别

// good:
map.centerAndZoom(point, 16); // 初始化地图,设置中心点坐标和地图级别

// perfect:
// 初始化地图,设置中心点坐标和地图级别
map.centerAndZoom(point, 16);2// not good: --> 多行注释
/*label.setStyle({
    position: "relative",
    border: "1px solid rgb(204, 204, 204)",
    color: "rgb(0, 0, 0)",
    textAlign: 'center',
    borderRadius: "10px",
    padding: "5px",
    background: "rgb(255, 255, 255)",
});*/


// good: --> 分行注释
// label.setStyle({
//     position: "relative",
//     border: "1px solid rgb(204, 204, 204)",
//     color: "rgb(0, 0, 0)",
//     textAlign: 'center',
//     borderRadius: "10px",
//     padding: "5px",
//     background: "rgb(255, 255, 255)",
// });

3.3 函数 / 方法注释

  • 函数 / 方法注释必须包含函数说明,有参数和返回值时必须使用注释标识
  • 参数和返回值注释必须包含类型信息和说明
    • @description: 本方法作用的描述
    • @method : 方法名(可写 / 可不写)
    • @author : 编写者的名字(方便找到编写者快速解决问题)
    • @param {参数的数据类型} 参数1: 参数1的说明
    • @param {参数的数据类型} 参数2: 参数2的说明
    • @return {返回值的数据类型}: 返回值描述

{…} 中的数据类型应该填写明确的数据类型或者具体的实体类 (该点在 TypeScript 语法中也有所体现)
例如: @param {String} 、@return {Object} 、@param {Student} ==> (Student 为自定义类)
当暂时不确定数据类型的时候可以用 {any} 占位,明确后修改为相应的数据类型

/**
* @description : 通过设置面板设置该元素css属性
* @method setCss
* @param {string} key : css的key值
* @param {any} value : css的value值 / 若flag为true -- 为携带value值的dom元素
* @param {boolean} flag : 用于区分传入的是否是需要正则转换的对象
*/
function setCss(key, value, flag) {
    if (!flag) {
        switch (key) {
            case "cycleNum":
                if (value) {
                    $("#imageCyclesCount").attr("disabled", "disabled");
                    value = "infinite";
                } else {
                    $("#imageCyclesCount").removeAttr("disabled");
                    var aniNum = $("#imageCyclesCount").val();
                    aniNum == "" ? value = 0 : value = aniNum;
                }
                break;
        }
        Widget.widgetData.currentObject.setProperty(key, value);
    } else {
        // 当echarts组件调用该方法时传入true
        Widget.widgetData.currentObject.setProperty(key, value, true);
    }
}

拓展:for…of 的对象遍历

varobj = {
    name: "hello",
    age: "18"
};
for(var i of Object.keys(obj)){
    console.log(i);
    // name
    // age
}
for(var i of Object.values(obj)){
    console.log(i);
    // hello
    // 18
}
for(var i of Object.entries(obj)){
    console.log(i);
    // ["name", "hello"]
    // ["age", "18"]
}

4. 代码书写规范

4.1 分号

  • 每个语句以分号结尾,不可依赖于JS自动添加分号的功能(return)
  • 代码块 } 后不加分号

注:想要 return 的值,不可换行书写

return
"<div class='ace-widget parentdiv' style='" + style + "'>" +
    "	 <style>" + keyFrames + "</style>" +
    "	 <div style='overflow: hidden;width: 100%;height: 100%'>" +
    "	 <div class='f-family'>" + this.nodeProperties.text +
    "	 	 </div>" +
    "	 </div>" +
    "</div>";
// 该段程序运行报错,就是JS自动添加分号的功能造成的,直接解析为 return;中断代码执行

解决办法:

return	"<div class='ace-widget parentdiv' style='" + style + "'>" +
    "	 <style>" + keyFrames + "</style>" +
    "	 <div style='overflow: hidden;width: 100%;height: 100%'>" +
    "	 <div class='f-family'>" + this.nodeProperties.text +
    "	 	 </div>" +
    "	 </div>" +
    "</div>";

4.2 空格

  • 非末尾符号后加,运算、赋值等前后加空格
let sUserName = 'Jack';

for (let i = 0; i < aMyArray.length; i ++) {...}

let oUser = {
    name: 'Tom',
    age: 15,
    hobbies: [
        reading: true,
        writing: false,
    ]
}

1 == 0 ? console.log(123) : console.log(456);

4.3 统一用词规范

  • 在函数嵌套时,为了改变 this 的指向,统一使用 that 承接

    (现有代码中很多使用 _this 或 _self 不统一,且书写相对困难)

尽可能的使用 箭头函数 ,防止 this 指向发生改变而导致需要重新定义变量

const that = this;

4.4 Axios 之后的链式写法

  • 使用箭头函数时,无论参数的个数,都用 () 进行包裹,且 => 前后必须加空格
  • .then / .catch 等类似链式写法包括其后的箭头函数,在 { 前统一不换行
// not good -- 此段代码极其不规范
const validateExsit=(rule, value, callback) => {
	this.$axios({
		method:'get',
		params:{name:value},
		url:'/maintKind/isNameExists'
	})
    .then(
    	res=>{
        	let status=res
            if(status!=true) {
            	callback(new Error('该物种已存在'));
            }
            else{
                callback()
            }                         
        }
    )
};

// good
const validateExsit = (rule, value, callback) => {
	this.$axios({
		method: 'get',
	    params: {
	        name: value
	    },
	    url: '/maintKind/isNameExists'
	}).then((res) => {
	    let status = res;
	    if (status!=true) {
	        callback(new Error('该物种已存在'));
	    } else {
	        callback();
	    }
	}).catch((rej) => {
		console.log(rej);
	});
}

4.5 setTimeout / setInterval

  • 清除计时器请使用对应的方法:clearTimeout / clearInterval 语义更明确
  • 若非必须无限计时的计时器,请在使用完毕后清除
  • 请按照规范书写计时器的格式
setTimeout(function () {
      console.log('Hello World')
}, 1000)

Ⅳ、Vue项目

1. Vue项目中的命名

1.1 文件夹命名

  • 不要使用 static 、router 等项目自带文件夹名(滁州项目中有 static 容易混淆)
  • 相同大目录下的文件放在一个文件夹下

1.2 文件命名

  • 使用帕斯卡命名法,尽可能语义化,把页面功能、结构体现在文件名中

1.3 类名命名规范

  • 每个单独的 Vue 文件中 <template> 中的最外层 <div> 使用和文件名一致的类名
  • 所有 Vue 项目的 <style> 标签中选择器前加 .文件名 的类名进行约束
  • 统一不用 <style scpoed> 这种 Vue 自带的样式局限约束(因为无法穿透组件)
  • 两个样式块中间用换行符隔开

例: 文件名为 HelloWorld.vue

<template>
    <div class='HelloWorld'>
    	<div class='content'>
        	<p class='title'>
        		......
        	</p>
		</div>
		<div class='footer'>
            ......
        </div>
    </div>
</template>

<script>
    ......
</script>

<style>
	.HelloWorld .content {
		width: 100%;
		height: 100%;
	}
	
	.HelloWorld .title {
		font-size: 12px;
		background-color: lightpink;
	}
	    
    .HelloWorld .footer {
		font-size: 12px;
		background-color: lightpink;
	}
</style>

为书写更方便,可使用 less 嵌套语法进行样式书写,使层次结构更加分明(可少写很多次 .文件名)

  • 嵌套时请先书写 父元素 中的属性,再书写 子元素 代码块
  • 若 父元素 有属性,请用空行和 子元素 代码块隔开
/* not good */
<style lang='less'>
	.HelloWorld {
       	.content {
               width: 100%;
               .title {
                   font-size: 12px;
                   background-color: lightpink;
               }
               height: 100%;
           }
           
           .footer {
               position: flexd;
               bottom: 0;
           }
	}
</style>
    
/* good */
<style lang='less'>
    .HelloWorld {
        .content {
            width: 100%;
            height: 100%;
			
                .title {
                    font-size: 12px;
                    background-color: lightpink;
                }
        }
              
        .footer {
            position: flexd;
            bottom: 0;
        }
    }
</style>
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值