前端代码规范及风格Code Guide

    科技2022-07-17  106

    前端 Code Guide

    命名规则项目命名目录命名JS文件命名CSS,SCSS文件命名HTML文件命名 HTML语法HTML doctypelang属性charset 字符编码IE兼容模式引入CSS,JSHTML5规范链接 属性顺序boolean属性JS中生成标签减少标签数量实用高于完美 CSS,SCSS通识缩进分号空格空行换行注释引号命名颜色选择器属性顺序属性简写媒体查询SCSS相关杂项 JavaScript通识缩进单行长度分号空格空行换行单行注释多行注释文档注释引号变量命名函数数组、对象括号nullundefinedESLint杂项 编辑器配置TODO总结vscode 配置总结文档注释的标签总结 Vue 代码风格 参考与感谢

    不管有多少人共同参与同一项目,一定要确保每一行代码都像是同一个人编写的

    命名规则

    项目命名

    全部采用 小写 方式,以 下划线 分隔例:my_project_name

    目录命名

    参照项目命名规则有复数结构时,采用复数命名法

    例如: scripts、styles、images、data_modals

    JS文件命名

    参照项目命名规则例: lk-utils.js

    CSS,SCSS文件命名

    参照项目命名规则例:lk-style.scss

    HTML文件命名

    参照项目命名规则例:lk-index.html


    HTML

    语法

    缩进使用2个空格(bootstrap规范)嵌套的节点应该缩进标签不要大写,即便是 doctype 标签在属性上,使用双引号,不要使用单引号属性名全小写,用中划线做分隔符不要在自动闭合标签结尾处使用斜线(HTML5 规范 指出他们是可选的)不要忽略可选的关闭标签,例: </li> 和 </body> <!doctype html> <html> <head> <title>Page title</title> </head> <body> <img src="images/company_logo.png" alt="Company"> <h1 class="hello-world">Hello, world!</h1> </body> </html>

    HTML doctype

    为每个 HTML 页面的第一行添加standards mode(标准模式)声明,这样能够确保在每个浏览器中拥有一致的展现

    lang属性

    根据HTML5规范:

    应在html标签上加上lang属性,从而为文档设置正确的语言。这会给语音工具和翻译工具帮助,告诉它们应当怎么去发音和翻译。

    更多关于 lang 属性的说明在这里 在菜鸟联盟上可以查到语言列表

    charset 字符编码

    通过声明一个明确的字符编码,让浏览器轻松、快速的确定适合网页内容的渲染方式,通常指定为‘UTF-8’

    IE兼容模式

    用标签可以指定页面应该用什么版本的IE来渲染

    如果想要了解更多,请点击这里

    What does <meta http-equiv=“X-UA-Compatible” content=“IE=edge”> do? Depending upon what Microsoft browsers you support you may not need to continue using the X-UA-Compatible tag. If you need to support IE9 or IE8, then I would recommend using the tag. If you only support the latest browsers (IE11 and/or Edge) then I would consider dropping this tag altogether.

    简而言之需要兼容IE9/8,加上X-UA-Compatible,否则不用加

    不同doctype在不同浏览器下会触发不同的渲染模式(这篇文章总结的很到位) <!DOCTYPE html> <html> <head> <meta http-equiv="X-UA-Compatible" content="IE=Edge"> </head> ... </html>

    引入CSS,JS

    根据html5规范,通常在引入CSS和JS时不需要指明type,因为 text/css和 text/javasctipt 分别是他们的默认值

    HTML5规范链接

    使用link使用style使用script <!-- External CSS --> <link rel="stylesheet" href="code_guide.css"> <!-- In-document CSS --> <style> ... </style> <!-- External JS --> <script src="code_guide.js"></script> <!-- In-document JS --> <script> ... </script>

    属性顺序

    属性应该按照特定的顺序出现以保证易读性

    classidnamedata-*src , for , type , href , value , max-length , max , min , patternplaceholder , title , altaria-* , rolerequired , readonly , disabled

    class是为高可复用组件设计的,所以应处在第一位id更加具体且应该尽量少使用,所以将它放在第二位

    <a class="..." id="..." data-modal="toggle" href="#">Example link</a> <input class="form-control" type="text"> <img src="..." alt="...">

    boolean属性

    boolean属性指不需要声明取值的属性,XHTML需要每个属性声明取值,但是HTML5中并不需要

    boolean属性的存在表示取值为true,不存在则表示取值为false。

    <input type="text" disabled> <input type="checkbox" value="1" checked> <select> <option value="1" selected>1</option> </select>

    JS中生成标签

    在JS文件中生成标签让内容变得更难查找,更难编辑,性能更差。应该尽量避免这种情况的出现。

    减少标签数量

    在编写HTML代码时,需要尽量避免多余的父节点很多时候, 需要通过迭代和重构来使HTML变得更少 <!-- Not well --> <span class="avatar"> <img src="..."> </span> <!-- Better --> <img class="avatar" src="...">

    实用高于完美

    尽量遵循HTML标准和语义任何时候都要用 尽量小的复杂度 和 尽量少的标签 来解决问题但是不应该以浪费实用性作为代价

    CSS,SCSS

    通识

    /* 这样叫规则(下同) */ .element { ... } .element { /* 这样叫属性(下同) */ height: 30px; }

    缩进

    使用2空格

    分号

    每个属性声明末尾都要加分号

    空格

    以下几种情况不需要空格:

    每条声明语句的 : 后多个规则的分隔符 " . 前!important ! 后属性值中 ( ) 的前后行末不要有多余的空格

    以下几种情况需要空格:

    属性值前选择器 > , + , ~ 前后{ 前!important ! 前@else 前后属性值中的 , 后注释 /* _后和 __*/_ 前 /* not good */ .element { color :red! important; background-color: rgba(0,0,0,.5); } /* good */ .element { color: red !important; background-color: rgba(0, 0, 0, .5); } /* not good */ .element , .dialog{ ... } /* good */ .element, .dialog { } /* not good */ .element>.dialog{ ... } /* good */ .element > .dialog{ ... } /* not good */ .element{ ... } /* good */ .element { ... } /* not good */ @if{ ... }@else{ ... } /* good */ @if { ... } @else { ... }

    空行

    以下几种情况需要空行:

    文件最后保留一个空行} 后最好跟一个空行,包括SCSS中嵌套的规则属性组之间需要适当的空行,详见下方的 属性顺序 /* not good */ .element { ... } .dialog { color: red; &:after { ... } } /* good */ .element { ... } .dialog { color: red; &:after { ... } }

    换行

    以下几种情况不需要换行:

    { 前

    以下几种情况需要换行:

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

    注释

    注释统一用 /* */ (SCSS中也不要用 // ) ,具体参照代码示例写法缩进与下一行代码保持一致;可位于一个代码行的末尾,与代码间隔一个空格 /* Modal header */ .modal-header { ... } /* * Modal header */ .modal-header { ... } .modal-header { /* 50px */ width: 50px; color: red; /* color red */ }

    引号

    最外层统一使用双引号;url的内容要用引号;属性选择器中的属性值需要引号。 .element:after { content: ""; background-image: url("logo.png"); } li[data-type="single"] { ... }

    命名

    类名使用小写字母,以中划线分隔id采用驼峰式命名SCSS中的变量、函数、混合、%placeholder采用驼峰式命名 /* class */ .element-content { ... } /* id */ #myDialog { ... } /* 变量 */ $colorBlack: #000; /* 函数 */ @function pxToRem($px) { ... } /* 混合 */ @mixin centerBlock { ... } /* placeholder */ %myDialog { ... }

    颜色

    颜色16进制用小写字母。在扫描文档时,小写字符易于分辨,因为他们的形式更易于区分颜色16进制尽量用简写 /* not good */ .element { color: #ABCDEF; background-color: #001122; } /* good */ .element { color: #abcdef; background-color: #012; }

    选择器

    对于通用元素使用 class ,这样利于渲染性能的优化。对于经常出现的组件,避免使用属性选择器(例如,[class^="..."])。浏览器的性能会受到这些因素的影响。选择器要尽可能短,并且尽量限制组成选择器的元素个数,建议不要超过 3 。只有在必要的时候才将 class 限制在最近的父元素内(也就是后代选择器)(例如,不使用带前缀的 class 时 – 前缀类似于命名空间)。

    扩展阅读:

    Scope CSS classes with prefixesStop the cascade

    属性顺序

    相关的属性声明应当归为一组,并按照下面的顺序排列: PositioningBox modelTypographicVisualMisc 由于定位(positioning)可以从正常的文档流中移除元素,并且还能覆盖盒模型(box model)相关的样式,因此排在首位。盒模型排在第二位,因为它决定了组件的尺寸和位置其他属性只是影响组件的 内部 或者是不影响前两组属性,因此排在后面

    完整的属性列表及其排列顺序请参考 Bootstrap property order for Stylelint

    .declaration-order { /* Positioning */ position: absolute; top: 0; right: 0; bottom: 0; left: 0; z-index: 100; /* Box-model */ display: block; float: right; width: 100px; height: 100px; /* Typography */ font: normal 13px "Helvetica Neue", sans-serif; line-height: 1.5; color: #333; text-align: center; /* Visual */ background-color: #f5f5f5; border: 1px solid #e5e5e5; border-radius: 3px; /* Misc */ opacity: 1; }

    属性简写

    属性简写需要你非常清楚属性值的正确顺序,而且在大多数情况下并不需要设置属性简写中包含的所有值,所以建议尽量分开声明会更加清晰;margin 和 padding 相反,需要使用简写;

    常见的属性简写包括:

    fontbackgroundtransitionanimation /* not good */ .element { transition: opacity 1s linear 2s; } /* good */ .element { transition-delay: 2s; transition-timing-function: linear; transition-duration: 1s; transition-property: opacity; }

    媒体查询

    尽量将媒体查询的规则靠近与他们相关的规则不要将他们一起放到一个独立的样式文件中,或者丢在文档的最底部,这样做只会让大家以后更容易忘记他们 .element { ... } .element-avatar{ ... } @media (min-width: 480px) { .element { ... } .element-avatar { ... } }

    SCSS相关

    提交的代码中不要@debug声明顺序: @extend不包含 @content 的 @include包含 @content 的 @include自身属性嵌套规则 @import 引入的文件不需要开头的 _ 和结尾的 .scss ,详情在这里

    使用sass的@import规则并不需要指明被导入文件的全名。你可以省略.sass或.scss文件后缀。 当你@import一个局部文件时,还可以不写文件的全名,即省略文件名开头的下划线。

    嵌套最多不能超过5层@extend 中使用placeholder选择器去掉不必要的父级引用符号 &操作符

    为了提高可读性,在圆括号中的数学计算表达式的数值、变量和操作符之间均添加一个空格

    /* not good */ @import "_dialog.scss"; /* good */ @import "dialog"; /* not good */ .fatal { @extend .error; } /* good */ .fatal { @extend %error; } /* not good */ .element { & > .dialog { ... } } /* good */ .element { > .dialog { ... } } /* not good */ .element { margin: 10px 0 @variable*2 10px; } /* good */ .element { margin: 10px 0 (@variable * 2) 10px; }

    杂项

    不允许有空的规则元素选择器用小写字母去掉小数点前面的0去掉数字中不必要的小数点和末尾的0属性值 0 后面不要加单位同个属性不同前缀的写法需要在垂直方向保持对齐,具体参照代码示例的写法(仁者见仁)无前缀的标准属性应该写在有前缀的属性后面不要在同个规则里出现重复的属性,如果重复的属性是连续的则没关系不要在一个文件里出现两个相同的规则用 border: 0; 代替 border: none;选择器不要超过4层(在SCSS中如果超过四层应该考虑用嵌套的方式来写)发布的代码中不要有 @import。 不光增加了额外的请求次数,还会导致不可预料的问题。替代办法有以下几种: 使用多个 元素通过 Sass 或 Less 之类的 CSS 预处理器将多个 CSS 文件编译为一个文件通过 Rails、Jekyll 或其他系统中提供过 CSS 文件合并功能

    详情在这里

    尽量少用 * 选择器 /* not good */ .selector, .selector-secondary, .selector[type=text] { padding:15px; margin:0px 0px 15px; background-color:rgba(0, 0, 0, 0.5); box-shadow:0px 1px 2px #CCC,inset 0 1px 0 #FFFFFF } /* good */ .selector, .selector-secondary, .selector[type="text"] { padding: 15px; margin-bottom: 15px; background-color: rgba(0,0,0,.5); box-shadow: 0 1px 2px #ccc, inset 0 1px 0 #fff; }

    JavaScript

    通识

    以下变量全部使用var来声明,开发中请用let、const代替

    缩进

    使用2空格

    单行长度

    不要超过80但如果编辑器开启 word wrap 可以不考虑单行长度

    分号

    一下几种情况后需加分号:

    变量声明表达式returnthrowbreakcontinuedo-while /* var declaration */ var x = 1; /* expression statement */ x++; /* do-while */ do { x++; } while (x < 10);

    空格

    以下几种情况不需要空格:

    对象的属性的属性名后 // not good var a = { b :1 }; // good var a = { b: 1 }; 前缀一元运算符后,后缀一元运算符前函数调用括号前无论是函数声明还是函数表达式, ( 前不要空格数组的 [ 后和 ] 前对象的 { 后和 } 前运算符 { 后和 } 前

    以下几种情况需要空格:

    二元运算符前后三元运算符 ? : 前后代码块 { 前下列关键字前: else , while, catch, finally下列关键字后:if, else, for, while, do, switch, case, try, catch, finally, with, return, typeof单行 // 后(若单行注释和代码同行,则 // 前也需要),多行注释 * 后对象的属性值前for循环,分号后留有一个空格,前置条件如果有多个,逗号后留一个空格无论是函数声明还是函数表达式, { 前一定要有空格函数的参数之间

    空行

    以下几种情况需要空行:

    变量声明后(当变量声明在代码块的最后一行时,则无需空行)注释前(当注释在代码块的第一行时,无需空行)代码块后(在函数调用、数组、对象中则无需空行)文件最后保留一个空行 // need blank line after variable declaration var x = 1; // not need blank line when variable declaration is last expression in the current block if (x >= 1) { var y = x + 1; } var a = 2; // need blank line before line comment a++; function b() { // not need blank line when comment is first line of block return a; } // need blank line after blocks for (var i = 0; i < 2; i++) { if (true) { return false; } continue; } // not need blank linße when in argument list, array, object func( 2, function() { a++; }, 3ß ); var foo = [ 2, function() { a++; }, 3 ]; var foo = { a: 2, b: function() { a++; }, c: 3 };

    换行

    换行的地方,行末必须有 , 或者运算符以下几种情况不需要换行:

    下列关键字后:else, catch, finally代码块 { 前

    以下几种情况需要换行:

    代码块 { 后和 } 前变量赋值后 换行的地方,行末必须有','或者运算符; 以下几种情况不需要换行: 下列关键字后:else, catch, finally 代码块'{'前 以下几种情况需要换行: 代码块'{'后和'}'前 变量赋值后 // not good var a = { b: 1 , c: 2 }; x = y ? 1 : 2; // good var a = { b: 1, c: 2 }; x = y ? 1 : 2; x = y ? 1 : 2; // no need line break with 'else', 'catch', 'finally' if (condition) { ... } else { ... } try { ... } catch (e) { ... } finally { ... } // not good function test() { ... } // good function test() { ... } // not good var a, foo = 7, b, c, bar = 8; // good var a, foo = 7, b, c, bar = 8;

    单行注释

    双斜线后,必须跟一个空格缩进与下一行代码保持一致可位于一个代码行的末尾,与代码间隔一个空格 if (condition) { // if you made it here, then all security checks passed allowed(); } var zhangsan = 'zhangsan'; // one space after code

    多行注释

    最少三行, * 后跟一个空格,具体参照代码示例的写法建议在以下情况下使用:

    难于理解的代码段可能存在错误的代码段浏览器特殊的HACK代码业务逻辑强相关的代码 /* * one space after '*' */ var x = 1;

    文档注释

    各类标签 @param , @method 等描述和例子请参考usejsdoc和JSDoc Guide(重要)建议在以下情况下使用:

    所有常量所有函数所有类 /** * @func * @desc 一个带参数的函数 * @param {string} a - 参数a * @param {number} b=1 - 参数b默认值为1 * @param {string} c=1 - 参数c有两种支持的取值</br>1—表示x</br>2—表示xx * @param {object} d - 参数d为一个对象 * @param {string} d.e - 参数d的e属性 * @param {string} d.f - 参数d的f属性 * @param {object[]} g - 参数g为一个对象数组 * @param {string} g.h - 参数g数组中一项的h属性 * @param {string} g.i - 参数g数组中一项的i属性 * @param {string} [j] - 参数j是一个可选参数 */ function foo(a, b, c, d, g, j) { ... }

    引号

    最外层统一使用单引号

    // not good var x = "test"; // good var y = 'foo', z = '<div id="test"></div>';

    变量命名

    标准变量采用驼峰式命名(除了对象的属性外,主要是考虑到CGI返回的数据)'ID’在变量名中全大写'URL’在变量名中全大写'Android’在变量名中大写第一个字母'iOS’在变量名中小写第一个,大写后两个字母常量全大写,用下划线连接函数,大写第一个字母jquery对象必须以’$'开头命名 var thisIsMyName; var goodID; var reportURL; var AndroidVersion; var iOSVersion; var MAX_COUNT = 10; function Person(name) { this.name = name; } // not good var body = $('body'); // good var $body = $('body');

    变量声明

    一个函数作用域中所有的变量声明尽量提到函数首部用一个var声明,不允许出现两个连续的var声明 function doSomethingWithItems(items) { // use one var var value = 10, result = value + 10, i, len; for (i = 0, len = items.length; i < len; i++) { result += 10; } }

    函数

    无论是函数声明还是函数表达式, ( 前不要空格,但 { 前一定要有空格函数调用括号前不需要空格立即执行函数外必须包一层括号不要给inline function命名参数之间用’, '分隔,注意逗号后有一个空格 // no space before '(', but one space before'{' var doSomething = function(item) { // do something }; function doSomething(item) { // do something } // not good doSomething (item); // good doSomething(item); // requires parentheses around immediately invoked function expressions (function() { return 1; })(); // not good [1, 2].forEach(function x() { ... }); // good [1, 2].forEach(function() { ... }); // not good var a = [1, 2, function a() { ... }]; // good var a = [1, 2, function() { ... }]; // use ', ' between function parameters var doSomething = function(a, b, c) { // do something };

    数组、对象

    对象属性名不需要加引号对象以缩进的形式书写,不要写在一行数组、对象最后不要有逗号(仁者见仁) // not good var a = { 'b': 1 }; var a = {b: 1}; var a = { b: 1, c: 2, }; // good var a = { b: 1, c: 2 };

    括号

    下列关键字后必须有大括号(即使代码块的内容只有一行):if, else, for, while, do, switch, try, catch, finally, with

    // not good if (condition) doSomething(); // good if (condition) { doSomething(); }

    null

    适用场景:

    初始化一个将来可能被赋值为对象的变量与已经初始化的变量做比较作为一个参数为对象的函数的调用传参作为一个返回对象的函数的返回值

    不适用场景:

    不要用null来判断函数调用时有无传参(有可能是undefined?)不要与未初始化的变量做比较 // not good function test(a, b) { if (b === null) { // not mean b is not supply ... } } var a; if (a === null) { ... } // good var a = null; if (a === null) { ... }

    undefined

    永远不要直接使用undefined进行变量判断使用typeof和字符串’undefined’对变量进行判断 undefined 永远不要直接使用undefined进行变量判断; 使用typeof和字符串'undefined'对变量进行判断。

    ESLint

    用’=’, '!‘代替’==’, ‘!=’for-in里一定要有hasOwnProperty的判断不要在内置对象的原型上添加方法,如Array, Date不要在内层作用域的代码里声明了变量,之后却访问到了外层作用域的同名变量变量不要先使用后声明,使用let、const可以避免不要在一句代码中单单使用构造函数,记得将其赋值给某个变量不要在同个作用域下声明同名变量不要在一些不需要的地方加括号,例:delete(a.b)不要使用未声明的变量(全局变量需要加到.jshintrc文件的globals属性里面)不要声明了变量却不使用不要在应该做比较的地方做赋值debugger不要出现在提交的代码里数组中不要存在空元素;不要在循环内部声明函数;不要像这样使用构造函数,例:new function () { ... }, new Object; // not good if (a == 1) { a++; } // good if (a === 1) { a++; } // good for (key in obj) { if (obj.hasOwnProperty(key)) { // be sure that obj[key] belongs to the object and was not inherited console.log(obj[key]); } } // not good Array.prototype.count = function(value) { return 4; }; // not good var x = 1; function test() { if (true) { var x = 0; } x += 1; } // not good function test() { console.log(x); var x = 1; } // not good new Person(); // good var person = new Person(); // not good delete(obj.attr); // good delete obj.attr; // not good if (a = 10) { a++; } // not good var a = [1, , , 2, 3]; // not good var nums = []; for (var i = 0; i < 10; i++) { (function(i) { nums[i] = function(j) { return i + j; }; }(i)); } // not good var singleton = new function() { var privateVar; this.publicMethod = function() { privateVar = 1; }; this.publicMethod2 = function() { privateVar = 2; }; };

    杂项

    不要混用tab和space不要在一处使用多个tab或space;换行符统一用 LF对上下文this的引用只能使用 _this , that , self 其中一个来命名行尾不要有空白字符switch的falling through和no default的情况一定要有注释特别说明不允许有空的代码块 // not good var a = 1; function Person() { // not good var me = this; // good var _this = this; // good var that = this; // good var self = this; } // good switch (condition) { case 1: case 2: ... break; case 3: ... // why fall through case 4 ... break; // why no default } // not good with empty block if (condition) { }

    编辑器配置

    将你的编辑器按照下面的配置进行设置,以避免常见的代码不一致和差异:

    用两个空格代替制表符(soft-tab 即用空格代表 tab 符)。保存文件时,删除尾部的空白符。设置文件编码为 UTF-8。在文件结尾添加一个空白行。

    参照文档并将这些配置信息添加到项目的 .editorconfig 文件中。例如:Bootstrap 中的 .editorconfig 实例。更多信息请参考 about EditorConfig。

    TODO

    总结vscode 配置

    总结文档注释的标签

    具体参考JSDoc Guide

    总结 Vue 代码风格

    具体参考vue代码风格介绍

    参考与感谢

    主要参考以下文章

    Code Guide by @AlloyTeam编码规范 by @mdo

    感谢以上团队或个人

    Processed: 0.012, SQL: 8