前端開發(fā)規(guī)范
[TOC]
<div STYLE="page-break-after: always;"></div>
一、概述
本規(guī)范旨在為前端程序的開發(fā)者提供規(guī)范化最新的指導(dǎo),可用于程序員個(gè)人編譯環(huán)境以及研發(fā)團(tuán)隊(duì)集成環(huán)境等場(chǎng)合的代碼規(guī)范化檢查。
不管有多少人共同參與同一項(xiàng)目,一定要確保每一行代碼都像是同一個(gè)人編寫的
二、方針
| 約束等級(jí) | 約束效力 | 強(qiáng)制性 |
|---|---|---|
| <font color=#f5222d>【強(qiáng)制】</font> | 違反該項(xiàng)將被認(rèn)為代碼存在嚴(yán)重缺陷 | 前端程序團(tuán)隊(duì)必須遵守 |
| <font color=#52c41a>【推薦】</font> | 違反該項(xiàng)將被認(rèn)為代碼存在輕微缺陷 | 根據(jù)具體產(chǎn)品特性的不同,選擇性地遵守 |
| <font color=#1890ff>【參考】</font> | 違反該項(xiàng)可被認(rèn)為代碼存在優(yōu)化空間 | 從產(chǎn)品持續(xù)優(yōu)化及人員技能提升的角度,參考使用 |
三、環(huán)境要求
<font color="#f5222d">【強(qiáng)制】</font>Node.js 8.9 或更高版本,你可以使用 nvm 或 nvm-windows 在一臺(tái)電腦中管理多個(gè) Node 版本
<font color=#f5222d>【強(qiáng)制】</font>使用 Visual Studio Code (VS Code) 進(jìn)行代碼編寫
<font color=#f5222d>【強(qiáng)制】</font>代碼提交前使用 VS Code 進(jìn)行格式化(不要格式引入的外部文件)
-
<font color=#f5222d>【強(qiáng)制】</font>規(guī)定 Tab 大小為 2 個(gè)空格,保證在所有環(huán)境下獲得一致展現(xiàn)
// settings.json { "editor.tabSize": 2 // ... } <font color=#f5222d>【強(qiáng)制】</font>安裝插件 Vetur( Vue開發(fā)擴(kuò)展及 Vue 文件代碼格式化)
<font color=#f5222d>【強(qiáng)制】</font>安裝插件 Prettier - Code formatter( CSS / Less / JS 等其他文件代碼格式化;Vetur 的格式化基于此插件實(shí)現(xiàn),固可以在所有文件實(shí)現(xiàn)統(tǒng)一的格式化)
- <font color=#52c41a>【推薦】</font>使用 Chrome 瀏覽器并安裝 Vue.js devtools 進(jìn)行調(diào)試
四、編碼規(guī)范
4.1 HTML / Template 編碼規(guī)范
語法
-
<font color=#f5222d>【強(qiáng)制】</font>縮進(jìn)使用兩個(gè)空格代替 Tab
- 前端代碼層級(jí)較深,使用短縮進(jìn)有利于利用屏幕空間,提升效率
- 使用兩個(gè)空格代替 Tab 可以保證在所有環(huán)境下獲得一致展現(xiàn)
<!-- not good --> <div> <div>bar</div> </div> <!-- good --> <div> <div>bar</div> </div> -
<font color=#f5222d>【強(qiáng)制】</font>嵌套元素應(yīng)當(dāng)縮進(jìn)一次(即兩個(gè)空格),同層級(jí)縮進(jìn)應(yīng)保持一致
<!-- not good --> <div> <div>bar</div> <div>bar</div> </div> <!-- good --> <div> <div>bar</div> <div>bar</div> </div> -
<font color=#f5222d>【強(qiáng)制】</font>對(duì)于屬性的定義,使用雙引號(hào),不要使用單引號(hào)
<!-- not good --> <input class='a' type=text> <!-- good --> <input class="a" type="text"> -
<font color=#f5222d>【強(qiáng)制】</font>不要省略可選的結(jié)束標(biāo)簽(closing tag)(如
</li>或</body>)省略可選的結(jié)束標(biāo)簽,雖不會(huì)違反 H5 規(guī)范;但可能會(huì)造成層級(jí)上的困擾,導(dǎo)致代碼出現(xiàn)無法預(yù)料的問題
<!-- not good --> <h1>h1 text <h2>h2 text <!-- good --> <h1>h1 text</h1> <h2>h2 text</h2> -
<font color=#f5222d>【強(qiáng)制】</font>特殊符號(hào)使用 HTML 字符實(shí)體(實(shí)體名稱對(duì)大小寫敏感),常用如下:
符號(hào) 實(shí)體編碼 空格 ? © ¥ ¥ ? ® > > < < & & -
<font color=#f5222d>【強(qiáng)制】</font>td / th 要在 tr 里面,li 要在 ul / ol 里面
<!-- not good --> <table> <td>test</td> </table> <!-- good --> <table> <tr> <td>test</td> </tr> </table> -
<font color=#f5222d>【強(qiáng)制】</font>ul / ol 的直接子元素只能是 li,不能包含其他元素
<!-- not good --> <ul> <span>123</span> <li>a</li> <li>b</li> </ul> -
<font color=#f5222d>【強(qiáng)制】</font>行內(nèi)元素里面不可使用塊級(jí)元素
a 標(biāo)簽是一個(gè)行內(nèi)元素,行內(nèi)元素里面套了一個(gè) div 的標(biāo)簽,這樣可能會(huì)導(dǎo)致 a 標(biāo)簽無法正常點(diǎn)擊
<!-- not good --> <a href="../test"> <div></div> </a>可以使用如下代碼進(jìn)行修復(fù):
<a href="../test" style="display: block"> <div></div> </a> <font color=#f5222d>【強(qiáng)制】</font>不使用自定義標(biāo)簽,會(huì)與Vue組件系統(tǒng)的自定義組件沖突
-
<font color=#f5222d>【強(qiáng)制】</font>不使用重復(fù)屬性,重復(fù)的屬性只會(huì)取第一個(gè)
<!-- error --> <input class="a" type="text" class="b"> <!-- good --> <input class="a b" type="text"> -
<font color=#f5222d>【強(qiáng)制】</font>不要在https的鏈接里寫http的圖片
只要https的網(wǎng)頁請(qǐng)求了一張http的圖片,就會(huì)導(dǎo)致瀏覽器地址欄左邊的小鎖沒有了,一般不要寫死,寫成根據(jù)當(dāng)前域名的協(xié)議去加載,用//開頭:
<img src="http://static.chimeroi.com/hello-world.jpg"> -
<font color=#52c41a>【推薦】</font>不要在自閉合(self-closing)元素的尾部添加斜線( HTML5 規(guī)范中說明這是可選的)
<!-- not good --> <img src="logo.png" alt /> <!-- good --> <img src="logo.png" alt> -
<font color=#52c41a>【推薦】</font>不使用屬性設(shè)置樣式(
img,table等元素)<!-- not good --> <img src="test.jpg" alt width="400" height="300"> <!-- good --> <img src="test.jpg" style="width:400px;height:300px;"> -
<font color=#1890ff>【參考】</font>自定義屬性要以data-開頭
自己添加的非標(biāo)準(zhǔn)的屬性要以data-開頭,否則w3c validator會(huì)認(rèn)為是不規(guī)范的<!-- not good --> <div count="5"></div> <!-- good --> <div data-count="5"></div>
HTML5 doctype
<font color=#f5222d>【強(qiáng)制】</font>為每個(gè) HTML 頁面添加標(biāo)準(zhǔn)模式(standard mode)的聲明,確保在每個(gè)瀏覽器中擁有一致的展現(xiàn)
<!DOCTYPE html>
<html>
...
語言屬性
<font color=#f5222d>【強(qiáng)制】</font>為每個(gè) HTML 頁面根元素添加 lang 屬性
根據(jù) HTML5 規(guī)范:
強(qiáng)烈建議為 html 根元素指定 lang 屬性,從而為文檔設(shè)置正確的語言。這將有助于語音合成工具確定其所應(yīng)該采用的發(fā)音,有助于翻譯工具確定其翻譯時(shí)所應(yīng)遵守的規(guī)則等等。
<html lang="zh-CN">
<!-- ... -->
</html>
字符編碼
<font color=#f5222d>【強(qiáng)制】</font>通過聲明一個(gè)明確的字符編碼,讓瀏覽器輕松、快速的確定網(wǎng)頁內(nèi)容渲染方式,通常指定為'UTF-8'
<html>
<head>
<meta charset="UTF-8">
</head>
...
引入 CSS 和 JavaScript 文件
<font color=#f5222d>【強(qiáng)制】</font>根據(jù) HTML5 規(guī)范,在引入 CSS 和 JavaScript 文件時(shí)不需要指定 type 屬性,因?yàn)?text/css 和 text/javascript 分別是它們的默認(rèn)值
<!-- 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>
減少標(biāo)簽的數(shù)量
<font color=#52c41a>【推薦】</font>編寫 HTML 代碼時(shí),盡量避免多余的層級(jí)
<!-- not good -->
<span class="avatar">
<img src="...">
</span>
<!-- good -->
<img class="avatar" src="...">
屬性順序
<font color=#1890ff>【參考】</font>屬性應(yīng)該按照特定的順序出現(xiàn)以保證易讀性
classidnamedata-*-
src,for,type,href,value,max-length,max,min,pattern -
placeholder,title,alt -
aria-*,role -
required,readonly,disabled
語義化
<font color=#1890ff>【參考】</font>盡量遵循 HTML 標(biāo)準(zhǔn)和語義,但是不要以犧牲實(shí)用性為代價(jià);任何時(shí)候都要盡量使用最少的標(biāo)簽并保持最小的復(fù)雜度。
4.2 CSS / Less 編碼規(guī)范
命名
<font color=#f5222d>【強(qiáng)制】</font>類名使用小寫字母,以中劃線分隔
<font color=#f5222d>【強(qiáng)制】</font>id 采用駝峰式命名
-
<font color=#f5222d>【強(qiáng)制】</font>less 中的變量、函數(shù)、混合等采用駝峰式命名
@mainFontColor: #444; #companyName, .company-name { color: @mainFontColor; }
語法
-
<font color=#f5222d>【強(qiáng)制】</font>所有聲明語句都應(yīng)當(dāng)以分號(hào)結(jié)尾
最后一條聲明語句后面的分號(hào)是可選的,但是,如果省略這個(gè)分號(hào),你的代碼可能更易出錯(cuò)/* error */ .selector { font-size: 15px color: red } /* not good */ .selector { font-size: 15px; color: red } /* good */ .selector { font-size: 15px; color: red; } <font color=#f5222d>【強(qiáng)制】</font>避免為 0 值指定單位,例如,用
margin: 0;代替margin: 0px;-
<font color=#f5222d>【強(qiáng)制】</font>為選擇器中的屬性添加雙引號(hào),例如,
input[type="text"];
某些情況下是可選的,但是,為了代碼的一致性,建議都加上雙引號(hào)/* not good */ .selector[type=text] { /* ... */ } /* good */ .selector[type="text"] { /* ... */ } <font color=#f5222d>【強(qiáng)制】</font>十六進(jìn)制值應(yīng)該全部小寫,例如,
#f3f6fa<font color=#f5222d>【強(qiáng)制】</font>不出現(xiàn)空的規(guī)則(聲明塊中沒有聲明語句)
<font color=#f5222d>【強(qiáng)制】</font>不要設(shè)置太大的z-index(一個(gè)正常的系統(tǒng)的層級(jí)關(guān)系在 10 以內(nèi)就能完成)
-
<font color=#f5222d>【強(qiáng)制】</font>多寫注釋,且多使用句子進(jìn)行描述而不是詞語
/* 為了去除輸入框和表單點(diǎn)擊時(shí)的灰色背景 */ input, form { -webkit-tap-highlight-color: rgba(255, 255, 255, 0); } <font color=#52c41a>【推薦】</font>不要使用
*選擇器<font color=#52c41a>【推薦】</font>適當(dāng)使用
:before和:after來畫頁面的一些視覺上的輔助性元素,如三角形、短的分隔線、短豎線等,可以減少頁面上沒有用的標(biāo)簽<font color=#52c41a>【推薦】</font>選擇器不要超過4層(在 Less 中避免嵌套超過 4 層)
<font color=#52c41a>【推薦】</font>用
border: 0;代替border: none;<font color=#52c41a>【推薦】</font>使用簡(jiǎn)寫形式的十六進(jìn)制值,例如,用
#fff代替#ffffff<font color=#52c41a>【推薦】</font>對(duì)于屬性值或顏色參數(shù),省略小于 1 的小數(shù)前面的 0 (例如,
.5代替0.5;-.5px代替-0.5px)
代碼風(fēng)格
此處大部分工作將由代碼格式化工具完成(參見環(huán)境要求),一般無需考慮
<font color=#f5222d>【強(qiáng)制】</font>縮進(jìn)使用兩個(gè)空格代替 Tab
-
<font color=#f5222d>【強(qiáng)制】</font>為選擇器分組時(shí),將單獨(dú)的選擇器單獨(dú)放在一行
/* not good */ .selector, .selector-secondary, .selector[type=text] { /* ... */ } /* good */ .selector, .selector-secondary, .selector[type="text"] { /* ... */ } <font color=#f5222d>【強(qiáng)制】</font>聲明塊的左花括號(hào)前添加一個(gè)空格
<font color=#f5222d>【強(qiáng)制】</font>聲明塊的右花括號(hào)應(yīng)當(dāng)單獨(dú)成行
<font color=#f5222d>【強(qiáng)制】</font>每條聲明語句的
:后應(yīng)該插入一個(gè)空格-
<font color=#f5222d>【強(qiáng)制】</font>每條樣式聲明應(yīng)該獨(dú)占一行
/* not good */ .selector { font-size: 15px; color: red; } /* good */ .selector { font-size: 15px; color: red; } -
<font color=#f5222d>【強(qiáng)制】</font>對(duì)于以逗號(hào)分隔的屬性值,每個(gè)逗號(hào)后面都應(yīng)該插入一個(gè)空格(例如,
box-shadow,transition)/* not good */ .selector { transition: border .2s,color .3s,padding .4s; } /* good */ .selector { transition: border .2s, color .3s, padding .4s; } <font color=#f5222d>【強(qiáng)制】</font>
!important前插入一個(gè)空格<font color=#f5222d>【強(qiáng)制】</font>注釋:
//后插入一個(gè)空格,/*后插入一個(gè)空格,*/前插入一個(gè)空格<font color=#f5222d>【強(qiáng)制】</font>Less 的操作符,在圓括號(hào)中的數(shù)學(xué)計(jì)算表達(dá)式的數(shù)值、變量和操作符之間均添加一個(gè)空格
<font color=#52c41a>【推薦】</font>注釋統(tǒng)一用
/* */( Less 中也不要用//)
樣式兼容性
<font color=#f5222d>【強(qiáng)制】</font>當(dāng)使用一些較新的 CSS3 語法時(shí),應(yīng)注意添加瀏覽器前綴( FAIS 2 打包工具包含 CSS 預(yù)處理,固無需考慮此條)
-
<font color=#52c41a>【推薦】</font>不要使用 input 的
line-height來做垂直居中
設(shè)置line-height為一個(gè)很高的值會(huì)導(dǎo)致 Safari 瀏覽器的輸入光標(biāo)變得巨大 (與line-height等高)/* not good */ input { height: 40px; line-height: 40px; } /* good */ input { height: 20px; line-height: 20px; padding: 10px 0; }
選擇器權(quán)重(樣式覆蓋)
權(quán)重的基本規(guī)則:
- 相同的權(quán)重:以后面出現(xiàn)的選擇器為最后規(guī)則
- 不同的權(quán)重,權(quán)重值高則生效
詳細(xì)了解權(quán)重計(jì)算方法
- <font color=#f5222d>【強(qiáng)制】</font>非通用樣式使用嵌套方式進(jìn)行編寫,避免影響其他自己不了解樣式,造成樣式覆蓋
- <font color=#52c41a>【推薦】</font>Vue 中樣式謹(jǐn)慎使用 scoped,會(huì)影響樣式選擇器性能,請(qǐng)使用第一點(diǎn)進(jìn)行特有樣式編寫
- <font color=#52c41a>【推薦】</font>樣式需要修改時(shí),盡量找到原樣式聲明進(jìn)行修改
- <font color=#f5222d>【強(qiáng)制】</font>無法修改原樣式聲明時(shí),應(yīng)通過權(quán)重關(guān)系,編寫權(quán)重更高的樣式進(jìn)行覆蓋
- <font color=#f5222d>【強(qiáng)制】</font>不使用
!important,除非原樣式使用內(nèi)聯(lián)樣式或!important且無法直接修改
聲明簡(jiǎn)寫
-
<font color=#52c41a>【推薦】</font>當(dāng)你不確定自己寫的屬性會(huì)否影響到其他屬性時(shí),應(yīng)避免使用簡(jiǎn)寫
/* error */ .element { margin: 0 0 10px; background: red; background: url("image.jpg"); border-radius: 3px 3px 0 0; } /* good */ .element { margin-bottom: 10px; background-color: red; background-image: url("image.jpg"); border-top-left-radius: 3px; border-top-right-radius: 3px; } -
<font color=#52c41a>【推薦】</font>當(dāng)你確定自己的聲明不會(huì)影響到其他屬性時(shí),請(qǐng)使用簡(jiǎn)寫提升代碼簡(jiǎn)潔性
/* not good */ .element { padding-top: 10px; padding-right: 20px; padding-bottom: 15px; padding-left: 20px; } /* good */ .element { padding: 10px 20px 15px; }
CSS動(dòng)畫
- <font color=#52c41a>【推薦】</font>不要使用all屬性做動(dòng)畫
使用transition做動(dòng)畫的時(shí)候不要使用all所有屬性,在有一些瀏覽器上面可能會(huì)有一些問題,如下:
transition: all 2s linear;
在Safari上面可能會(huì)有一些奇怪的抖動(dòng),正確的做法是要用哪個(gè)屬性做動(dòng)畫就寫哪個(gè),如果有多個(gè)就用隔開,如下代碼所示:
transition: transform 2s linear, opacity 2s linear;
- <font color=#52c41a>【推薦】</font>位移動(dòng)畫使用 transform 替代 position (提升動(dòng)畫性能)
- <font color=#52c41a>【推薦】</font>使用 CSS 動(dòng)畫替代 JS 動(dòng)畫
聲明順序
<font color=#1890ff>【參考】</font>相關(guān)的屬性聲明按以下順序做分組處理,組之間需要有一個(gè)空行
Positioning(影響其他元素和自身位置相關(guān)聲明)
Box model(自身盒模型相關(guān)聲明)
Typographic(文本相關(guān)聲明)
Visual(自身樣式)
-
Misc(其他聲明)
.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; }
4.3 JavaScript 編碼規(guī)范
命名
<font color=#f5222d>【強(qiáng)制】</font>標(biāo)準(zhǔn)變量采用駝峰式命名(考慮與后臺(tái)交換數(shù)據(jù)的情況,對(duì)象屬性可靈活命名)
<font color=#f5222d>【強(qiáng)制】</font>常量全大寫,用下劃線連接
-
<font color=#f5222d>【強(qiáng)制】</font>變量名不應(yīng)過短,要能準(zhǔn)確完整地描述該變量所表述的事物
不好的變量名 好的變量名 inp input, priceInput day1, day2, param1 today, tomorrow id userId, orderId obj orderData, houseInfos tId removeMsgTimerId handler submitHandler, searchHandler <font color=#f5222d>【強(qiáng)制】</font>變量名不要使用計(jì)算機(jī)術(shù)語,如 texareaData,應(yīng)該取和業(yè)務(wù)相關(guān)的名字,如 leaveMsg
<font color=#f5222d>【強(qiáng)制】</font>變量名的對(duì)仗要明確,如 up/down、begin/end、opened/closed、visible/invisible、scource/target
-
<font color=#f5222d>【強(qiáng)制】</font>變量名使用正確的語法
不要使用中文拼音,如 shijianchuo 應(yīng)改成 timestamp ;
如果是復(fù)數(shù)的話加 s,或者加上 List,如 orderList、menuItems;
而過去式的加上 ed,如 updated/found 等;
如果正在進(jìn)行的加上 ing,如 calling; -
<font color=#52c41a>【推薦】</font>使用臨時(shí)變量時(shí)請(qǐng)結(jié)合實(shí)際需要進(jìn)行變量命名
有些喜歡取temp和obj之類的變量,如果這種臨時(shí)變量在兩行代碼內(nèi)就用完了,接下來的代碼就不會(huì)再用了,還是可以接受的,如交換數(shù)組的兩個(gè)元素。但是有些人取了個(gè)temp,接下來十幾行代碼都用到了這個(gè)temp,這個(gè)就讓人很困惑了。所以應(yīng)該盡量少用temp類的變量
// not good let temp = 10; let leftPosition = currentPosition + temp, topPosition = currentPosition - temp; // good let adjustSpace = 10; let leftPosition = currentPosition + adjustSpace, topPosition = currentPosition - adjustSpace; -
<font color=#52c41a>【推薦】</font>波爾變量可以結(jié)合實(shí)際語境使用 done/found/successs/ok/available/complete 等修飾詞
// good let ajaxDone = true, fileFound = false, resourceUpdated = true; <font color=#52c41a>【推薦】</font>波爾變量名應(yīng)使用肯定的布爾變量名,不要使用否定的名詞,如 notOk、notReady,因?yàn)榉穸ǖ脑~取反的時(shí)候就會(huì)比較奇怪,如
if (!notOk)
語法
<font color=#f5222d>【強(qiáng)制】</font>變量不要先使用后聲明
<font color=#f5222d>【強(qiáng)制】</font>不要聲明了變量卻不使用
<font color=#f5222d>【強(qiáng)制】</font>不要在同個(gè)作用域下聲明同名變量
-
<font color=#f5222d>【強(qiáng)制】</font>一個(gè)函數(shù)作用域中所有的變量聲明盡量提到函數(shù)首部,可根據(jù)代碼進(jìn)行分組,但不允許出現(xiàn)兩個(gè)連續(xù)的變量聲明
// not good let registerForm = null; let question = ""; let calculateResult = 0; // good let registerForm = null, question = "", calculateResult = 0; -
<font color=#f5222d>【強(qiáng)制】</font>為了快速知曉變量類型,聲明變量時(shí)要賦值
// not good let registerForm, question, calculateResult; // good let registerForm = null, question = "", calculateResult = 0; -
<font color=#f5222d>【強(qiáng)制】</font>單一函數(shù)的返回值類型要確定(如下無法確定該函數(shù)的最終返回類型)
// not good function calculatePrice(seatCount){ if (seatCount <= 0) { return ""; } else { return seatCount * 79; } } <font color=#f5222d>【強(qiáng)制】</font>debugger不要出現(xiàn)在提交的代碼里
-
<font color=#52c41a>【推薦】</font>使用
===代替==,!==代替!=(==會(huì)自動(dòng)進(jìn)行類型轉(zhuǎn)換,可能會(huì)出現(xiàn)奇怪的結(jié)果)null == undefined //true '' == '0' //false 0 == '' //true 0 == '0' //true ' \t\r\n ' == 0 //true new String("abc") == "abc" //true new Boolean(true) == true //true true == 1 //true -
<font color=#52c41a>【推薦】</font>使用三目運(yùn)算代替簡(jiǎn)單的 if-else
// not good let seatDiscount = 100; if (seat < 5) { seatDiscount = 90; } else if(seat < 10) { seatDiscount = 80; } else { seatDiscount = 70; } // good let seatDiscount = seat < 5 ? 90 : seat < 10 ? 80 : 70; <font color=#52c41a>【推薦】</font>使用
let定義變量,const定義常量-
<font color=#52c41a>【推薦】</font>使用箭頭函數(shù)取代簡(jiǎn)單的函數(shù)
// not good let _this = this; setTimeout(function() { _this.foo = "bar"; }, 2000); // good setTimeout(() => this.foo = "bar", 2000); <font color=#52c41a>【推薦】</font>在必要的地方添加非空判斷以提高代碼的穩(wěn)健性
<font color=#52c41a>【推薦】</font>將復(fù)雜的函數(shù)分解成多個(gè)子函數(shù),方便維護(hù)和復(fù)用
代碼風(fēng)格
此處大部分工作將由代碼格式化工具完成(參見環(huán)境要求),一般無需考慮
- <font color=#f5222d>【強(qiáng)制】</font>縮進(jìn)使用兩個(gè)空格代替 Tab
- <font color=#f5222d>【強(qiáng)制】</font>統(tǒng)一使用雙引號(hào)
""(與 Prettier 默認(rèn)格式化配置持一致) - <font color=#f5222d>【強(qiáng)制】</font>以下幾種情況后需加分號(hào)
;變量聲明
表達(dá)式
return
throw
break
continue
do-while
- <font color=#f5222d>【強(qiáng)制】</font>以下幾種情況不需要空格:
- 對(duì)象的屬性名后
- 前綴一元運(yùn)算符后
- 后綴一元運(yùn)算符前
- 函數(shù)調(diào)用括號(hào)前
- 無論是函數(shù)聲明還是函數(shù)表達(dá)式,'('前不要空格
- 數(shù)組的'['后和']'前
- 對(duì)象的'{'后和'}'前
- 運(yùn)算符'('后和')'前
- <font color=#f5222d>【強(qiáng)制】</font>以下幾種情況需要空格:
- 二元運(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 - 單行注釋'//'后(若單行注釋和代碼同行,則'//'前也需要),多行注釋'*'后
- 對(duì)象的屬性值前
- for循環(huán),分號(hào)后留有一個(gè)空格,前置條件如果有多個(gè),逗號(hào)后留一個(gè)空格
- 無論是函數(shù)聲明還是函數(shù)表達(dá)式,'{'前一定要有空格
- 函數(shù)的參數(shù)之間
數(shù)組、對(duì)象
<font color=#f5222d>【強(qiáng)制】</font>對(duì)象屬性名不需要加引號(hào)
<font color=#f5222d>【強(qiáng)制】</font>對(duì)象以縮進(jìn)的形式書寫,不要寫在一行
<font color=#f5222d>【強(qiáng)制】</font>數(shù)組中不要存在空元素
<font color=#f5222d>【強(qiáng)制】</font>不要用
for in循環(huán)數(shù)組-
<font color=#52c41a>【推薦】</font>數(shù)組、對(duì)象最后不要有逗號(hào)
// not good let a = { 'b': 1 }; let a = { b: 1 }; let a = { b: 1, c: 2, }; // good let a = { b: 1, c: 2 };
使用 null
<font color=#f5222d>【強(qiáng)制】</font>正確使用 null
適用場(chǎng)景:
- 初始化一個(gè)將來可能被賦值為對(duì)象的變量
- 與已經(jīng)初始化的變量做比較
- 作為一個(gè)參數(shù)為對(duì)象的函數(shù)的調(diào)用傳參
- 作為一個(gè)返回對(duì)象的函數(shù)的返回值
不要用null來判斷函數(shù)調(diào)用時(shí)有無傳參
-
不要與未初始化的變量做比較
// not good function test(a, b) { if (b === null) { // not mean b is not supply // ... } } let a; if (a === null) { // ... } // good let a = null; if (a === null) { // ... }
使用 undefined
<font color=#f5222d>【強(qiáng)制】</font>正確使用 undefined
不要給變量賦值 undefined(undefined 本身就表示一個(gè)變量未定義)
不要直接使用 undefined 進(jìn)行變量判斷
-
使用
typeof和字符串 'undefined' 對(duì)變量進(jìn)行判斷// not good if (person === undefined) { // ... } // good if (typeof person === 'undefined') { // ... }
文檔注釋
<font color=#1890ff>【參考】</font>各類標(biāo)簽 @param, @method 等請(qǐng)參考 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è)對(duì)象
* @param {string} d.e - 參數(shù)d的e屬性
* @param {string} d.f - 參數(shù)d的f屬性
* @param {object[]} g - 參數(shù)g為一個(gè)對(duì)象數(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) {
// ...
}
4.4 Vue 組件編碼規(guī)范
命名
-
<font color=#f5222d>【強(qiáng)制】</font>組件名應(yīng)該始終是多個(gè)單詞的,根組件
App除外// not good Vue.component('todo', { // ... }) export default { name: 'Todo', // ... } // good Vue.component('todo-item', { // ... }) export default { name: 'TodoItem', // ... } -
<font color=#f5222d>【強(qiáng)制】</font>單文件組件的文件名應(yīng)該要么始終是單詞大寫開頭( PascalCase ),要么始終是橫線連接( kebab-case )
// not good components/ |- mycomponent.vue components/ |- myComponent.vue // good components/ |- MyComponent.vue components/ |- my-component.vue -
<font color=#52c41a>【推薦】</font>應(yīng)用特定樣式和約定的基礎(chǔ)組件 (也就是展示類的、無邏輯的或無狀態(tài)的組件) 應(yīng)該全部以一個(gè)特定的前綴開頭,比如 Base、App 或 V
// not good components/ |- MyButton.vue |- VueTable.vue |- Icon.vue // good components/ |- BaseButton.vue |- BaseTable.vue |- BaseIcon.vue components/ |- AppButton.vue |- AppTable.vue |- AppIcon.vue components/ |- VButton.vue |- VTable.vue |- VIcon.vue -
<font color=#52c41a>【推薦】</font>只應(yīng)該擁有單個(gè)活躍實(shí)例的單例組件應(yīng)該以 The 前綴命名,以示其唯一性
單例組件不意味著組件只可用于一個(gè)單頁面,而是每個(gè)頁面只使用一次。這些組件永遠(yuǎn)不接受任何 prop,因?yàn)樗鼈兪菫槟愕膽?yīng)用定制的,而不是它們?cè)谀愕膽?yīng)用中的上下文。如果你發(fā)現(xiàn)有必要添加 prop,那就表明這實(shí)際上是一個(gè)可復(fù)用的組件,只是目前在每個(gè)頁面里只使用一次
// not good components/ |- Heading.vue |- MySidebar.vue // good components/ |- TheHeading.vue |- TheSidebar.vue -
<font color=#f5222d>【強(qiáng)制】</font>和父組件緊密耦合的子組件應(yīng)該以父組件名作為前綴命名
如果一個(gè)組件只在某個(gè)父組件的場(chǎng)景下有意義,這層關(guān)系應(yīng)該體現(xiàn)在其名字上。因?yàn)榫庉嬈魍ǔ?huì)按字母順序組織文件,所以這樣做可以把相關(guān)聯(lián)的文件排在一起
// not good components/ |- TodoList.vue |- TodoItem.vue |- TodoButton.vue components/ |- SearchSidebar.vue |- NavigationForSearchSidebar.vue //good components/ |- TodoList.vue |- TodoListItem.vue |- TodoListItemButton.vue components/ |- SearchSidebar.vue |- SearchSidebarNavigation.vue -
<font color=#f5222d>【強(qiáng)制】</font>組件名應(yīng)該以高級(jí)別的 (通常是一般化描述的) 單詞開頭,以描述性的修飾詞結(jié)尾
// not good components/ |- ClearSearchButton.vue |- ExcludeFromSearchInput.vue |- LaunchOnStartupCheckbox.vue |- RunSearchButton.vue |- SearchInput.vue |- TermsCheckbox.vue // good components/ |- SearchButtonClear.vue |- SearchButtonRun.vue |- SearchInputQuery.vue |- SearchInputExcludeGlob.vue |- SettingsCheckboxTerms.vue |- SettingsCheckboxLaunchOnStartup.vue -
<font color=#52c41a>【推薦】</font>組件名應(yīng)該傾向于完整單詞而不是縮寫
// not good components/ |- SdSettings.vue |- UProfOpts.vue // good components/ |- StudentDashboardSettings.vue |- UserProfileOptions.vue
語法
-
<font color=#f5222d>【強(qiáng)制】</font>組件的
data必須是一個(gè)函數(shù)(除了new Vue外的任何地方)// not good export default { data: { foo: 'bar' } } // good export default { data () { return { foo: 'bar' } } } -
<font color=#f5222d>【強(qiáng)制】</font>
prop的定義應(yīng)該盡量詳細(xì),至少需要指定其類型// not good // 這樣做只有開發(fā)原型系統(tǒng)時(shí)可以接受 props: ['status'] // good props: { status: String } // better props: { status: { type: String, required: true, validator: function (value) { return [ 'syncing', 'synced', 'version-conflict', 'error' ].indexOf(value) !== -1 } } } -
<font color=#f5222d>【強(qiáng)制】</font>為
v-for設(shè)置鍵值;在組件上總是必須用key配合v-for,以便維護(hù)內(nèi)部組件及其子樹的狀態(tài)在組件上總是必須用 key 配合 v-for,以便維護(hù)內(nèi)部組件及其子樹的狀態(tài)
-
<font color=#f5222d>【強(qiáng)制】</font>不要把
v-if和v-for同時(shí)用在同一個(gè)元素上(大部分時(shí)候你可以使用計(jì)算屬性實(shí)現(xiàn))<!-- not good --> <ul> <li v-for="user in users" v-if="user.isActive" :key="user.id" > {{ user.name }} </li> </ul> <!-- good --> <ul> <li v-for="user in activeUsers" :key="user.id" > {{ user.name }} </li> </ul> -
<font color=#f5222d>【強(qiáng)制】</font>自閉合組件在單文件組件、字符串模板和 JSX 中沒有內(nèi)容的組件應(yīng)該是自閉合的;但在 DOM 模板里不要這樣做
<!-- not good --> <!-- 在單文件組件、字符串模板和 JSX 中 --> <MyComponent></MyComponent> <!-- 在 DOM 模板中 --> <my-component/> <!-- good --> <!-- 在單文件組件、字符串模板和 JSX 中 --> <MyComponent/> <!-- 在 DOM 模板中 --> <my-component></my-component> -
<font color=#f5222d>【強(qiáng)制】</font>模版中的組件名大小寫在單文件組件和字符串模板中組件名應(yīng)該總是 PascalCase 的;但是在 DOM 模板中總是 kebab-case 的
<!-- not good --> <!-- 在單文件組件和字符串模板中 --> <mycomponent/> <!-- 在單文件組件和字符串模板中 --> <myComponent/> <!-- 在 DOM 模板中 --> <MyComponent></MyComponent> <!-- good --> <!-- 在單文件組件和字符串模板中 --> <MyComponent/> <!-- 在 DOM 模板中 --> <my-component></my-component>亦或者
<!-- 在所有地方 --> <my-component></my-component> -
<font color=#f5222d>【強(qiáng)制】</font>JS/JSX 中的組件名應(yīng)該始終是 PascalCase 的
// not good Vue.component('myComponent', { // ... }) import myComponent from './MyComponent.vue' export default { name: 'myComponent', // ... } export default { name: 'my-component', // ... } // good Vue.component('MyComponent', { // ... }) import MyComponent from './MyComponent.vue' export default { name: 'MyComponent', // ... } -
<font color=#52c41a>【推薦】</font>Prop 名大小寫,在聲明
prop的時(shí)候,其命名應(yīng)該始終使用 camelCase,而在模板和 JSX 中應(yīng)該始終使用 kebab-case// not good props: { 'greeting-text': String } <WelcomeMessage greetingText="hi"/> // good props: { greetingText: String } <WelcomeMessage greeting-text="hi"/> -
<font color=#52c41a>【推薦】</font>多個(gè)特性的元素應(yīng)該分多行撰寫,每個(gè)特性一行(此項(xiàng) Vetur 插件會(huì)自動(dòng)根據(jù)行寬閾值進(jìn)行自動(dòng)折行處理,一般無需考慮)
<!-- not good --> <img src="https://vuejs.org/images/logo.png" alt="Vue Logo"> <MyComponent foo="a" bar="b" baz="c"/> <!-- good --> <img src="https://vuejs.org/images/logo.png" alt="Vue Logo" > <MyComponent foo="a" bar="b" baz="c" /> -
<font color=#f5222d>【強(qiáng)制】</font>組件模板應(yīng)該只包含簡(jiǎn)單的表達(dá)式,復(fù)雜的表達(dá)式則應(yīng)該重構(gòu)為計(jì)算屬性或方法
// not good {{ fullName.split(' ').map(function (word) { return word[0].toUpperCase() + word.slice(1) }).join(' ') }} // good // 在模板中 {{ normalizedFullName }} // 復(fù)雜表達(dá)式已經(jīng)移入一個(gè)計(jì)算屬性 computed: { normalizedFullName: function () { return this.fullName.split(' ').map(function (word) { return word[0].toUpperCase() + word.slice(1) }).join(' ') } } -
<font color=#52c41a>【推薦】</font>應(yīng)該把復(fù)雜計(jì)算屬性分割為盡可能多的更簡(jiǎn)單的屬性
// not good computed: { finalPrice: function () { var basePrice = this.manufactureCost / (1 - this.profitMargin) return ( basePrice - basePrice * (this.discountPercent || 0) ) } } // good computed: { basePrice: function () { return this.manufactureCost / (1 - this.profitMargin) }, discount: function () { return this.basePrice * (this.discountPercent || 0) }, finalPrice: function () { return this.basePrice - this.discount } } -
<font color=#f5222d>【強(qiáng)制】</font>非空 HTML 特性值應(yīng)該始終帶引號(hào)
<!-- not good --> <input type=text> <AppSidebar :style={width:sidebarWidth+'px'}> <!-- good --> <input type="text"> <AppSidebar :style="{ width: sidebarWidth + 'px' }"> <font color=#f5222d>【強(qiáng)制】</font>可簡(jiǎn)寫指令需要縮寫 (用
:表示v-bind:和用@表示v-on:)
代碼風(fēng)格
此處大部分工作將由代碼格式化工具完成(參見環(huán)境要求),一般無需考慮
具體要求見 4.1 ,4.2,4.3 中代碼風(fēng)格部分
組件/實(shí)例的選項(xiàng)的順序
<font color=#1890ff>【參考】</font>組件/實(shí)例的選項(xiàng)應(yīng)該有統(tǒng)一的順序,這是我們推薦的組件選項(xiàng)默認(rèn)順序:
-
副作用 (觸發(fā)組件外的影響)
el
-
全局感知 (要求組件以外的知識(shí))
nameparent
-
組件類型 (更改組件的類型)
functional
-
模板修改器 (改變模板的編譯方式)
delimiterscomments
-
模板依賴 (模板內(nèi)使用的資源)
componentsdirectivesfilters
-
組合 (向選項(xiàng)里合并屬性)
extendsmixins
-
接口 (組件的接口)
inheritAttrsmodel-
props/propsData
-
本地狀態(tài) (本地的響應(yīng)式屬性)
datacomputed
-
事件 (通過響應(yīng)式事件觸發(fā)的回調(diào))
watch- 生命周期鉤子 (按照它們被調(diào)用的順序)
beforeCreatecreatedbeforeMountmountedbeforeUpdateupdatedactivateddeactivatedbeforeDestroydestroyed
-
非響應(yīng)式的屬性 (不依賴響應(yīng)系統(tǒng)的實(shí)例屬性)
methods
-
渲染 (組件輸出的聲明式描述)
-
template/render renderError
-
元素特性的順序
<font color=#1890ff>【參考】</font>元素 (包括組件) 的特性應(yīng)該有統(tǒng)一的順序,這是我們?yōu)樵靥匦酝扑]的默認(rèn)順序:
-
定義 (提供組件的選項(xiàng))
is
-
列表渲染 (創(chuàng)建多個(gè)變化的相同元素)
v-for
-
條件渲染 (元素是否渲染/顯示)
v-ifv-else-ifv-elsev-showv-cloak
-
渲染方式 (改變?cè)氐匿秩痉绞?
v-prev-once
-
全局感知 (需要超越組件的知識(shí))
id
-
唯一的特性 (需要唯一值的特性)
refkeyslot
-
雙向綁定 (把綁定和事件結(jié)合起來)
v-model
- 其它特性 (所有普通的綁定或未綁定的特性)
-
事件 (組件事件監(jiān)聽器)
v-on
-
內(nèi)容 (覆寫元素的內(nèi)容)
v-htmlv-text
單文件組件的頂級(jí)元素的順序
<font color=#f5222d>【強(qiáng)制】</font>單文件組件應(yīng)該總是按照 <template>、<script> 和 <style> 的標(biāo)簽順序
<!-- good -->
<!-- ComponentA.vue -->
<template>...</template>
<style>/* ... */</style>
<!-- ComponentB.vue -->
<template>...</template>
<script>/* ... */</script>
<style>/* ... */</style>
隱性的父子組件通信
<font color=#f5222d>【強(qiáng)制】</font>應(yīng)該優(yōu)先通過 prop 和事件進(jìn)行父子組件之間的通信,而不是 this.$parent 或改變 prop。
一個(gè)理想的 Vue 應(yīng)用是 prop 向下傳遞,事件向上傳遞的。遵循這一約定會(huì)讓你的組件更易于理解。然而,在一些邊界情況下 prop 的變更或 this.$parent 能夠簡(jiǎn)化兩個(gè)深度耦合的組件。
問題在于,這種做法在很多簡(jiǎn)單的場(chǎng)景下可能會(huì)更方便。但請(qǐng)當(dāng)心,不要為了一時(shí)方便 (少寫代碼) 而犧牲數(shù)據(jù)流向的簡(jiǎn)潔性 (易于理解)。
非 Flux 的全局狀態(tài)管理
<font color=#f5222d>【強(qiáng)制】</font>應(yīng)該優(yōu)先通過 Vuex 管理全局狀態(tài),而不是通過 this.$root 或一個(gè)全局事件總線。
通過 this.$root 和/或全局事件總線管理狀態(tài)在很多簡(jiǎn)單的情況下都是很方便的,但是并不適用于絕大多數(shù)的應(yīng)用。Vuex 提供的不僅是一個(gè)管理狀態(tài)的中心區(qū)域,還是組織、追蹤和調(diào)試狀態(tài)變更的好工具。