是你需要的前端編碼風格嗎?
阿新 • • 發佈:2019-12-12
- 一、HTML
- 1、基本原則
- 2、class 命名規則
- 二、CSS
- 1、基本規則
- 2、註釋
- 3、邊框
- 4、Sass
- 三、JavaScript
- 1、基本格式化
- 1.1 縮排層級
- 1.2 語句結尾
- 1.3 行的長度
- 1.4 換行
- 1.5 命名
- 1.5.1 變數和函式
- 1.5.2 常量
- 1.5.3 函式
- 1.5.3 建構函式
- 2、註釋
- 2.1 單行註釋
- 2.2 多行註釋
- 3、語句和表示式
- 3.1 所有的塊語句都應當使用花括號,包括
- 3.2 語句和表示式 前後加空格
- 3.2 switch 語句
- 3.3 with 語句
- 3.4 for 迴圈
- 3.5 for-in 迴圈
- 4、彙總
- 4.1 物件
- 4.2 陣列
- 4.3 解構
- 4.4 字串
- 4.5 使用模板字串代替字串連線
- 4.5 函式
- 4.6 箭頭函式
- 4.7 構造器
- 4.8 模組
- 4.9 比較運算子和等號
- 4.10 空格
- 4.11 分號
- 4.12 型別轉換
- 1、基本格式化
- 四、針對vue的程式碼風格
- 1、專案結構(vue-cli 3.0)
- 2、api 資料夾
- 3、assets 資料夾
- 4、router 路由
- 5、vue 檔案
- 其他風格指南
- 參考文獻:
程式是寫給人讀的,只是偶爾讓計算機執行一下 -- Donald Knuth
以下程式碼風格僅供參考,沒有明確規定那種書寫方式好,那種書寫方式一定就不好,程式碼風格的統一,目的就是提高程式碼的可讀性。
一、HTML
1、基本原則
html
(結構)、css
(樣式)、js
(樣式)分離- 標籤具有語義化
- 2個空格字元為一個縮排層級,設定敲入
Tab
鍵時插入2個空格 - 標籤名使用一律小寫字母,
vue
元件名必須使用小寫 - 標籤需閉合,自閉合(
self-closing
)標籤,無需閉合 ( 例如:img
input
br
hr
等 ); - 不要使用
id
選擇器,class
命名多個單詞采用中劃線-
連線 - 屬性按照特定的順序出現保證易讀性,
id
、class
、name
、src
、for
、type
、href
、title
和alt
- 禁止行內元素巢狀塊級元素
<!--放註釋內容-->
獨佔一行
2、class 命名規則
- 不能出現中文
- 以字母開頭,不能使用其他格式開頭
- 以名見義 命名需要有規範,有含義、可以快速的理解這個標籤的具體意義
很早以前收藏的表格,具體出處自己記不清了,如有侵權,可與本人聯絡,謝謝
命名 | 說明 |
---|---|
.wrapper | 頁面外圍控制整體佈局寬度 |
.container或.content | 容器,用於最外層 |
.layout | 佈局 |
.head, .header | 頁頭部分 |
.foot, .footer | 頁尾部分 |
.nav | 主導航 |
.subnav | 二級導航 |
.menu | 選單 |
.submenu | 子選單 |
.sideBar | 側欄 |
.sidebar_a, .sidebar_b | 左邊欄或右邊欄 |
.main | 頁面主體 |
.tag | 標籤 |
.msg .message | 提示資訊 |
.tips | 小技巧 |
.vote | 投票 |
.friendlink | 友情連線 |
.title | 標題 |
.summary | 摘要 |
.loginbar | 登入條 |
.searchInput | 搜尋輸入框 |
.hot | 熱門熱點 |
.search | 搜尋 |
.searchBar | 搜尋條 |
.search_results | 搜尋結果 |
.copyright | 版權資訊 |
.branding | 商標 |
.logo | 網站LOGO標誌 |
.siteinfo | 網站資訊 |
.siteinfoLegal | 法律宣告 |
.siteinfoCredits | 信譽 |
.joinus | 加入我們 |
.partner | 合作伙伴 |
.service | 服務 |
.regsiter | 註冊 |
arr/arrow | 箭頭 |
.guild | 指南 |
.sitemap | 網站地圖 |
.list | 列表 |
.homepage | 首頁 |
.subpage | 二級頁面子頁面 |
.tool, .toolbar | 工具條 |
.drop | 下拉 |
.dorpmenu | 下拉選單 |
.status | 狀態 |
.scroll | 滾動 |
.tab | 標籤頁 |
.left .right .center | 居左、中、右 |
.news | 新聞 |
.download | 下載 |
.banner | 廣告條(頂部廣告條) |
二、CSS
1、基本規則
- 使用 2 個空格作為縮排
- 不要使用
id
選擇器,class
命名多個單詞采用中劃線-
連線 - 在左大括號
{
前加上一個空格, 右大括號}
獨佔一行 - 在屬性的冒號
:
後面加上一個空格,前面不加空格
2、註釋
- 建議使用行註釋 (在
Sass
中是//
) 代替塊註釋。 - 建議註釋獨佔一行。避免行末註釋。
3、邊框
在定義無邊框樣式時,使用0
代替none
.nav {
border: none;
}
// good
.nav {
border: 0;
}
4、Sass
- 使用
.scss
的語法,不使用.sass
原本的語法。 - 變數名使用駝峰命名
$borderLine
三、JavaScript
1、基本格式化
1.1 縮排層級
2個空格字元為一個縮排層級,設定敲入 Tab
鍵時插入2個空格
1.2 語句結尾
語句結尾使用分號
1.3 行的長度
單行程式碼長度不超過80個字元
vscode配置如下:
{
"editor.wordWrap": "wordWrapColumn",
"editor.wordWrapColumn": 80
}
1.4 換行
當一行長度達到了單行最大字元數限制時,就需要手動將一行拆成兩行。通常我們會在運算子後換行,下一行會增加兩個層級的縮排。
1.5 命名
命名長度應儘可能短,並抓住重點,儘量在變數名中體現出值的資料型別。比如,命名 count
、 length
和 size
表明資料型別是數字,而命名 name
、 title
和 message
表明資料型別是字串。但用單個字元命名的變數諸如i、j、和k通常在迴圈中使用。使用這些能夠體現出資料型別的命名,可以讓你的程式碼容易被別人和自己讀懂。
不要使用下劃線 _
結尾或開頭來命名屬性和方法。
1.5.1 變數和函式
變數:遵守駝峰大小寫命名法,並且命名字首應當是名詞。
let count = 0;
let myName = 'sheng';
let visible = true;
函式:遵守駝峰大小寫命名法,並且命名字首應當是動詞。
function getName() {};
function setName() {};
使用動詞常見約定
動詞 | 含義 |
---|---|
can | 函式返回一個布林值 |
has | 函式返回一個布林值 |
is | 函式返回一個布林值 |
get | 函式返回一個非布林值 |
set | 函式用來儲存一個值 |
1.5.2 常量
常量: 必須使用 const
定義常量
const count = 10;
const url = 'http://baidu.com';
1.5.3 函式
- 在控制語句(
if
、while
等)的小括號前放一個空格。在函式呼叫及宣告中,不在函式的引數列表前加空格。
// bad
function getName() {
return userName;
}
// good
function getName() {
return userName;
}
- 別儲存 this 的引用。使用箭頭函式或 Function#bind。
// bad
function getName() {
const self = this;
return function() {
console.log(self);
}
}
// bad
function getName() {
const that = this;
return function() {
console.log(that);
};
}
// good
function getName() {
return () => {
console.log(this);
};
}
1.5.3 建構函式
在 JavaScript
中,建構函式只不過是前面冠以new運算子的函式,用來建立物件
建構函式:遵照大駝峰命名法(Pascal Case)
function Person(name) {
this.name = name
}
2、註釋
2.1 單行註釋
- 縮排層級與下一行程式碼保持一致
- 雙斜槓後敲入一個空格, 保持註釋文字有一定的偏移
- 在程式碼行的尾部註釋,程式碼結束到註釋之間有一個縮排,超過單行最大字元限制,應移動當前程式碼行的上方。
// bad
//這是一個Person建構函式
function Person(name) {
this.name = name
}
// good
// 這是一個Person建構函式
function Person(name) {
this.name = name
}
// bad
const MAX_COUNT = 10; //這是一個常量
// good
const MAX_COUNT = 10; // 這是一個常量
2.2 多行註釋
// bad 註釋之前無空格
if (condition) {
/**
* 如果程式碼執行到這裡
* 說明判斷條件成立,可以執行下面程式
*/
console.log('Hello world!');
}
// bad 星號後無空格
if (condition) {
/**
*如果程式碼執行到這裡
*說明判斷條件成立,可以執行下面程式
*/
console.log('Hello world!');
}
// bad 錯誤的縮排
if (condition) {
/**
* 如果程式碼執行到這裡
* 說明判斷條件成立,可以執行下面程式
*/
console.log('Hello world!');
}
// good
if (condition) {
/**
* 如果程式碼執行到這裡
* 說明判斷條件成立,可以執行下面程式
*/
console.log('Hello world!');
}
3、語句和表示式
3.1 所有的塊語句都應當使用花括號,包括
if
for
while
do...while...
try...catch...finally
// bad
if (condition) console.log('Hello world!');
// good
if (condition) {
console.log('Hello world!');
}
3.2 語句和表示式 前後加空格
// bad 前後無空格
if (condition) {
doSomething();
} else {
doElseSomething();
}
// good
if (condition) {
doSomething();
} else {
doElseSomething();
}
3.2 switch 語句
// bad
switch (condition) {
case 0:
console.log(0);
break;
case 1:
console.log(1);
break;
default:
console.log('default');
}
// good
switch (condition) {
case 0:
console.log(0);
break;
case 1:
console.log(1);
break;
default:
console.log('default');
}
3.3 with 語句
禁止使用with語句
3.4 for 迴圈
儘可能避免使用 continue
// bad
for (let i = 0; i < array.length; i++) {
if (i === 2) {
continue; // 跳過本次迭代
};
doSomething();
}
// good
for (let i = 0; i < array.length; i++) {
if (i !== 2) {
doSomething();
};
}
3.5 for-in 迴圈
- 必須使用
hasOwnProperty()
方法來為for-in
迴圈過濾出例項屬性,除非想查詢原型鏈 - 禁止使用
for-in
遍歷陣列
// bad
for (let k in obj) {
console.log(obj[k]);
}
// good
for (let k in obj) {
if (obj.hasOwnProperty(k)) {
console.log(obj[k]);
}
}
4、彙總
4.1 物件
- 使用字面量建立物件
// bad
const obj = new Object();
// good
const obj = {};
- 建立有動態屬性名物件時,使用可被計算的屬性名稱
function getKey(k) {
return `a key name ${k}` ;
};
// bad
const obj = {
id: 1,
name: 'sheng'
};
obj[getKey('hidden')] = true;
// good
const obj = {
id: 1,
name: 'sheng',
[getKey('hidden')] = true
}
- 使用物件方法的簡寫
// bad
const obj = {
name: 'sheng',
setName: function(name) {
return obj.name + name;
}
}
// good
const obj = {
name: 'sheng',
setName(name) {
return obj.name + name;
}
}
4.2 陣列
- 使用字面量建立陣列
// bad
const arr = new Array();
// good
const arr = [];
- 使用擴充套件運算子
...
複製陣列
// bad
let arr = [1, 2, 3];
let newArr = [];
for (let i = 0; i < arr.length; i++) {
newArr[i] = arr[i];
};
// good
const newArry = [...arr];
4.3 解構
- 使用解構存取和使用多屬性物件
// bad
function getUserInfo(user) {
const userName = user.name;
const userAge = user.age;
}
// good
function getUserInfo(user) {
const {
userName,
userAge
} = user;
}
- 對陣列使用解構賦值
const arr = [1, 2, 3, 4];
// bad
const num0 = arr[0];
const num1 = arr[1];
// good
const [num0, num1] = arr;
4.4 字串
- 字串使用單引號
// bad
const name = "sheng";
// good
const name = 'sheng';
4.5 使用模板字串代替字串連線
// bad
window.open(configService.domain + '/exportFile');
// good
window.open( `${configService.domain}/exportFile` );
4.5 函式
- 使用函式宣告代替函式表示式
// bad
const getName = function() {
};
// good
function getName() {
}
- 立即呼叫的函式
(() => {
console.log('Hello world!');
})();
- 不要使用arguments。可以使用rest語法
...
替代
// bad
function getName() {
const args = Array.prototype.slice.call(arguments);
return args.join('')
}
// good
function getName(...args) {
return args.join('');
}
4.6 箭頭函式
let arr = [1, 2, 3];
// bad
arr.map(function(x) {
return x + 1;
})
// good
arr.map(x => {
return x + 1;
})
// good
arr.map(x => x + 1);
4.7 構造器
- 使用
class
,避免使用prototype
// bad
function User(user) {
this.userName = user.name
}
User.prototype.getName = function() {
return this.userName;
}
// good
class User {
constructor(user) {
this.userNmae = user.name
}
getName() {
return this.userName;
}
}
4.8 模組
- 使用(
import
/export
)而不是其他模組系統, 除非特殊情況
// bad
const data = require('./data.js');
module.exports = data;
// good
import data from './data.js';
export default data;
4.9 比較運算子和等號
- 優先使用
===
和!==
而不是==
和!=
; - 條件表示式例如
if
語句通過抽象方法ToBoolean
強制計算它們的表示式並且總是遵守下面的規則:- 物件被計算為
true
undefined
被計算為false
null
被計算為false
boolean
被計算為boolean
- 數字如果為+0、-0、或
NaN
被計算為false
, 否則為true
- 字串如果是空字串
''
被計算為false
, 否則為true
- 物件被計算為
// bad
if (name !== '') {
}
// good
if (name) {
}
// bad
if (arr.length > 0) {
}
// good
if (arr.length) {
}
4.10 空格
- 使用空格把運算子隔開
// bad
const y = x + 1
// good
const y = x + 1;
4.11 分號
- 使用分號
// bad
function getName() {}
// good
function getName() {};
4.12 型別轉換
// bad
const str = 0 + '';
// good
const str = String(0);
// bad
const num = +'4';
// good
const num = Number('4');
// bad
const b = new Boolean(0);
// good
const b = Boolean(0);
// good
const b = !!0;
四、針對vue的程式碼風格
僅適用於個人團隊,當然你也可以提出建議,一起交流學習。
1、專案結構(vue-cli 3.0)
以下示例專案結構適用於現階段的業務開發,後期根據業務場景可增刪,詳情個人github
src 資料夾
|-- api (請求介面的資料夾)
|-- rain-search
| |-- rian-search.js (對應頁面的後端請求)
|-- water-info
| |-- use-water-manage.js
| |-- use-water-search.js
|-- assets
|-- components (全域性通用元件)
|-- environments (環境配置,包括開發環境和生產環境)
|-- environment.dev.js
|-- environment.prod.js
|-- services
|-- auth.service.js (封裝和使用者授權相關函式)
|-- config.service.js (匯出開發環境和生成環境的配置項)
|-- request.service.js (封裝axios,以及一些請求攔截)
|-- styles
|-- element-ui.scss
|-- index.scss
|-- utils (全域性通用的方法)
|-- views
|-- errorPage
| |-- 404.vue
| |-- 401.vue
|-- home
|-- rain-search (當前導航只有一級選單)
| |-- components (只存放當前頁面使用的元件)
| |-- index.vue (當前目錄的入口頁面,都命名index.vue)
|-- water-info (當前導航有二級選單)
| |-- use-water-manage
| |-- components
| |-- index.vue
| |-- use-water-search
| |-- components
| |-- index.vue
|-- APP.vue
|-- main.js
|-- router.js
|-- store.js
- 頁面檔案不同單詞使用
-
連線符命名
2、api 資料夾
api
資料夾中建立資料夾名稱要與views
資料夾中頁面保持一致,方便快速頁面對應的後端介面- 匯出的檔名以
Api
作為字尾,可以明確檔案的作用, 如下:
import request from '../services/request.service';
const useWaterSearchApi = {
getUserResources() {
return request.get('/mock/getUserResources.json');
}
};
export default useWaterSearchApi; // 以 Api作為字尾
- 頁面引入介面名稱與匯出名稱保持一致
3、assets 資料夾
assets
資料夾主要存放三個主要資料夾, 分別為fonts
(字型)、images
(圖片)、js
(外部引入的js檔案)
4、router 路由
- 路由的
path
和name
值,是對應頁面檔案的駝峰命名, 有利於通過位址列找到對應的頁面
- 頁面的一級和二級選單使用巢狀的
children
寫法 - 路由物件新增
meta
物件,meta
物件有兩個屬性,一個title
是當前導航將要在頁面中顯示的名稱,另一個是hidden
用來判斷是否在頁面顯示
示例
new Router({
routes: [
{
path: '/',
component: Home,
redirect: '/rainSearch',
meta: { title: '雨量查詢' },
children: [
{
path: 'rainSearch',
name: 'rainSearch',
component: () => import('@/views/rain-search/index.vue'),
meta: { title: '雨量查詢' }
}
]
},
{
path: '/waterInfo',
component: Home,
redirect: '/waterInfo/useWaterManage',
meta: { title: '雨量資訊' },
children: [
{
path: 'useWaterManage',
name: 'useWaterManage',
component: () => import('@/views/water-info/use-water-manage/index.vue'),
meta: { title: '用水管理' }
},
{
path: 'useWaterSearch',
name: 'useWaterSearch',
component: () => import('@/views/water-info/use-water-search/index.vue'),
meta: { title: '用水查詢' }
}
]
},
{
path: '*',
meta: { title: '404', hidden: true },
component: () => import('@/views/errorPage/404')
},
]
});
5、vue 檔案
- 檔案結構總體安照
template
、js
、css
順序, - js檔案中,元件、屬性/狀態、生命週期、方法的順序,
- 生命週期方法的順序依照執行順序排序
name
以檔名命名
<template>
</template>
<script>
export default {
name: 'use-water-search'
components: {},
props: {},
filters: {},
data () {
return {}
},
computed: {},
watch() {},
beforeCreate () {},
created () {},
beforeMount () {},
mounted () {},
beforeUpdate () {},
updated () {},
beforeDestroy () {},
destroyed () {},
methods: {},
}
</script>
<style lang="scss" scoped>
</style>
- 所有的引入的檔案字尾不要省略,如元件字尾
.vue
、.js
- 對引入的檔案
.vue
、.js
進行分組,.vue
放在最前方,.js
緊跟其後
import sideBar from './components/side-bar/side-bar.vue';
import navBar from './components/nav-bar/nav-bar.vue';
import useWaterSearchApi from '@/api/water-info/use-water-search.js'
css
必須加上scoped
屬性- 屬性按照特定的順序出現並換行保證易讀性,如下
<el-pagination ref="pagination"
class="bottom-pagination"
layout="total, prev, pager, next"
:current-page.sync="currentPage"
:page-size="pageSize"
:total="totalCount"
@size-change="sizeChange"
@current-change="handleCurrentChange"></el-pagination>
- 引入檔案儘可能使用絕對路徑,當前頁面的元件使用相對路徑,這樣移動資料夾時,避免依賴檔案找不到
其他風格指南
- Google JavaScript Style Guide
- jQuery Core Style Guidelines
- Principles of Writing Consistent, Idiomatic JavaScript
參考文獻:
- 編寫可維護的JavaScript
- yuche/javascript
- css-style-guide