前端常见代码规范

前言

本文档旨在规范前端编码规范,力求达到任何人阅读他人代码都能快速理解并着手开发,其他未总结到的编码格式规范应严格按照ESLint格式要求编写即可。

css规范

​ 本文档的目标是规范组内代码风格,尽可能的使 同事们的 CSS 代码风格保持一致,容易被理解和被维护。 虽然本文档是针对 CSS 设计的,但是在使用各种 CSS 的预编译器(如 less、sass、stylus 等)时,适用的部分也应尽量遵循本文档的约定。

空格、缩进、属性简写

使用 2 个空格做为一个缩进层级,不允许使用 4 个空格 或 tab 字符。 选择器 与 { 之间必须包含空格。 属性名 与之后的 : 之间不允许包含空格, : 与 属性值 之间必须包含空格。 列表型属性值 书写在单行时, 后必须跟一个空格。 属性能简写时,必须简写,方便阅读和维护。 属性值为 0 时,建议不带单位,若带单位,须保持单个项目整体统一! 属性定义必须另起一行。 示例:

/* good */
.selector {
  margin: 5px 10px;
  padding: 0 10px 5px 10px;
 font-family: Arial, sans-serif;
}

选择器

当一个 rule 包含多个 selector 时,每个选择器声明必须独占一行。 示例:

/* good */
.post,
.page,
.comment {
  line-height: 1.5;
}

/* bad */
.post, .page, .comment {
  line-height: 1.5;
}
/* 建议 >、+、~ 选择器的两边各保留一个空格。若不保留空格,须保持单个项目整体统一!
示例:*/
/* good */
main > nav {
    padding: 10px;
}

label + input {
    margin-left: 5px;
}

input:checked ~ button {
    background-color: #69C;
}
/* 属性选择器中的值必须用双引号包围。
示例:*/
/* good */
article[character="juliet"] {
    voice-family: "Vivien Leigh", victoria, female;
}

/* bad */
article[character='juliet'] {
    voice-family: "Vivien Leigh", victoria, female;
}

清除浮动

当元素需要撑起高度以包含内部的浮动元素时,通过对父级的伪类设置 clear 进行 clearfix。 示例:

.clearfix::after {
    content: "";
    display: block;
    clear: both;
}
.clearfix{
    *zoom: 1;
}

颜色

RGB 颜色值必须使用十六进制记号形式 #rrggbb 。不允许使用 rgb() ,带有 alpha 的颜色信息可以使用 rgba() 。使用 rgba() 时每个逗号后必须保留一个空格。 示例:

/* good */
.success {
    box-shadow: 0 0 2px rgba(0, 128, 0, .3);
    border-color: #008000;
}

/* bad */
.success {
    box-shadow: 0 0 2px rgba(0,128,0,.3);
    border-color: rgb(0, 128, 0);
}
/*
颜色值不允许使用命名色值。
颜色值中的英文字符采用小写。如不用小写也需要保证同一项目内保持大小写一致。
示例:
*/
/* good */
.success {
    background-color: #aaccaa;
    color: #90ee90;
}

/* good */
.success {
    background-color: #AACCAA;
    color: #90EE90;
}

/* bad */
.success {
    background-color: #ACA;
    color: #90ee90;
}

过渡与动画

尽可能在浏览器能高效实现的属性上添加过渡和动画。能使用 transform 实现的效果绝不使用 transition 解释: 见本文,在可能的情况下应选择这样四种变换:

transform: translate(npx, npx);
transform: scale(n);
transform: rotate(ndeg);
opacity: 0.1;
/*
典型的,可以使用 translate 来代替 left 作为动画属性。示例:
*/
/* good */
.box {
    transition: transform 1s;
}
.box:hover {
    transform: translate(20px); /* move right for 20px */
}

/* bad */
.box {
    left: 0;
    transition: left 1s;
}
.box:hover {
    left: 20px; /* move right for 20px */
}

JS 规范

本文档的目标是规范组内代码风格,尽可能的使 同事们的 JS 代码风格保持一致,容易被理解和被维护。

代码风格

  • 使用2个空格进行缩进;
  • 除需要转义的情况外,字符串统一使用单引号;
  • 不要定义未使用的变量;
  • 关键字后面加空格;
  • 函数声明时括号与函数名间加空格;
  • 无分号;
  • 行首不要以 ( , [ , or ` 开头,这是省略分号时唯一会造成问题的地方;
  • 等等……

解释:

  1. 本组代码风格应严格按照 JavaScript Standard Style 规则执行,具体细则参考 Standard 细则

  2. 就目前而言,组内大部分使用 vue-cli 搭建的项目都已经集成好了 Standard 校验,具体配置可以参考根目录中的 .eslintrc.js文件,同时不排除未集成 Standard 校验的项目,此时应该按照 安装教程 并集成到自己的 IDE 中。

  3. 当项目中存在第三方库有大量代码无法通过格式校验时,可采用以下方法排除此类文件:

    • 可以在 package.json 里添加 standard.ignore 属性来配置:

      "standard": {
        "ignore": [
          "**/out/",
          "/lib/select2/",
          "/lib/ckeditor/",
          "tmp.js"
        ]
      }
      
    • JavaScript Standard 代码规范底层使用的是 ESLint。所以如果需要隐藏某些警告,使用 /* eslint-disable */ 即可

命名规则

基本原则:全英文命名,且命名规则应遵循基本的见名思意原则

见名思意 原则

在兼顾长度和可读性的情况下应尽可能准确的表达出其作用

  • 变量名 和 函数名 使用小驼峰命名,即首字母小写,每个有意义的单词首字母大写
  • 常量 使用 全部字母大写,单词间下划线分隔 的命名方式
  • boolean 类型的变量使用 ishas 开头

示例:

var loadingModules = {}
const HTML_ENTITY = {}
function stringFormat (source) {}
var isReady = false
var hasMoreCommands = false

注释

  • 单行注释,// 后跟一个空格;若另起一行,缩进与下一行被注释说明的代码一致
  • 多行注释使用 /** **/ 的方式

示例:

// 单行注释
 
/**
 * 这是一个多行注释
 * 多行注释的第二行
 */
  • 方法/函数注释,应对方法功能和注意事项做简要描述,且注明所需参数的类型和说明
  • 对 Object 中各项的描述, 必须使用 @param 标识。

示例:

/**
 * 函数描述
 *
 * @param {string} p1 参数1的说明
 * @param {string} p2 参数2的说明,比较长
 *     那就换行了.
 * @param {number=} p3 参数3的说明(可选)
 * @return {Object} 返回值描述
 */
function foo(p1, p2, p3) {
    var p3 = p3 || 10;
    return {
        p1: p1,
        p2: p2,
        p3: p3
    }
}
 
 
/**
 * 函数描述
 *
 * @param {Object} option 参数描述
 * @param {string} option.url option项描述
 * @param {string=} option.method option项描述,可选参数
 */
function foo(option) {
    // TODO
}

varletconst

  • 在块级作用域中,使用 let 代替 var 使用
  • 在无特殊要求的for 循环中,强制要求使用 let 定义索引
  • 在定义常量时,使用 const

类型转换

  • 转换成 string 时,使用 + ''
  • 转换成 number 时,通常使用 + 或者 - 0
  • string 转换成 number,要转换的字符串结尾包含非数字并期望忽略时,使用 parseInt
  • 使用 parseInt 时,必须指定进制
  • 转换成 boolean 时,使用 !!
  • number 去除小数点,使用 Math.floor / Math.round / Math.ceil,不使用 parseInt

示例:

// good
num + ''
 
// bad
new String(num)
num.toString()
String(num)
 
_______________________
// good
+str;
str - 0
// bad
Number(str)
 
________________________
var width = '200px'
parseInt(width, 10)
 
________________________
// good
parseInt(str, 10)
 
// bad
parseInt(str)
 
 
________________________
var num = 3.14
!!num
 
________________________
// good
var num = 3.14
Math.ceil(num)
 
// bad
var num = 3.14
parseInt(num, 10)

对象

  • 使用对象字面量 {} 创建新 Object
  • 对象创建时,如果一个对象的所有 属性 均可以不添加引号,建议所有 属性 不添加引号
  • 对象创建时,如果任何一个 属性 需要添加引号,则所有 属性 建议添加 '
  • 属性 访问时,尽量使用 .
  • for in 遍历对象时, 使用 hasOwnProperty 过滤掉原型中的属性

示例:

// good
var obj = {}
 
// bad
var obj = new Object()
 
________________________
var info = {
    name: 'someone',
    age: 28
}
 
________________________
info.age
info['more-info']
 
________________________
var newInfo = {}
for (var key in info) {
    if (info.hasOwnProperty(key)) {
        newInfo[key] = info[key]
    }
}

数组

  • 使用数组字面量 [] 创建新数组,除非想要创建的是指定长度的数组
  • 遍历数组不使用 for in

示例:

// good
var arr = []
 
// bad
var arr = new Array()
 
________________________
var arr = ['a', 'b', 'c'];
 
// 这里仅作演示, 实际中应使用 Object 类型
arr.other = 'other things'
 
// 正确的遍历方式
for (let i = 0, len = arr.length; i < len; i++) {
    console.log(i)
}
 
// 错误的遍历方式
for (var i in arr) {
    console.log(i)
}

Less 规范

本文档的目标是规范组内代码风格,尽可能的使 同事们的 Less 代码风格保持一致,容易被理解和被维护。Less 代码的基本规范和原则与Css规范保持一致。

代码组织

  • 代码必须(MUST)按如下形式按顺序组织:
    1. @import
    2. 变量声明
    3. 样式声明

示例:

// ✓
@import "est/all.less";

@default-text-color: #333;

.page {
    width: 960px;
    margin: 0 auto;
}

变量

  • Less 的变量值总是以同一作用域下最后一个同名变量为准,务必注意后面的设定会覆盖所有之前的设定。
  • 变量命名必须采用 @foo-bar 形式,不得使用 @fooBar 形式。
  • 变量命名不得使用 @font-14 形式,此种命名方式与直接书写 font-size: 14px; 无异,而应该使用 @font-size-normal 这种形式。

示例:

// ✗
@sidebarWidth: 200px;
@width:800px;

// ✓
@sidebar-width: 200px;
@width: 800px;

文件导入

  • 使用 @import (reference) 导入 less 文件,避免导入的 less 文件代码重复打包到最终的 css文件中

解释:

原理参见 Less导入选项reference关键词 或自行google

示例:

@import (reference) "base.less"

Vue 规范

组件名

命名须遵循以下原则:

有意义的名词、简短、具有可读性,避免与 HTML 标签冲突,结构清晰。 以大写开头,采用大驼峰的命名方式。

组件文件夹命名主要以功能模块代表命名,采用中划线格式命名,达到看到中划线文件夹就知晓是组件效果。例如:article-item。同时还需要注意:必须符合自定义元素规范。

示例:

// 反例
export default {
    name: 'articleItem'
}

// 正例
export default {
    name: 'ArticleItem'
}

Prop

定义 Prop 的时候应该始终以驼峰格式(camelCase)命名,且定义的时候应该尽量详细的指定其类型,默认值以及验证。

示例:

// 反例
props: ['attrM', 'attrA', 'attrZ']

// 正例
props: {
    attrM: Number,
    attrA: {
        type: String,
        required: true
    },
    attrZ: {
        type: Object,
        // 数组/对象的默认值应该由一个工厂函数返回
        default: function ( ) {
            return {
                msg: '成就你我'
            }
        }
    },
    attrE: {
        type: String,
        validator: function (v) {
            return !(['success', 'fail'].indexOf(v) === -1) 
        }
    }
}

v-for

在执行 v-for 遍历的时候,总是应该带上 key 值使更新 DOM 时渲染效率更高。注意:v-for与v-if不能同时使用。

示例:

// 反例
<ul>
    <li v-for="item in list">
        {{ item.title }}
    </li>
</ul>

// 正例
<ul>
    <li v-for="item in list" :key="item.id">
        {{ item.title }}
    </li>
</ul>

v-if / v-else-if / v-else

若同一组 v-if 逻辑控制中的元素逻辑相同,Vue 为了更高效的元素切换,会复用相同的部分,例如: value 。为了避免复用带来的不合理效果,建议在同种元素上加上 key 做标识。

示例:
// 反例
<div v-if="hasData">
    <span>{{ mazeyData }}</span>
</div>
<div v-else>
    <span>无数据</span>
</div>

// 正例
<div v-if="hasData" key="mazey-data">
    <span>{{ mazeyData }}</span>
</div>
<div v-else key="mazey-none">
    <span>无数据</span>
</div>

指令缩写

为了统一规范始终使用指令缩写,使用 v-bindv-on 并没有什么不好,这里仅为了统一规范。

示例:

<input :value="mazeyUser" @click="verifyUser">

样式

为了避免样式冲突,整个项目建议全都使用 scoped 特性,若遇到使用动态生成 DOM 节点无法赋上 scopeId 的而无法修改样式的情况,应另行新建 reset 样式表全局引入,做单独的样式重置,

总结

本文档旨在规范前端编码规范,力求达到任何人阅读他人代码都能快速理解并着手开发,其他未总结到的编码格式还请补充指正。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350