一般規範
命名規範
命名分類
camelCase
(駝峰式,也叫小駝峰命名,e.g. userInfo
)PascalCase
(帕斯卡命名式,也叫大駝峰命名,e.g. UserInfo
)kebab-case
(短橫線連線式,e.g. user-info
)snake_case
(下劃線連線式,e.g. user_info
)
變數命名
- 命名方式 : 小駝峰式命名方法
- 命名規範 : 型別+物件描述或屬性的方式
// bad
var getTitle = "LoginTable"
// good
let tableTitle = "LoginTable"
複製程式碼
函式命名
- 命名方式 : 小駝峰方式 ( 建構函式使用大駝峰命名法 )
- 命名規則 : 字首為動詞
動詞 含義 返回值
can 判斷是否可執行某個動作 (權 ) 函式返回一個布林值。true:可執行;false:不可執行
has 判斷是否含有某個值 函式返回一個布林值。true:含有此值;false:不含有此值
is 判斷是否為某個值 函式返回一個布林值。true:為某個值;false:不為某個值
get 獲取某個值 函式返回一個非布林值
set 設定某個值 無返回值、返回是否設定成功或者返回鏈式物件
複製程式碼
推薦:
//是否可閱讀
function canRead(){
return true;
}
//獲取姓名
function getName{
return this.name
}
複製程式碼
常量命名
- 命名方法 : 全部大寫
- 命名規範 : 使用大寫字母和下劃線來組合命名,下劃線用以分割單詞。
推薦:
const MAX_COUNT = 10;
const URL = 'http://test.host.com';
複製程式碼
類的成員命名
- 公共屬性和方法 : 同變數命名方式
- 私有屬性和方法 : 字首為下劃線(_)後面跟公共屬性和方法一樣的命名方式
推薦:
function Student(name) {
var _name = name; // 私有成員
// 公共方法
this.getName = function () {
return _name;
}
// 公共方式
this.setName = function (value) {
_name = value;
}
}
var st = new Student('tom');
st.setName('jerry');
console.log(st.getName()); // => jerry:輸出_name私有變數的值
複製程式碼
註釋規範
單行註釋
- 單獨一行://(雙斜線)與註釋文字之間保留一個空格
- 在程式碼後面新增註釋://(雙斜線)與程式碼之間保留一個空格,並且//(雙斜線)與註釋文字之間保留一個空格。
- 註釋程式碼://(雙斜線)與程式碼之間保留一個空格。
推薦 :
// 呼叫了一個函式 <= 1)單獨在一行
setTitle();
var maxCount = 10; // 設定最大量 <= 2)在程式碼後面註釋
// setName(); // <= 3)註釋程式碼
複製程式碼
多行註釋 ( / 註釋說明 / )
- 若開始(
/\*
)和結束(\*/
)都在一行,推薦採用單行註釋 - 若至少三行註釋時,第一行為
/\*
,最後行為\*/
,其他行以*
開始,並且註釋文字與*
保留一個空格。
推薦 :
/*
* 程式碼執行到這裡後會呼叫setTitle()函式
* setTitle():設定title的值
*/
setTitle();
複製程式碼
函式 ( 方法 ) 註釋
函式(方法)註釋也是多行註釋的一種,但是包含了特殊的註釋要求,參照JavaDoc規範
語法:
/**
* 函式說明
* @關鍵字
*/
複製程式碼
常用註釋關鍵字:
註釋名 | 語法 | 含義 | 示例 |
---|---|---|---|
@param | @param 引數名 {引數型別} 描述資訊 | 描述引數的資訊 | @param name {String} 傳入名稱 |
@return | @return {返回型別} 描述資訊 | 描述返回值的資訊 | @return {Boolean} true:可執行;false:不可執行 |
@author | @author 作者資訊 [附屬資訊:如郵箱、日期] | 描述此函式作者的資訊 | @author 張三 2015/07/21 |
@version | @version XX.XX.XX | 描述此函式的版本號 | @version 1.0.3 |
@example | @example 示例程式碼 | @example setTitle('測試') |
需要新增註釋的地方
程式碼註釋在一個專案的後期維護中顯的尤為重要,所以我們要為每一個被複用的元件編寫元件使用說明,為元件中每一個方法編寫方法說明。
以下情況,務必新增註釋:
1. 公共元件使用說明
2. 各元件中重要函式或者類說明
3. 複雜的業務邏輯處理說明
4. 特殊情況的程式碼處理說明,對於程式碼中特殊用途的變數、存在臨界值、函式中使用的hack、使用了某種演算法或思路等需要進行註釋描述
7. 多重 if 判斷語句
複製程式碼
Vue規範
Vue專案規範
結構化規範(webpack)
├── index.html 入口頁面
├── favicon.ico 頁面圖示
├── .babelrc babel規則
├── .editorconfig 編輯器配置
├── .eslintignore eslint忽略規律
├── .eslintrc.js eslint規則
├── .gitignore git忽略規則
├── build 構建指令碼目錄
│ ├── build-server.js 執行本地構建伺服器,可以訪問構後的頁面
│ ├── build.js 生產環境構建指令碼
│ ├── dev-client.js 開發伺服器熱過載指令碼,主要用來實現開發階段的頁面自動重新整理
│ ├── dev-server.js 執行本地開發伺服器
│ ├── utils.js 構建相關工具方法
│ ├── webpack.base.conf.js wabpack基礎配置
│ ├── webpack.dev.conf.js wabpack開發環境配置
│ └── webpack.prod.conf.js wabpack生產環境配置
│ └── webpack.cdn.conf.js wabpack cdn配置
│ └── webpack.dll.conf.js wabpack dll配置
├── config 專案配置
│ ├── dev.env.js 開發環境變數
│ ├── index.js 專案配置檔案
│ ├── prod.env.js 生產環境變數
│ └── test.env.js 測試環境變數
├── mock mock資料目錄
│ └── hello.js
├── package.json npm包配置檔案,裡面定義了專案的npm指令碼,依賴包等資訊
├── readmd.md 專案描述檔案
├── src 專案原始碼目錄
│ ├── main.js 入口js檔案
│ ├── App.vue 根元件
│ ├── components 公共元件目錄
│ │ └── ComponentItem.vue
│ ├── assets 靜態資源目錄,這裡的資源會被wabpack構建
│ │ ├── css 公共樣式檔案目錄
│ │ ├── js 公共js檔案目錄(如幫助方法)
│ │ └── img 圖片存放目錄
| |── lib 外部引用的外掛存放及修改檔案
| |—— datas 模擬資料,臨時存放
│ ├── routes 前端路由
│ │ └── index.js
│ ├── apis 介面,統一管理
│ │ └── index.js
│ ├── store vuex, 統一管理
│ │ └── index.js
│ └── views 檢視模組名
│ ├── view-module 檢視模組
| └── index.vue 檢視模組的主頁面
│ ├── hello.vue
│ └── notfound.vue
├── static 純靜態資源,不會被wabpack構建。
└── test 測試檔案目錄(unit&e2e)
└── unit 單元測試
├── index.js 入口指令碼
├── karma.conf.js karma配置檔案
└── specs 單測case目錄
└── Hello.spec.js
複製程式碼
目錄、檔案、元件命名規範
1. 目錄
目錄統一使用kebab-case
風格
2. views下的檔案
- js類檔案使用
PascalCase
,如UserInfo.js
- 其他資原始檔統一使用
kebab-case
風格,如user-detail.js
,user-detail.css
,user-avatar.png
3. 元件檔案
- 命名遵循
PascalCase
約定。
元件檔名除index.vue
之外,一律採用PascalCase
(大駝峰)寫法。原因是引入元件時,元件的變數通常用PascalCase
格式,以區別於一般變數。元件檔名與變數名一致,方便對應。
import UserBook from './user/UserBook'
複製程式碼
- 元件名應該始終是多個單詞的,根元件 App 除外
html元素都是單個單詞的(如<article>
,<header>
),為了區分元件和一般html元素,元件由多個單片語成,如BookItem.vue
,單獨的Book.vue
不推薦。
- 元件使用遵循
kebab-case
約定
在頁面中使用元件需要前後閉合,並以短線分隔,如:
<user-book></user-book>
複製程式碼
Vue開發規範
Vue檔案結構
- 基本結構
順序:template -> script -> style。一個元件儘量不要超過200行,頁面包含獨立部分時儘量分離成子元件。
<template>
<div>...</div>
</template>
<script>
export default {
components: {},
data() {
return {};
},
created(){},
methods: {},
};
</script>
<!-- 宣告語言,並且新增scoped -->
<style lang="scss" scoped>...</style>
複製程式碼
- 元件/例項的選項順序
- name (全域性引用)
- components (模板依賴)
- directives ...
- filters ...
- mixins (組合)
- props (介面)
- data (本地狀態屬性)
- computed ...
- watch (響應回撥)
- created (生命週期函式)
- mounted ...
- methods (例項屬性)
複製程式碼
Vue Router Path規範
router path採用kebab-case格式。
用下劃線(如:/user_info)或camelCase(如:/userInfo)的單詞被當成一個單詞,搜尋引擎無法區分語義。
// bad
{
path: '/user_info', // user_info當成一個單詞
name: 'UserInfo',
component: UserInfo,
meta: {
title: ' - 使用者',
desc: ''
}
},
// good
{
path: '/user-info', // 能解析成user info
name: 'UserInfo',
component: UserInfo,
meta: {
title: ' - 使用者',
desc: ''
}
},
複製程式碼
元件開發規範
1. 註冊元件
註冊元件的時候,全部使用 PascalCase 格式。
import UserBook from './user/UserBook'
複製程式碼
2. props 命名規範
- 在宣告
prop
的時候,其命名應該始終使用camelCase
,而在模板中應該始終使用kebab-case
<!-- bad -->
<welcome-message greetingText="hi"></welcome-message>
<script>
props: {
'greeting-text': String
}
</script>
<!-- good -->
<welcome-message greeting-text="hi"></welcome-message>
<script>
props: {
greetingText: String;
}
</script>
複製程式碼
- prop定義應該儘量詳細
- 元件 props 原子化
- 提供預設值
- 使用 type 屬性校驗型別
// bad 這樣做只有開發原型系統時可以接受
props: ['status']
// good
props: {
status: {
type: String,
required: true,
validator: function (value) {
return [
'syncing',
'synced',
'version-conflict',
'error'
].indexOf(value) !== -1
}
}
}
複製程式碼
3. methods 命名規範
- 駝峰式命名,統一使用動詞或者動詞+名詞形式
//bad
go、nextPage、show、login、get_code
// good
jumpPage、openCarInfoDialog
複製程式碼
- 請求資料方法,以 data 結尾
//bad
takeData、confirmData、getList、postForm
// good
getListData、postFormData
複製程式碼
- 儘量使用常用單詞開頭(set、get、go、can、has、is)
附: 函式方法常用的動詞:
get 獲取/set 設定,
add 增加/remove 刪除
create 建立/destory 移除
start 啟動/stop 停止
open 開啟/close 關閉,
read 讀取/write 寫入
load 載入/save 儲存,
create 建立/destroy 銷燬
begin 開始/end 結束,
backup 備份/restore 恢復
import 匯入/export 匯出,
split 分割/merge 合併
inject 注入/extract 提取,
attach 附著/detach 脫離
bind 繫結/separate 分離,
view 檢視/browse 瀏覽
edit 編輯/modify 修改,
select 選取/mark 標記
copy 複製/paste 貼上,
undo 撤銷/redo 重做
insert 插入/delete 移除,
add 加入/append 新增
clean 清理/clear 清除,
index 索引/sort 排序
find 查詢/search 搜尋,
increase 增加/decrease 減少
play 播放/pause 暫停,
launch 啟動/run 執行
compile 編譯/execute 執行,
debug 除錯/trace 跟蹤
observe 觀察/listen 監聽,
build 構建/publish 釋出
input 輸入/output 輸出,
encode 編碼/decode 解碼
encrypt 加密/decrypt 解密,
compress 壓縮/decompress 解壓縮
pack 打包/unpack 解包,
parse 解析/emit 生成
connect 連線/disconnect 斷開,
send 傳送/receive 接收
download 下載/upload 上傳,
refresh 重新整理/synchronize 同步
update 更新/revert 復原,
lock 鎖定/unlock 解鎖
check out 簽出/check in 簽入,
submit 提交/commit 交付
push 推/pull 拉,
expand 展開/collapse 摺疊
begin 起始/end 結束,
start 開始/finish 完成
enter 進入/exit 退出,
abort 放棄/quit 離開
obsolete 廢棄/depreciate 廢舊,
collect 收集/aggregate 聚集
複製程式碼
4. 多個屬性的html元素規範
多個特性的元素,佔據一行過長時,應該分多行撰寫,每個特性一行。(增強更易讀)
<!-- bad -->
<img src="https://vuejs.org/images/logo.png" alt="Vue Logo">
<my-component foo="fooattribute" bar="barattribute" baz="bazattribute"></my-component>
<!-- good -->
<img
src="https://vuejs.org/images/logo.png"
alt="Vue Logo"
>
<my-component
foo="fooattribute"
bar="barattribute"
baz="bazattribute"
>
</my-component>
複製程式碼
5. 元素屬性的順序
原生屬性放前面,指令放後面
- class
- id,ref
- name
- data-*
- src, for, type, href,value,max-length,max,min,pattern
- title, alt,placeholder
- aria-*, role
- required,readonly,disabled
- is
- v-for
- key
- v-if
- v-else-if
- v-else
- v-show
- v-cloak
- v-pre
- v-once
- v-model
- v-bind,:
- v-on,@
- v-html
- v-text
複製程式碼
6. 指令規範
- 指令有縮寫則一律採用縮寫形式
// bad
v-bind:code="code"
v-on:click="getUserData"
// good
:code="code"
@click="getUserData"
複製程式碼
- v-for 迴圈必須加上 key 屬性,在整個 for 迴圈中 key 需要唯一
<!-- bad -->
<ul>
<li v-for="todo in todos">
{{ todo.text }}
</li>
</ul>
<!-- good -->
<ul>
<li v-for="todo in todos" :key="todo.id">
{{ todo.text }}
</li>
</ul>
複製程式碼
-
避免 v-if 和 v-for 同時用在一個元素上(效能問題)
出現這樣的需求,有兩種解決方案:
-
將資料替換為一個計算屬性,讓其返回過濾後的列表
<!-- bad --> <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> <script> computed: { activeUsers: function () { return this.users.filter(function (user) { return user.isActive }) } } </script> 複製程式碼
-
將 v-if 移動至容器元素上 (比如 ul, ol)
<!-- bad --> <ul> <li v-for="user in users" v-if="shouldShowUsers" :key="user.id"> {{ user.name }} </li> </ul> <!-- good --> <ul v-if="shouldShowUsers"> <li v-for="user in users" :key="user.id"> {{ user.name }} </li> </ul> 複製程式碼
-
其他
- 避免 this.$parent
- 除錯資訊 console.log() 使用完及時刪除
- 除了三目運算,if,else 等禁止簡寫
- 行尾分號可以加或不加,應統一風格,但建議都不加。分號的作用在現代ES指令碼不會影響,如果你不懂分號的作用,該入的坑照樣會入,沒有分號的程式碼更加清爽。大部分Vue專案都去除了分號。
// bad if (true) alert(name); console.log(name); // bad if (true) alert(name); console.log(name); // good if (true) { alert(name) } console.log(name) 複製程式碼
HTML規範
指令碼載入
- 相容老舊瀏覽器(IE9-)時:
指令碼引用寫在 body 結束標籤之前,並帶上 async 屬性。這雖然在老舊瀏覽器中不會非同步載入指令碼,但它只阻塞了 body 結束標籤之前的 DOM 解析,這就大大降低了其阻塞影響。
- 而在現代瀏覽器中:
指令碼將在 DOM 解析器發現 body 尾部的 script 標籤才進行載入,此時載入屬於非同步載入,不會阻塞 CSSOM(但其執行仍發生在 CSSOM 之後)。
因此,相容所有瀏覽器,則推薦:
<html>
<head>
<link rel="stylesheet" href="main.css">
</head>
<body>
<!-- body goes here -->
<script src="main.js" async></script>
</body>
</html>
複製程式碼
只相容現代瀏覽器,則推薦:
<html>
<head>
<link rel="stylesheet" href="main.css">
<script src="main.js" async></script>
</head>
<body>
<!-- body goes here -->
</body>
</html>
複製程式碼
語義化
語義化是指:根據元素其被創造出來時的初始意義來使用它。 用正確的標籤表達正確的內容,這也有利於SEO。
正確合理使用nav
, header
, article
, section
等語義標籤,不要全篇div。
alt標籤不為空
<img>
標籤的 alt 屬性指定了替代文字,用於在影像無法顯示或者使用者禁用影像顯示時,代替影像顯示在瀏覽器中的內容。
假設由於下列原因使用者無法檢視影像,alt 屬性可以為影像提供替代的資訊:
- 網速太慢
- src 屬性中的錯誤
- 瀏覽器禁用影像
- 使用者使用的是螢幕閱讀器
從SEO角度考慮,瀏覽器的爬蟲爬不到圖片的內容,所以我們要有文字告訴爬蟲圖片的內容
結構、表現、行為三者分離
- 儘量在文件和模板中只包含結構性的 HTML;
- 將所有表現程式碼,移入樣式表中;
- 將所有動作行為,移入指令碼之中。
HTML只關注內容
- HTML只顯示展示內容資訊
- 不要引入一些特定的 HTML 結構來解決一些視覺設計問題,多考慮使用偽元素
:before
、:after
- 不要將 img 元素當做專門用來做視覺設計的元素
- 樣式上的問題應該使用css解決
<!-- bad -->
<!-- We should not introduce an additional element just to solve a design problem -->
<span class="text-box">
<span class="square"></span>
See the square next to me?
</span>
css 程式碼:
.text-box > .square {
display: inline-block;
width: 1rem;
height: 1rem;
background-color: red;
}
<!-- good -->
<!-- That's clean markup! -->
<span class="text-box">
See the square next to me?
</span>
css 程式碼:
/* We use a :before pseudo element to solve the design problem of placing a colored square in front of the text content */
.text-box:before {
content: "";
display: inline-block;
width: 1rem;
height: 1rem;
background-color: red;
}
複製程式碼
JS規範
一般規範
使用嚴格等===
總是使用 === 精確的比較操作符,避免在判斷的過程中,由 JavaScript 的強制型別轉換所造成的困擾。
this關鍵字
只在物件構造器、方法和在設定的閉包中使用 this 關鍵字。
this 的語義常容易被誤導。它時而指向全域性物件(大多數時),時而指向呼叫者的定義域(在 eval 中),時而指向 DOM 樹中的某一節點(當用事件處理繫結到 HTML 屬性上時),時而指向一個新建立的物件(在構造器中),還時而指向其它的一些物件(如果函式被 call() 和 apply() 執行和呼叫時)。
正因為它是如此容易地被搞錯,請限制它的使用場景:
- 在建構函式中
- 在物件的方法中(包括由此建立出的閉包內)
三元操作符
用三元操作符分配或返回語句。在比較簡單的情況下使用,避免在複雜的情況下使用。
// bad
if(x === 10) {
return 'valid';
} else {
return 'invalid';
}
// good
return x === 10 ? 'valid' : 'invalid'
複製程式碼
不使用eval()函式
就如eval的字面意思來說,惡魔,使用eval()函式會帶來安全隱患。 eval()函式的作用是返回任意字串,當作js程式碼來處理。
使用ES6編碼規範
- 定義變數使用
let
,定義常量使用const
- 靜態字串一律使用單引號或反引號,動態字串使用反引號
// bad const a = 'foobar'; const b = 'foo' + a + 'bar'; // good const a = 'foobar'; const b = `foo${a}bar`; const c = 'foobar'; 複製程式碼
- 解構賦值
// 1. 陣列解構賦值 const arr = [1, 2, 3, 4]; // bad const first = arr[0]; const second = arr[1]; // good const [first, second] = arr; // 2. 物件解構賦值 // bad function getFullName(user) { const firstName = user.firstName; const lastName = user.lastName; } // good function getFullName(obj) { const { firstName, lastName } = obj; } // best function getFullName({ firstName, lastName }) {} 複製程式碼
- 使用擴充套件運算子(...)拷貝陣列。
const items = [1, 2, 3, 4, 5]; // bad const itemsCopy = items; // good const itemsCopy = [...items]; 複製程式碼
- 箭頭函式
需要使用函式表示式的場合,儘量用箭頭函式代替。因為這樣更簡潔,而且繫結了 this
// bad const self = this; const boundMethod = function(...params) { return method.apply(self, params); }; // good const boundMethod = (...params) => method.apply(this, params); 複製程式碼
CSS規範
合理地使用ID
一般情況下ID不應該被用於樣式,並且ID的權重很高,所以不使用ID解決樣式的問題,而是使用class
css選擇器中避免使用標籤名
從結構、表現、行為分離的原則來看,應該儘量避免css中出現HTML標籤,並且在css選擇器中出現標籤名會存在潛在的問題。
使用直接子選擇器
使用後代選擇器常可能導致設計問題和效能損耗,這是個不好的做法,應總是考慮直接子選擇器
/* bad */
.content .title {
font-size: 2rem;
}
/* good */
.content > .title {
font-size: 2rem;
}
複製程式碼
儘量使用縮寫屬性
儘量使用縮寫屬性對於程式碼效率和可讀性是很有用的,比如font屬性。
/* bad */
.user-box {
border-top-style: none;
font-family: palatino, georgia, serif;
font-size: 100%;
line-height: 1.6;
padding-bottom: 2em;
padding-left: 1em;
padding-right: 1em;
padding-top: 0;
}
/* good */
.user-box {
border-top: 0;
font: 100%/1.6 palatino, georgia, serif;
padding: 0 1em 2em;
}
複製程式碼
0後面不帶單位
/* bad */
.user-box {
padding-bottom: 0px;
margin: 0em;
}
/* good */
.user-box {
padding-bottom: 0;
margin: 0;
}
複製程式碼
屬性格式
- 為了保證一致性和可擴充套件性,每個宣告應該用分號結束,每個宣告換行。
- 屬性名的冒號後使用一個空格。出於一致性的原因,
- 屬性和值(但屬性和冒號之間沒有空格)的之間始終使用一個空格。
- 每個選擇器和屬性宣告總是使用新的一行。
- 屬性選擇器或屬性值用雙引號(""),而不是單引號('')括起來。
屬性順序
作為最佳實踐,按照分組及重要性進行排序。具體地,按照由外向內,從元素與外界的關係,是否會影響外部佈局,到外邊距,內邊距等。
- 佈局相關(display, position, float, overflow, clear),因為元素的佈局會對對相鄰元素產生影響,自身甚至會脫離原來的文件流,所以比較重要。
- 盒模型相關(width, height, margin, padding)
- 外觀 (color, background, border, box-shadow)
- 文字排版 (font-size, font-family, text-align, text-transform)
- 其他 (cursor, z-index)
/* bad */
.box {
font-family: 'Arial', sans-serif;
border: 3px solid #ddd;
left: 30%;
position: absolute;
text-transform: uppercase;
background-color: #eee;
right: 30%;
isplay: block;
font-size: 1.5rem;
overflow: hidden;
padding: 1em;
margin: 1em;
}
/* good */
.box {
display: block;
position: absolute;
left: 30%;
right: 30%;
overflow: hidden;
margin: 1em;
padding: 1em;
background-color: #eee;
border: 3px solid #ddd;
font-family: 'Arial', sans-serif;
font-size: 1.5rem;
text-transform: uppercase;
}
複製程式碼