前端設計與編碼規範

呂·suming發表於2019-05-14
  • Version 1.1 @Suming Lv

[TOC]目錄

1.0 命名規則

1.1 專案命名

全部採用小寫方式, 以中劃線分隔。

例:my-project-name

1.2 目錄命名

參照專案命名規則;

有複數結構時,要採用複數命名法。

例:scripts, styles, images, data-models

1.3 檔案命名

參照專案命名規則。

例:
HTML檔案命名:error-report.html
JS檔案命名:account-model.js
CSS, LESS檔案命名:retina-sprites.less

1.4 HTML命名

參照專案命名規則。

1.5 JS命名

1.5.1 函式命名

1) 獲取單個物件的方法用 get 做字首。
2) 獲取多個物件的方法用 list 做字首。
3) 獲取統計值的方法用 count 做字首。
4) 插入的方法用 save(推薦)或 insert 做字首。
5) 刪除的方法用 remove(推薦)或 delete 做字首。
6) 修改的方法用 update 做字首。

1.5.2 分頁命名

1) 傳參值:current(當前頁,預設1)、size(分頁數,預設10)
2) 響應值:total(總頁數,預設0)

1.5.3 其他

說明:任何類、方法、引數、變數,嚴控訪問範圍。過寬泛的訪問範圍,不利於模組解耦。

1.6 CSS, LESS命名

參照專案命名規則。

2.0 HTML

2.1 語法

用四個空格來代替製表符(tab)。
巢狀元素應當縮排一次(即四個空格)。
對於屬性的定義,確保全部使用雙引號,而不要使用單引號。
不要在自閉合(self-closing)元素的尾部新增斜線。
IMG元素加alt註釋。
為超過12行的元素塊或關鍵邏輯新增註釋,全部採用如下格式。

  <!-- comment Begin -->                       
	...
  <!-- comment Begin -->
複製程式碼

HTML裡插入JS時,前後需要增加空格

2.2 HTML5 Doctype

為每個 HTML 頁面的第一行新增標準模式(standard mode)的宣告,這樣能夠確保在每個瀏覽器中擁有一致的展現。

為了確保適當的繪製和觸屏縮放,需要在<head> 之中新增 viewport 後設資料標籤。

2.3 lang屬性

根據HTML5規範:應在html標籤上加上lang屬性。

2.4 字元編碼

通過宣告一個明確的字元編碼,讓瀏覽器輕鬆、快速的確定適合網頁內容的渲染方式,通常指定為'UTF-8'。

2.5 IE相容模式

<meta>標籤可以指定頁面應該用什麼版本的IE來渲染;

2.6 引入 CSS 和 JavaScript 檔案

根據 HTML5 規範,在引入 CSS 和 JavaScript 檔案時一般不需要指定 type 屬性,因為 text/css 和 text/javascript 分別是它們的預設值。

2.7 屬性順序

屬性應該按照特定的順序出現以保證易讀性;

class  
id  
name  
data-*  
src, for, type, href, value , max-length, max, min, pattern  
placeholder, title, alt  
aria-*, role  
required, readonly, disabled  
複製程式碼

[//]: # class是為高可複用元件設計的,所以應處在第一位;
[//]: # id更加具體且應該儘量少使用,所以將它放在第二位。

2.8 boolean屬性

boolean屬性指不需要宣告取值的屬性,XHTML需要每個屬性宣告取值,但是HTML5並不需要;

<input type="text" disabled>
<input type="checkbox" value="1" checked>
<select>
    <option value="1" selected>1</option>
</select>
複製程式碼

2.9 JS生成標籤

在JS檔案中生成標籤讓內容變得更難查詢,更難編輯,效能更差。應該儘量避免這種情況的出現。

2.10 減少標籤數量

在編寫HTML程式碼時,需要儘量避免多餘的父節點;
很多時候,需要通過迭代和重構來使HTML變得更少。

2.11 實用高於完美

儘量遵循HTML標準和語義,但是不應該以浪費實用性作為代價;
任何時候都要用盡量小的複雜度和儘量少的標籤來解決問題。

3.0 CSS, SCSS, LESS

3.1 縮排

使用4個空格。

3.2 分號

每個屬性宣告末尾都要加分號。

3.3 空格

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

屬性名後 多個規則的分隔符','前
!important '!'後
屬性值中'('後和')'前
行末不要有多餘的空格
以下幾種情況需要空格:

屬性值前 選擇器'>', '+', '~'前後
'{'前
!important '!'前
@else 前後
屬性值中的','後
註釋'/'後和'/'前

3.4 空行

以下幾種情況需要空行:

檔案最後保留一個空行
'}'後最好跟一個空行,包括less中巢狀的規則
屬性之間需要適當的空行,具體見屬性宣告順序

3.5 換行

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

以下幾種情況需要換行:
'{'後和'}'前
每個屬性獨佔一行
多個規則的分隔符','後

3.6 註釋

註釋統一用'/* */'(less或scss中也不要用'//')。
縮排與下一行程式碼保持一致;
可位於一個程式碼行的末尾,與程式碼間隔一個空格。

3.7 引號

最外層統一使用雙引號;
url的內容要用引號;
屬性選擇器中的屬性值需要引號。

3.8 命名

類名使用小寫字母,以中劃線分隔
id採用駝峰式命名
less或scss中的變數、函式、混合、placeholder採用駝峰式命名

3.9 屬性宣告順序

相關的屬性宣告按右邊的順序做分組處理,組之間需要有一個空行。

// 例:
.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"
  ]
]
複製程式碼

3.10 顏色

顏色16進位制用小寫字母;
顏色16進位制儘量用簡寫。

3.11 屬性簡寫

屬性簡寫需要你非常清楚屬性值的正確順序,而且在大多數情況下並不需要設定屬性簡寫中包含的所有值,所以建議儘量分開宣告會更加清晰; margin 和 padding 相反,需要使用簡寫;
常見的屬性簡寫包括:
font
background
transition
animation

3.12 媒體查詢

儘量將媒體查詢的規則靠近與他們相關的規則,不要將他們一起放到一個獨立的樣式檔案中,或者丟在文件的最底部,這樣做只會讓大家以後更容易忘記他們。

.element {
    ...
}

.element-avatar{
    ...
}

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

  .element-avatar {
      ...
  }
}
複製程式碼

3.13 LESS或SCSS相關

提交的程式碼中不要有 @debug;

宣告順序:

@extend
不包含 @content 的 @include
包含 @content 的 @include
自身屬性
巢狀規則
@import 引入的檔案不需要開頭的'_'和結尾的'.scss';

巢狀最多不能超過5層;

@extend 中使用placeholder選擇器;

去掉不必要的父級引用符號'&'。

3.14 雜項

不允許有空的規則;

元素選擇器用小寫字母;

去掉小數點前面的0;

去掉數字中不必要的小數點和末尾的0;

屬性值'0'後面不要加單位;

同個屬性不同字首的寫法需要在垂直方向保持對齊,具體參照右邊的寫法;

無字首的標準屬性應該寫在有字首的屬性後面;

不要在同個規則裡出現重複的屬性,如果重複的屬性是連續的則沒關係;

不要在一個檔案裡出現兩個相同的規則;

用 border: 0; 代替 border: none;;

選擇器不要超過4層(在scss中如果超過4層應該考慮用巢狀的方式來寫);

釋出的程式碼中不要有 @import;

儘量少用'*'選擇器。

4.0 JavaScript

4.1 縮排

使用4個空格

4.2 單行長度

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

4.3 分號

每行邏輯後面需要以分號結尾

4.4 空格

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

物件的屬性名後
字首一元運算子後
字尾一元運算子前
函式呼叫括號前
無論是函式宣告還是函式表示式,'('前不要空格
陣列的'['後和']'前
物件的'{'後和'}'前
運算子'('後和')'前

以下幾種情況需要空格:

二元運算子前後
三元運算子'?:'前後
程式碼塊'{'前
下列關鍵字前:else, while, catch, finally
下列關鍵字後:if, else, for, while, do, switch, case, try, catch, finally, with, return, typeof
單行註釋'//'後(若單行註釋和程式碼同行,則'//'前也需要),多行註釋'*'後
物件的屬性值前
for迴圈,分號後留有一個空格,前置條件如果有多個,逗號後留一個空格
無論是函式宣告還是函式表示式,'{'前一定要有空格
函式的引數之間

// 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++
}
複製程式碼

4.5 空行

以下幾種情況需要空行:

變數宣告後(當變數宣告在程式碼塊的最後一行時,則無需空行)
註釋前(當註釋在程式碼塊的第一行時,則無需空行)
程式碼塊後(在函式呼叫、陣列、物件中則無需空行)
檔案最後保留一個空行

4.6 換行

換行的地方,行末必須有','或者運算子;

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

下列關鍵字後: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
複製程式碼

4.7 單行註釋

雙斜線後,必須跟一個空格;

縮排與下一行程式碼保持一致;

可位於一個程式碼行的末尾,與程式碼間隔一個空格。

4.8 多行註釋

最少三行, '*'後跟一個空格,具體參照右邊的寫法;

建議在以下情況下使用:

難於理解的程式碼段
可能存在錯誤的程式碼段
瀏覽器特殊的HACK程式碼
業務邏輯強相關的程式碼

/*
 * one space after '*'
 */
var x = 1
複製程式碼

4.9 文件註釋

各類標籤@param, @method等請參考 JSDoc中文、usejsdoc和JSDoc Guide;

建議在以下情況下使用:

所有常量
所有函式
所有類

/**
 * @func

 * @desc 一個帶引數的函式

 * @param {string} a - 引數a

 * @param {number} b=1 - 引數b預設值為1

 * @param {string} c=1 - 引數c有兩種支援的取值  1—表示x  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) { ... }
複製程式碼

4.10 引號

最外層統一使用單引號。

4.11 變數命名

標準變數採用駝峰式命名(除了物件的屬性外,主要是考慮到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');
複製程式碼

4.12 變數宣告

一個函式作用域中所有的變數宣告儘量提到函式首部,用一個var或let宣告,不允許出現兩個連續的var或let宣告。

4.13 函式

無論是函式宣告還是函式表示式,'('前不要空格,但'{'前一定要有空格;

函式呼叫括號前不需要空格;

立即執行函式外必須包一層括號;

不要給inline function命名;

引數之間用', '分隔,注意逗號後有一個空格。

4.14 陣列、物件

物件屬性名不需要加引號;

物件以縮排的形式書寫,不要寫在一行;

陣列、物件最後不要有逗號。

4.15 括號

下列關鍵字後必須有大括號(即使程式碼塊的內容只有一行):
if, else, for, while, do, switch, try, catch, finally, with。

4.16 null

適用場景:

初始化一個將來可能被賦值為物件的變數
與已經初始化的變數做比較
作為一個引數為物件的函式的呼叫傳參
作為一個返回物件的函式的返回值

不適用場景:

不要用null來判斷函式呼叫時有無傳參
不要與未初始化的變數做比較

4.17 undefined

永遠不要直接使用undefined進行變數判斷;

使用typeof和字串'undefined'對變數進行判斷。

4.18 jshint

'===', '!=='代替'==', '!='

for-in裡一定要有hasOwnProperty的判斷;

不要在內建物件的原型上新增方法,如Array, Date;

不要在內層作用域的程式碼裡宣告瞭變數,之後卻訪問到了外層作用域的同名變數;

變數不要先使用後宣告;

不要在一句程式碼中單單使用建構函式,記得將其賦值給某個變數;

不要在同個作用域下宣告同名變數;

不要在一些不需要的地方加括號,例:delete(a.b);

不要使用未宣告的變數(全域性變數需要加到.jshintrc檔案的globals屬性裡面);

不要宣告瞭變數卻不使用;

不要在應該做比較的地方做賦值;

debugger不要出現在提交的程式碼裡;

陣列中不要存在空元素;

不要在迴圈內部宣告函式;

不要像這樣使用建構函式,例:new function () { ... }, new Object

4.19 雜項

不要混用tab和space;

不要在一處使用多個tab或space;

換行符統一用'LF';

對上下文this的引用只能使用'_this', 'that', 'self'其中一個來命名;

行尾不要有空白字元;

switch的falling through和no default的情況一定要有註釋特別說明;

不允許有空的程式碼塊。

相關文章