前端開發(fā)100天(第1天FE前端規(guī)范)

最佳原則

堅(jiān)持制定好的代碼規(guī)范。
無論團(tuán)隊(duì)人數(shù)多少,代碼應(yīng)該同出一門。
如果你想要為這個(gè)規(guī)范做貢獻(xiàn)或覺得有不合理的地方,請留言說明。


命名規(guī)則

項(xiàng)目命名

全部采用小寫方式, 以下劃線分隔。
例:my_project_name

目錄命名

參照項(xiàng)目命名規(guī)則;
有復(fù)數(shù)結(jié)構(gòu)時(shí),要采用復(fù)數(shù)命名法。
例:scripts, styles, images, data_models

JS文件命名

參照項(xiàng)目命名規(guī)則。
例:account_model.js

CSS, SCSS文件命名

參照項(xiàng)目命名規(guī)則。
例:retina_sprites.scss

HTML文件命名

參照項(xiàng)目命名規(guī)則。
例:error_report.html

HTML

語法

  • 縮進(jìn)使用soft tab(4個(gè)空格);
  • 嵌套的節(jié)點(diǎn)應(yīng)該縮進(jìn);
  • 在屬性上,使用雙引號,不要使用單引號;
  • 屬性名全小寫,用中劃線做分隔符;
  • 不要在自動閉合標(biāo)簽結(jié)尾處使用斜線(HTML5規(guī)范 指出他們是可選的);
  • 不要忽略可選的關(guān)閉標(biāo)簽,例:</li></body>
<!DOCTYPE html>
<html>
    <head>
        <title>Page title</title>
    </head>
    <body>
        ![](images/company_logo.png)
        <h1 class="hello-world">Hello, world!</h1>
    </body>
</html>

HTML5 doctype

在頁面開頭使用這個(gè)簡單地doctype來啟用標(biāo)準(zhǔn)模式,使其在每個(gè)瀏覽器中盡可能一致的展現(xiàn);
雖然doctype不區(qū)分大小寫,但是按照慣例,doctype大寫。

<!DOCTYPE html>
<html>
    ...
</html>

lang屬性

根據(jù)HTML5規(guī)范:
應(yīng)在html標(biāo)簽上加上lang屬性。這會給語音工具和翻譯工具幫助,告訴它們應(yīng)當(dāng)怎么去發(fā)音和翻譯。
更多關(guān)于 lang 屬性的說明在這里;
在sitepoint上可以查到語言列表;
但sitepoint只是給出了語言的大類,例如中文只給出了zh,但是沒有區(qū)分香港,臺灣,大陸。而微軟給出了一份更加詳細(xì)的語言列表,其中細(xì)分了zh-cn, zh-hk, zh-tw。

<!DOCTYPE html>
<html lang="en-us">
    ...
</html>

字符編碼

通過聲明一個(gè)明確的字符編碼,讓瀏覽器輕松、快速的確定適合網(wǎng)頁內(nèi)容的渲染方式,通常指定為'UTF-8'。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
    </head>
    ...
</html>

IE兼容模式

用 <meta> 標(biāo)簽可以指定頁面應(yīng)該用什么版本的IE來渲染;
不同doctype在不同瀏覽器下會觸發(fā)不同的渲染模式。

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="X-UA-Compatible" content="IE=Edge">
    </head>
    ...
</html>

引入CSS, JS

根據(jù)HTML5規(guī)范, 通常在引入CSS和JS時(shí)不需要指明 type,因?yàn)?text/css 和 text/javascript 分別是他們的默認(rèn)值。
HTML5 規(guī)范鏈接
使用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>

屬性順序

屬性應(yīng)該按照特定的順序出現(xiàn)以保證易讀性;

  • class
  • id
  • name
  • data-*
  • src, for, type, href, value , max-length, max, min, pattern
  • placeholder, title, alt
  • aria-*, role
  • required, readonly, disabled
    class是為高可復(fù)用組件設(shè)計(jì)的,所以應(yīng)處在第一位;
    id更加具體且應(yīng)該盡量少使用,所以將它放在第二位。
<a class="..." id="..." data-modal="toggle" href="#">Example link</a>
<input class="form-control" type="text">
![](...)

boolean屬性

boolean屬性指不需要聲明取值的屬性,XHTML需要每個(gè)屬性聲明取值,但是HTML5并不需要;
boolean屬性的存在表示取值為true,不存在則表示取值為false。

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

JS生成標(biāo)簽

在JS文件中生成標(biāo)簽讓內(nèi)容變得更難查找,更難編輯,性能更差。應(yīng)該盡量避免這種情況的出現(xiàn)。

減少標(biāo)簽數(shù)量

在編寫HTML代碼時(shí),需要盡量避免多余的父節(jié)點(diǎn);
很多時(shí)候,需要通過迭代和重構(gòu)來使HTML變得更少。

 <!-- Not well -->
 <span class="avatar">
    ![](...)
 </span>
 <!-- Better -->
 ![](...)

實(shí)用高于完美

盡量遵循HTML標(biāo)準(zhǔn)和語義,但是不應(yīng)該以浪費(fèi)實(shí)用性作為代價(jià);
任何時(shí)候都要用盡量小的復(fù)雜度和盡量少的標(biāo)簽來解決問題。


CSS, SCSS

縮進(jìn)

使用soft tab(4個(gè)空格)。

.element {
    position: absolute;
    top: 10px;
    left: 10px;

    border-radius: 10px;
    width: 50px;
    height: 50px;
}

分號

每個(gè)屬性聲明末尾都要加分號。

.element {
    width: 20px;
    height: 20px;

    background-color: red;
}

空格

以下幾種情況不需要空格:

  • 屬性名后
  • 多個(gè)規(guī)則的分隔符','前
  • !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 {
    ...
}

空行

以下幾種情況需要空行:

  • 文件最后保留一個(gè)空行
  • '}'后最好跟一個(gè)空行,包括scss中嵌套的規(guī)則
  • 屬性之間需要適當(dāng)?shù)目招校唧w見屬性聲明順序
/* not good */
.element {
    ...
}
.dialog {
    color: red;
    &:after {
        ...
    }
}

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

.dialog {
    color: red;

    &:after {
        ...
    }
}

換行

以下幾種情況不需要換行:

  • '{'前
    以下幾種情況需要換行:
    '{'后和'}'前
  • 每個(gè)屬性獨(dú)占一行
  • 多個(gè)規(guī)則的分隔符','后
/* not good */
.element
{color: red; background-color: black;}

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

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

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

注釋

注釋統(tǒng)一用'/* */'(scss中也不要用'//'),具體參照右邊的寫法;
縮進(jìn)與下一行代碼保持一致;
可位于一個(gè)代碼行的末尾,與代碼間隔一個(gè)空格。

/* Modal header */
.modal-header {
    ...
}

/*
 * Modal header
 */
.modal-header {
    ...
}

.modal-header {
    /* 50px */
    width: 50px;

    color: red; /* color red */
}

引號

最外層統(tǒng)一使用雙引號;
url的內(nèi)容要用引號;
屬性選擇器中的屬性值需要引號。

.element:after {
    content: "";
    background-image: url("logo.png");
}

li[data-type="single"] {
    ...
}

命名

  • 類名使用小寫字母,以中劃線分隔
  • id采用駝峰式命名
  • scss中的變量、函數(shù)、混合、placeholder采用駝峰式命名
/* class */
.element-content {
    ...
}

/* id */
#myDialog {
    ...
}

/* 變量 */
$colorBlack: #000;

/* 函數(shù) */
@function pxToRem($px) {
    ...
}

/* 混合 */
@mixin centerBlock {
    ...
}

/* placeholder */
%myDialog {
    ...
}

屬性聲明順序

相關(guān)的屬性聲明按右邊的順序做分組處理,組之間需要有一個(gè)空行。

.declaration-order {
    display: block;
    float: right;

    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 100;

    border: 1px solid #e5e5e5;
    border-radius: 3px;
    width: 100px;
    height: 100px;

    font: normal 13px "Helvetica Neue", sans-serif;
    line-height: 1.5;
    text-align: center;

    color: #333;
    background-color: #f5f5f5;

    opacity: 1;
}
// 下面是推薦的屬性的順序
[
    [
        "display",
        "visibility",
        "float",
        "clear",
        "overflow",
        "overflow-x",
        "overflow-y",
        "clip",
        "zoom"
    ],
    [
        "table-layout",
        "empty-cells",
        "caption-side",
        "border-spacing",
        "border-collapse",
        "list-style",
        "list-style-position",
        "list-style-type",
        "list-style-image"
    ],
    [
        "-webkit-box-orient",
        "-webkit-box-direction",
        "-webkit-box-decoration-break",
        "-webkit-box-pack",
        "-webkit-box-align",
        "-webkit-box-flex"
    ],
    [
        "position",
        "top",
        "right",
        "bottom",
        "left",
        "z-index"
    ],
    [
        "margin",
        "margin-top",
        "margin-right",
        "margin-bottom",
        "margin-left",
        "-webkit-box-sizing",
        "-moz-box-sizing",
        "box-sizing",
        "border",
        "border-width",
        "border-style",
        "border-color",
        "border-top",
        "border-top-width",
        "border-top-style",
        "border-top-color",
        "border-right",
        "border-right-width",
        "border-right-style",
        "border-right-color",
        "border-bottom",
        "border-bottom-width",
        "border-bottom-style",
        "border-bottom-color",
        "border-left",
        "border-left-width",
        "border-left-style",
        "border-left-color",
        "-webkit-border-radius",
        "-moz-border-radius",
        "border-radius",
        "-webkit-border-top-left-radius",
        "-moz-border-radius-topleft",
        "border-top-left-radius",
        "-webkit-border-top-right-radius",
        "-moz-border-radius-topright",
        "border-top-right-radius",
        "-webkit-border-bottom-right-radius",
        "-moz-border-radius-bottomright",
        "border-bottom-right-radius",
        "-webkit-border-bottom-left-radius",
        "-moz-border-radius-bottomleft",
        "border-bottom-left-radius",
        "-webkit-border-image",
        "-moz-border-image",
        "-o-border-image",
        "border-image",
        "-webkit-border-image-source",
        "-moz-border-image-source",
        "-o-border-image-source",
        "border-image-source",
        "-webkit-border-image-slice",
        "-moz-border-image-slice",
        "-o-border-image-slice",
        "border-image-slice",
        "-webkit-border-image-width",
        "-moz-border-image-width",
        "-o-border-image-width",
        "border-image-width",
        "-webkit-border-image-outset",
        "-moz-border-image-outset",
        "-o-border-image-outset",
        "border-image-outset",
        "-webkit-border-image-repeat",
        "-moz-border-image-repeat",
        "-o-border-image-repeat",
        "border-image-repeat",
        "padding",
        "padding-top",
        "padding-right",
        "padding-bottom",
        "padding-left",
        "width",
        "min-width",
        "max-width",
        "height",
        "min-height",
        "max-height"
    ],
    [
        "font",
        "font-family",
        "font-size",
        "font-weight",
        "font-style",
        "font-variant",
        "font-size-adjust",
        "font-stretch",
        "font-effect",
        "font-emphasize",
        "font-emphasize-position",
        "font-emphasize-style",
        "font-smooth",
        "line-height",
        "text-align",
        "-webkit-text-align-last",
        "-moz-text-align-last",
        "-ms-text-align-last",
        "text-align-last",
        "vertical-align",
        "white-space",
        "text-decoration",
        "text-emphasis",
        "text-emphasis-color",
        "text-emphasis-style",
        "text-emphasis-position",
        "text-indent",
        "-ms-text-justify",
        "text-justify",
        "letter-spacing",
        "word-spacing",
        "-ms-writing-mode",
        "text-outline",
        "text-transform",
        "text-wrap",
        "-ms-text-overflow",
        "text-overflow",
        "text-overflow-ellipsis",
        "text-overflow-mode",
        "-ms-word-wrap",
        "word-wrap",
        "-ms-word-break",
        "word-break"
    ],
    [
        "color",
        "background",
        "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader",
        "background-color",
        "background-image",
        "background-repeat",
        "background-attachment",
        "background-position",
        "-ms-background-position-x",
        "background-position-x",
        "-ms-background-position-y",
        "background-position-y",
        "-webkit-background-clip",
        "-moz-background-clip",
        "background-clip",
        "background-origin",
        "-webkit-background-size",
        "-moz-background-size",
        "-o-background-size",
        "background-size"
    ],
    [
        "outline",
        "outline-width",
        "outline-style",
        "outline-color",
        "outline-offset",
        "opacity",
        "filter:progid:DXImageTransform.Microsoft.Alpha(Opacity",
        "-ms-filter:\\'progid:DXImageTransform.Microsoft.Alpha",
        "-ms-interpolation-mode",
        "-webkit-box-shadow",
        "-moz-box-shadow",
        "box-shadow",
        "filter:progid:DXImageTransform.Microsoft.gradient",
        "-ms-filter:\\'progid:DXImageTransform.Microsoft.gradient",
        "text-shadow"
    ],
    [
        "-webkit-transition",
        "-moz-transition",
        "-ms-transition",
        "-o-transition",
        "transition",
        "-webkit-transition-delay",
        "-moz-transition-delay",
        "-ms-transition-delay",
        "-o-transition-delay",
        "transition-delay",
        "-webkit-transition-timing-function",
        "-moz-transition-timing-function",
        "-ms-transition-timing-function",
        "-o-transition-timing-function",
        "transition-timing-function",
        "-webkit-transition-duration",
        "-moz-transition-duration",
        "-ms-transition-duration",
        "-o-transition-duration",
        "transition-duration",
        "-webkit-transition-property",
        "-moz-transition-property",
        "-ms-transition-property",
        "-o-transition-property",
        "transition-property",
        "-webkit-transform",
        "-moz-transform",
        "-ms-transform",
        "-o-transform",
        "transform",
        "-webkit-transform-origin",
        "-moz-transform-origin",
        "-ms-transform-origin",
        "-o-transform-origin",
        "transform-origin",
        "-webkit-animation",
        "-moz-animation",
        "-ms-animation",
        "-o-animation",
        "animation",
        "-webkit-animation-name",
        "-moz-animation-name",
        "-ms-animation-name",
        "-o-animation-name",
        "animation-name",
        "-webkit-animation-duration",
        "-moz-animation-duration",
        "-ms-animation-duration",
        "-o-animation-duration",
        "animation-duration",
        "-webkit-animation-play-state",
        "-moz-animation-play-state",
        "-ms-animation-play-state",
        "-o-animation-play-state",
        "animation-play-state",
        "-webkit-animation-timing-function",
        "-moz-animation-timing-function",
        "-ms-animation-timing-function",
        "-o-animation-timing-function",
        "animation-timing-function",
        "-webkit-animation-delay",
        "-moz-animation-delay",
        "-ms-animation-delay",
        "-o-animation-delay",
        "animation-delay",
        "-webkit-animation-iteration-count",
        "-moz-animation-iteration-count",
        "-ms-animation-iteration-count",
        "-o-animation-iteration-count",
        "animation-iteration-count",
        "-webkit-animation-direction",
        "-moz-animation-direction",
        "-ms-animation-direction",
        "-o-animation-direction",
        "animation-direction"
    ],
    [
        "content",
        "quotes",
        "counter-reset",
        "counter-increment",
        "resize",
        "cursor",
        "-webkit-user-select",
        "-moz-user-select",
        "-ms-user-select",
        "user-select",
        "nav-index",
        "nav-up",
        "nav-right",
        "nav-down",
        "nav-left",
        "-moz-tab-size",
        "-o-tab-size",
        "tab-size",
        "-webkit-hyphens",
        "-moz-hyphens",
        "hyphens",
        "pointer-events"
    ]
]

顏色

顏色16進(jìn)制用小寫字母;
顏色16進(jìn)制盡量用簡寫。

/* not good */
.element {
    color: #ABCDEF;
    background-color: #001122;
}

/* good */
.element {
    color: #abcdef;
    background-color: #012;
}

屬性簡寫

屬性簡寫需要你非常清楚屬性值的正確順序,而且在大多數(shù)情況下并不需要設(shè)置屬性簡寫中包含的所有值,所以建議盡量分開聲明會更加清晰;
margin 和 padding 相反,需要使用簡寫;
常見的屬性簡寫包括:

  • font
  • background
  • transition
  • animation
/* not good */
.element {
    transition: opacity 1s linear 2s;
}

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

媒體查詢

盡量將媒體查詢的規(guī)則靠近與他們相關(guān)的規(guī)則,不要將他們一起放到一個(gè)獨(dú)立的樣式文件中,或者丟在文檔的最底部,這樣做只會讓大家以后更容易忘記他們。

.element {
    ...
}

.element-avatar{
    ...
}

@media (min-width: 480px) {
    .element {
        ...
    }

    .element-avatar {
        ...
    }
}

SCSS相關(guān)

提交的代碼中不要有 @debug;
聲明順序:

  • @extend
  • 不包含 @content 的 @include
  • 包含 @content 的 @include
  • 自身屬性
  • 嵌套規(guī)則
    @import 引入的文件不需要開頭的'_'和結(jié)尾的'.scss';
    嵌套最多不能超過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 {
        ...
    }
}

雜項(xiàng)

不允許有空的規(guī)則;
元素選擇器用小寫字母;
去掉小數(shù)點(diǎn)前面的0;
去掉數(shù)字中不必要的小數(shù)點(diǎn)和末尾的0;
屬性值'0'后面不要加單位;
同個(gè)屬性不同前綴的寫法需要在垂直方向保持對齊,具體參照右邊的寫法;
無前綴的標(biāo)準(zhǔn)屬性應(yīng)該寫在有前綴的屬性后面;
不要在同個(gè)規(guī)則里出現(xiàn)重復(fù)的屬性,如果重復(fù)的屬性是連續(xù)的則沒關(guān)系;
不要在一個(gè)文件里出現(xiàn)兩個(gè)相同的規(guī)則;
用 border: 0; 代替 border: none;;
選擇器不要超過4層(在scss中如果超過4層應(yīng)該考慮用嵌套的方式來寫);
發(fā)布的代碼中不要有 @import;
盡量少用'*'選擇器。

/* not good */
.element {
}

/* not good */
LI {
    ...
}

/* good */
li {
    ...
}

/* not good */
.element {
    color: rgba(0, 0, 0, 0.5);
}

/* good */
.element {
    color: rgba(0, 0, 0, .5);
}

/* not good */
.element {
    width: 50.0px;
}

/* good */
.element {
    width: 50px;
}

/* not good */
.element {
    width: 0px;
}

/* good */
.element {
    width: 0;
}

/* not good */
.element {
    border-radius: 3px;
    -webkit-border-radius: 3px;
    -moz-border-radius: 3px;

    background: linear-gradient(to bottom, #fff 0, #eee 100%);
    background: -webkit-linear-gradient(top, #fff 0, #eee 100%);
    background: -moz-linear-gradient(top, #fff 0, #eee 100%);
}

/* good */
.element {
    -webkit-border-radius: 3px;
       -moz-border-radius: 3px;
            border-radius: 3px;

    background: -webkit-linear-gradient(top, #fff 0, #eee 100%);
    background:    -moz-linear-gradient(top, #fff 0, #eee 100%);
    background:         linear-gradient(to bottom, #fff 0, #eee 100%);
}

/* not good */
.element {
    color: rgb(0, 0, 0);
    width: 50px;
    color: rgba(0, 0, 0, .5);
}

/* good */
.element {
    color: rgb(0, 0, 0);
    color: rgba(0, 0, 0, .5);
}

其他補(bǔ)充

屬性編寫順序

推薦的樣式編寫順序

  1. 顯示屬性
    display/list-style/position/float/clear
  2. 自身屬性(盒模型)
    width/height/margin/padding/border
  3. 背景
    background
  4. 行高
    line-height
  5. 文本屬性
    color/font/text-decoration/text-align/
    text-indent/vertical-align/white-space/content
  6. 其他
    cursor/z-index/zoom
  7. CSS3屬性
    transform/transition/animation/box-shadow/border-radius
  8. 鏈接的樣式請嚴(yán)格按照如下順序添加:
    a:link -> a:visited -> a:hover -> a:active(LoVeHAte)

性能優(yōu)化

  1. 合并margin、padding、border的-left/-top/-right/-bottom的設(shè)置,盡量使用短名稱。
  2. 選擇器應(yīng)該在滿足功能的基礎(chǔ)上盡量簡短,減少選擇器嵌套,查詢消耗。但是一定要避免覆蓋全局樣式設(shè)置。
  3. 注意選擇器的性能,不要使用低性能的選擇器,例如:
    div > * {}
    ul > li > a {}
    body.profile ul.tabs.nav li a {}
  4. 禁止在css中使用*選擇符
  5. 除非必須,否則,一般有class或id的,不需要再寫上元素對應(yīng)的tag,例如:
    div#test { width: 100px; }
  6. 0后面不需要單位,比如0px可以省略成0,0.8px可以省略成.8px
  7. 如果是16進(jìn)制表示顏色,則顏色取值應(yīng)該大寫。
  8. 如果可以,顏色盡量用三位字符表示,例如#AABBCC寫成#ABC
  9. 如果沒有邊框時(shí),不要寫成border:0,應(yīng)該寫成border:none
  10. 盡量避免使用AlphaImageLoader
  11. 在保持代碼解耦的前提下,盡量合并重復(fù)的樣式,例如:
    h1 { color: black; }
    p { color: black; }
    –>
    h1,
    p { color: black; }
  12. background、font等可以縮寫的屬性,盡量使用縮寫形式
    background: color image repeat attachment position;
    font: style weight size/lineHeight family;

hack使用規(guī)范

重要原則:盡量少用hack,能不hack堅(jiān)決不hack,不允許濫用hack。
如果需要使用hack,請參考以下hack方式:

區(qū)分規(guī)則

  • IE6 * html selector { … }
  • IE7 *+html selector { … }
  • 非IE6 html>body selector { … }
  • firefox @-moz-document url-prefix() { … }
  • safari3+/chrome @media screen and (-webkit-min-device-pixel-ratio:0) { … }
  • opera @media all and (-webkit-min-device-pixel-ratio:10000), not all and (-webkit-min-device-pixel-ratio:0) { … }
  • iPhone/mobile webkit @media screen and (max-device-width: 480px) { … }

常用的 CSS 命名

頭 header
內(nèi)容 content
尾 footer
導(dǎo)航 nav
子導(dǎo)航 subnav
欄目 column
主體 main
新聞 news
版權(quán) copyright
文章列表 list
加入 joinus 合
作伙伴 partner
標(biāo)志 logo
側(cè)欄 sidebar
橫幅 banner
狀態(tài) status
菜單 menu
子菜單 submenu
滾動 scroll
搜索 search
標(biāo)簽頁 tab
提示信息 msg
小技巧 tips
標(biāo)題 title
指南 guild
服務(wù) service
熱點(diǎn) hot
下載 download
注冊 regsiter
登錄條 loginbar
按鈕 btn 投票 vote
注釋 note
友情鏈接 friend-link
外套 wrap
面包屑 bread-crumb
當(dāng)前的 current
購物車 shop
圖標(biāo) icon
文本 txt

待補(bǔ)充…


JavaScript

縮進(jìn)

使用soft tab(4個(gè)空格)。

var x = 1,
    y = 1;

if (x < y) {
    x += 10;
} else {
    x += 1;
}

單行長度

不要超過80,但如果編輯器開啟word wrap可以不考慮單行長度。

分號

以下幾種情況后需加分號:

  • 變量聲明
  • 表達(dá)式
  • return
  • throw
  • break
  • continue
  • do-while
/* var declaration */
var x = 1;

/* expression statement */
x++;

/* do-while */
do {
    x++;
} while (x < 10);

空格

以下幾種情況不需要空格:

  • 對象的屬性名后
  • 前綴一元運(yùn)算符后
  • 后綴一元運(yùn)算符前
  • 函數(shù)調(diào)用括號前
  • 無論是函數(shù)聲明還是函數(shù)表達(dá)式,'('前不要空格
  • 數(shù)組的'['后和']'前
  • 對象的'{'后和'}'前
  • 運(yùn)算符'('后和')'前
    以下幾種情況需要空格:
  • 二元運(yùn)算符前后
  • 三元運(yùn)算符'?:'前后
  • 代碼塊'{'前
  • 下列關(guān)鍵字前:else, while, catch, finally
  • 下列關(guān)鍵字后:if, else, for, while, do, switch, case, try, catch, finally, with, return, typeof
  • 單行注釋'//'后(若單行注釋和代碼同行,則'//'前也需要),多行注釋'*'后
  • 對象的屬性值前
  • for循環(huán),分號后留有一個(gè)空格,前置條件如果有多個(gè),逗號后留一個(gè)空格
  • 無論是函數(shù)聲明還是函數(shù)表達(dá)式,'{'前一定要有空格
  • 函數(shù)的參數(shù)之間
// not good
var a = {
    b :1
};

// good
var a = {
    b: 1
};

// not good
++ x;
y ++;
z = x?1:2;

// good
++x;
y++;
z = x ? 1 : 2;

// not good
var a = [ 1, 2 ];

// good
var a = [1, 2];

// not good
var a = ( 1+2 )*3;

// good
var a = (1 + 2) * 3;

// no space before '(', one space before '{', one space between function parameters
var doSomething = function(a, b, c) {
    // do something
};

// no space before '('
doSomething(item);

// not good
for(i=0;i<6;i++){
    x++;
}

// good
for (i = 0; i < 6; i++) {
    x++;
}

空行

以下幾種情況需要空行:

  • 變量聲明后(當(dāng)變量聲明在代碼塊的最后一行時(shí),則無需空行)
  • 注釋前(當(dāng)注釋在代碼塊的第一行時(shí),則無需空行)
  • 代碼塊后(在函數(shù)調(diào)用、數(shù)組、對象中則無需空行)
  • 文件最后保留一個(gè)空行
// 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;
}

var obj = {
    foo: function() {
        return 1;
    },

    bar: function() {
        return 2;
    }
};

// not need blank line 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
};

換行

換行的地方,行末必須有','或者運(yùn)算符;
以下幾種情況不需要換行:

  • 下列關(guān)鍵字后: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;

單行注釋

雙斜線后,必須跟一個(gè)空格;
縮進(jìn)與下一行代碼保持一致;
可位于一個(gè)代碼行的末尾,與代碼間隔一個(gè)空格。

if (condition) {
    // if you made it here, then all security checks passed
    allowed();
}

var zhangsan = 'zhangsan'; // one space after code

多行注釋

最少三行, '*'后跟一個(gè)空格,具體參照右邊的寫法;
建議在以下情況下使用:

  • 難于理解的代碼段
  • 可能存在錯(cuò)誤的代碼段
  • 瀏覽器特殊的HACK代碼
  • 業(yè)務(wù)邏輯強(qiáng)相關(guān)的代碼
/*
 * one space after '*'
 */
var x = 1;

文檔注釋

各類標(biāo)簽@param, @method等請參考usejsdoc和JSDoc Guide;
建議在以下情況下使用:

  • 所有常量
  • 所有函數(shù)
  • 所有類
/**
 * @func
 * @desc 一個(gè)帶參數(shù)的函數(shù)
 * @param {string} a - 參數(shù)a
 * @param {number} b=1 - 參數(shù)b默認(rèn)值為1
 * @param {string} c=1 - 參數(shù)c有兩種支持的取值</br>1—表示x</br>2—表示xx
 * @param {object} d - 參數(shù)d為一個(gè)對象
 * @param {string} d.e - 參數(shù)d的e屬性
 * @param {string} d.f - 參數(shù)d的f屬性
 * @param {object[]} g - 參數(shù)g為一個(gè)對象數(shù)組
 * @param {string} g.h - 參數(shù)g數(shù)組中一項(xiàng)的h屬性
 * @param {string} g.i - 參數(shù)g數(shù)組中一項(xiàng)的i屬性
 * @param {string} [j] - 參數(shù)j是一個(gè)可選參數(shù)
 */
function foo(a, b, c, d, g, j) {
    ...
}

引號

最外層統(tǒng)一使用單引號。

// not good
var x = "test";

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

變量命名

  • 標(biāo)準(zhǔn)變量采用駝峰式命名(除了對象的屬性外,主要是考慮到cgi返回的數(shù)據(jù))
  • 'ID'在變量名中全大寫
  • 'URL'在變量名中全大寫
  • 'Android'在變量名中大寫第一個(gè)字母
  • 'iOS'在變量名中小寫第一個(gè),大寫后兩個(gè)字母
  • 常量全大寫,用下劃線連接
  • 構(gòu)造函數(shù),大寫第一個(gè)字母
  • 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');

變量聲明

一個(gè)函數(shù)作用域中所有的變量聲明盡量提到函數(shù)首部,用一個(gè)var聲明,不允許出現(xiàn)兩個(gè)連續(xù)的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;
    }
}

函數(shù)

無論是函數(shù)聲明還是函數(shù)表達(dá)式,'('前不要空格,但'{'前一定要有空格;
函數(shù)調(diào)用括號前不需要空格;
立即執(zhí)行函數(shù)外必須包一層括號;
不要給inline function命名;
參數(shù)之間用', '分隔,注意逗號后有一個(gè)空格。

// 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
};

數(shù)組、對象

對象屬性名不需要加引號;
對象以縮進(jìn)的形式書寫,不要寫在一行;
數(shù)組、對象最后不要有逗號。

// not good
var a = {
    'b': 1
};

var a = {b: 1};

var a = {
    b: 1,
    c: 2,
};

// good
var a = {
    b: 1,
    c: 2
};

括號

下列關(guān)鍵字后必須有大括號(即使代碼塊的內(nèi)容只有一行):if, else, for, while, do, switch, try, catch, finally, with。

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

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

null

適用場景:

  • 初始化一個(gè)將來可能被賦值為對象的變量
  • 與已經(jīng)初始化的變量做比較
  • 作為一個(gè)參數(shù)為對象的函數(shù)的調(diào)用傳參
  • 作為一個(gè)返回對象的函數(shù)的返回值
    不適用場景:
  • 不要用null來判斷函數(shù)調(diào)用時(shí)有無傳參
  • 不要與未初始化的變量做比較
// 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

永遠(yuǎn)不要直接使用undefined進(jìn)行變量判斷;
使用typeof和字符串'undefined'對變量進(jìn)行判斷。

// not good
if (person === undefined) {
    ...
}

// good
if (typeof person === 'undefined') {
    ...
}

jshint

用'===', '!=='代替'==', '!=';
for-in里一定要有hasOwnProperty的判斷;
不要在內(nèi)置對象的原型上添加方法,如Array, Date;
不要在內(nèi)層作用域的代碼里聲明了變量,之后卻訪問到了外層作用域的同名變量;
變量不要先使用后聲明;
不要在一句代碼中單單使用構(gòu)造函數(shù),記得將其賦值給某個(gè)變量;
不要在同個(gè)作用域下聲明同名變量;
不要在一些不需要的地方加括號,例:delete(a.b);
不要使用未聲明的變量(全局變量需要加到.jshintrc文件的globals屬性里面);
不要聲明了變量卻不使用;
不要在應(yīng)該做比較的地方做賦值;
debugger不要出現(xiàn)在提交的代碼里;
數(shù)組中不要存在空元素;
不要在循環(huán)內(nèi)部聲明函數(shù);
不要像這樣使用構(gòu)造函數(shù),例: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;
    };
};

雜項(xiàng)

不要混用tab和space;
不要在一處使用多個(gè)tab或space;
換行符統(tǒng)一用'LF';
對上下文this的引用只能使用'_this', 'that', 'self'其中一個(gè)來命名;
行尾不要有空白字符;
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) {

}

編輯器配置和構(gòu)建檢查

sublime3插件

  1. 安裝node包
    • jscs npm install jscs -g
    • jshint npm install jshint -g
    • csscomb npm install csscomb -g
    • csslint npm install csslint -g
  2. 安裝gem包
    • scss-lint gem install scss_lint
  3. 安裝sublime3 Package Control
    • 按下 ctrl+`
    • 復(fù)制粘貼以下代碼 import urllib.request,os,hashlib; h = 'eb2297e1a458f27d836c04bb0cbaf282' + 'd0e7a3098092775ccb37ca9d6b2e4b7d'; pf = 'Package Control.sublime-package'; ipp = sublime.installed_packages_path(); urllib.request.install_opener( urllib.request.build_opener( urllib.request.ProxyHandler()) ); by = urllib.request.urlopen( 'http://packagecontrol.io/' + pf.replace(' ', '%20')).read(); dh = hashlib.sha256(by).hexdigest(); print('Error validating download (got %s instead of %s), please try manual install' % (dh, h)) if dh != h else open(os.path.join( ipp, pf), 'wb' ).write(by)
  4. 安裝sublime3插件
    • 按下 ctrl+shift+p,輸入'ip'(Install Package)
    • 輸入以下插件的名字,按順序逐個(gè)進(jìn)行安裝:
      • EditorConfig
      • Sass
      • SublimeLinter
      • SublimeLinter-jscs
      • SublimeLinter-jshint
      • SublimeLinter-csslint
      • SublimeLinter-contrib-scss-lint
      • JSFormat
      • CSScomb
  5. 插件的配置文件
    將以下配置文件分別下載后放入項(xiàng)目根目錄下:
    • EditorConfig 配置文件
    • JSCS 配置文件
    • JSHint 配置文件
      注意:全局變量需要手動加到配置文件的globals屬性里,例:
      {
      "globals": {
      "ImageHandle": true
      }
      }
    • CSSLint 配置文件
    • SCSS-Lint 配置文件
  6. 編輯器及插件設(shè)置
    • sublime3 自身
      Preferences->Setting-User,增加下面兩個(gè)配置:
      {
      "translate_tabs_to_spaces": true,
      "word_wrap": true
      }
      點(diǎn)擊右下角的Spaces->Convert Indentation to Spaces可以將文件中的所有tab轉(zhuǎn)換成空格
    • JSFormat
      Preferences->Package Settings->JSFormat->Setting-User,下載配置文件覆蓋
      配置好后格式化的默認(rèn)快捷鍵是 ctrl+alt+f
    • SublimeLinter
      右鍵->SublimeLinter->Lint Mode,有4種檢查模式,建議選擇 Load/save
      右鍵->SublimeLinter->Mark Style,建議選擇 Outline
      右鍵->SublimeLinter->Choose Gutter Theme,建議選擇 Blueberry-round
      右鍵->SublimeLinter->Open User Settings,將linter里面jscs的args改成 ["--verbose"],將linter里面csslint的ignore改成 "box-model,adjoining-classes,box-sizing,compatible-vendor-prefixes,gradients,text-indent,fallback-colors,star-property-hack,underscore-property-hack,bulletproof-font-face,font-faces,import,regex-selectors,universal-selector,unqualified-attributes,overqualified-elements,duplicate-background-images,floats,font-sizes,ids,important,outline-none,qualified-headings,unique-headings"
      當(dāng)光標(biāo)處于有錯(cuò)誤的代碼行時(shí),詳細(xì)的錯(cuò)誤信息會顯示在下面的狀態(tài)欄中
      右鍵->SublimeLinter可以看到所有的快捷鍵,其中 ctrl+k, a 可以列出所有錯(cuò)誤
    • CSScomb
      Preferences->Package Settings->CSScomb->Setting-User,下載配置文件覆蓋
      配置好后格式化的默認(rèn)快捷鍵是 ctrl+shift+c

grunt插件

  1. 在項(xiàng)目中安裝grunt插件
    • jscs npm install grunt-jscs --save-dev
    • jshint npm install grunt-contrib-jshint --save-dev
    • csslint npm install grunt-contrib-csslint --save-dev
    • scss-lint npm install grunt-scss-lint --save-dev
  2. 插件的配置文件
    * JSCS
{
    options: {
        config: true,
        verbose: true
    },
    files: {
        src: [...]
    }
}
    * JSHint
{
    options: {
        jshintrc: true
    },
    files: {
        src: [...]
    }
}
    * CSSLint
{
    options: {
        csslintrc: '.csslintrc'
    },
    files: {
        src: [...]
    }
}
    * SCSS-Lint
{
    options: {
        config: '.scss-lint.yml'
    },
    files: {
        src: [...]
    }
}

關(guān)于作者

Open sourced under MIT. Copyright (c) 2015 by lee134134134, All rights reserved.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容