為提高團(tuán)隊(duì)協(xié)作效率, 便于后臺(tái)人員添加功能及前端后期優(yōu)化維護(hù),輸出高質(zhì)量的文檔,特制訂此文檔。 本規(guī)范文檔一經(jīng)確認(rèn), 前端開(kāi)發(fā)人員須按本文檔規(guī)范進(jìn)行開(kāi)發(fā)。 本文檔如有不對(duì)或者不合適的地方請(qǐng)及時(shí)提出,經(jīng)討論決定后可以更改此文檔。
1、基本原則
符合 web 標(biāo)準(zhǔn) ( UTF-8 HTML5 ) ,語(yǔ)義化 html ( HTML5 新增要求,減少 div 和 span 等無(wú)特定語(yǔ)義的標(biāo)簽使用 ) ,結(jié)構(gòu)表現(xiàn)行為分離 ( HTML-CSS-JS代碼分離,不同行為代碼高內(nèi)聚低耦合 ) ,兼容性優(yōu)良 ( 早期版本瀏覽器兼容,移動(dòng)端和PC端設(shè)備兼容 ) 。頁(yè)面性能方面 ( 減少請(qǐng)求次數(shù),例如使用精靈圖和sass語(yǔ)法 ) ,代碼要求簡(jiǎn)潔明了有序,盡可能的減小服務(wù)器負(fù)載,保證最快的解析速度 ( 減小 repaint 和 reflow ) 。禁止直接操作DOM。
2、文件命名、結(jié)構(gòu)規(guī)范
- 文件名不能含有空格
- 文件名建議只使用小寫(xiě)字母,不使用大寫(xiě)字母。( 但比如說(shuō)像 github 的說(shuō)明類文件,README,則應(yīng)該全部使用大寫(xiě) )
- 文件名包含多個(gè)單詞時(shí),單詞之間建議使用半角的連詞線 ( - ) 分隔。
3、iconfont--使用字體圖標(biāo)減少圖片資源消耗
4、JS 書(shū)寫(xiě)規(guī)范 - 遵照ES6標(biāo)準(zhǔn)
-
命名規(guī)范
let 定義的變量不會(huì)被變量提升,const 定義的常量不能被修改,let 和 const 都是塊級(jí)作用域
盡量不實(shí)用 var
const 定義常量全部大寫(xiě)并單詞間用下劃線分隔
小駝峰式定義普通變量比如對(duì)象的屬性或方法名、變量名、函數(shù)名
小駝峰式但首字母大寫(xiě)定義類名 ( 構(gòu)造器 )
小駝峰式但需要用_開(kāi)頭定義私有變量
// const 定義常量
export const VOUCHER_STATUS_NORMAL = 1 // 正常
export const VOUCHER_STATUS_ADD = 2 // 新增
export const VOUCHER_STATUS_EDIT = 3 // 編輯 (查看狀態(tài)下進(jìn)行了修改)
// 對(duì)象的屬性或方法名、變量名、函數(shù)名
pageChanged = (pageIndex, pageSize) => {
let page = this.metaAction.gf('data.pagination').toJS(),
filter = this.metaAction.gf('data.filter').toJS()
if(pageIndex){
page.pageIndex = pageIndex
}
if(pageSize){
page.pageSize = pageSize
}
this.load( page, filter)
}
// 定義類名 ( 構(gòu)造器 )
class DragTitle extends Component {
updateTransform = transformStr => {
this.modalDom.style.transform = transformStr;
};
componentDidMount() { ...
...
// 定義私有變量
let _current, _defaultConfig
- import導(dǎo)入模塊、export導(dǎo)出模塊
// 全部導(dǎo)入
import people from './example'
// 將整個(gè)模塊當(dāng)作單一對(duì)象進(jìn)行導(dǎo)入,該模塊的所有導(dǎo)出都會(huì)作為對(duì)象的屬性存在
import * as example from "./example.js"
console.log(example.name)
console.log(example.getName())
// 導(dǎo)入部分,引入非 default 時(shí),使用花括號(hào)
import {name, age} from './example'
// 導(dǎo)出默認(rèn), 有且只有一個(gè)默認(rèn)
export default App
// 部分導(dǎo)出
export class App extend Component {};
-
class、extends、super
ES5中最令人頭疼的的幾個(gè)部分:原型、構(gòu)造函數(shù),繼承,ES6 引入了 Class ( 類 ) 這個(gè)概念。
ES6 允許我們用 class 定義一個(gè)“類”。
Class 之間可以通過(guò) extends 關(guān)鍵字實(shí)現(xiàn)繼承。
super 關(guān)鍵字,它指代父類的實(shí)例 ( 即父類的 this 對(duì)象 )。子類必須在 constructor 方法中調(diào)用 super 方法,否則就得不到 this 對(duì)象。
更多 ES6 類聲明繼承機(jī)制詳見(jiàn) ES6 類 共同學(xué)習(xí)共同進(jìn)步
class Animal {
constructor() {
this.type = 'animal';
}
says(say) {
console.log(this.type + ' says ' + say);
}
}
let animal = new Animal();
animal.says('hello'); //animal says hello
class Cat extends Animal {
constructor() {
super();
this.type = 'cat';
}
}
let cat = new Cat();
cat.says('hello'); //cat says hello
-
arrow functions ( 箭頭函數(shù) )
函數(shù)的快捷寫(xiě)法。不需要 function 關(guān)鍵字來(lái)創(chuàng)建函數(shù),省略 return 關(guān)鍵字,繼承當(dāng)前上下文的 this 關(guān)鍵字
箭頭函數(shù)小細(xì)節(jié):當(dāng)你的函數(shù)有且僅有一個(gè)參數(shù)的時(shí)候,是可以省略掉括號(hào)的;當(dāng)你函數(shù)中有且僅有一個(gè)表達(dá)式的時(shí)候可以省略{}
JavaScript 語(yǔ)言的 this 對(duì)象一直是一個(gè)令人頭痛的問(wèn)題,運(yùn)行上面的代碼會(huì)報(bào)錯(cuò),這是因?yàn)?setTimeout 中的 this 指向的是全局對(duì)象。
當(dāng)我們使用箭頭函數(shù)時(shí),函數(shù)體內(nèi)的 this 對(duì)象,就是定義時(shí)所在的對(duì)象
更多 ES6 箭頭函數(shù) this 巧用詳見(jiàn) ES6寫(xiě)法優(yōu)化 箭頭函數(shù) 共同學(xué)習(xí)共同進(jìn)步
// ES5
var arr1 = [1, 2, 3];
var newArr1 = arr1.map(function(x) {
return x + 1;
});
// ES6
let arr2 = [1, 2, 3];
let newArr2 = arr2.map((x) => {
x + 1
});
let arr2 = [1, 2, 3];
let newArr2 = arr2.map(x => x + 1);
-
template string ( 模板字符串 )
字符串拼接。將表達(dá)式嵌入字符串中進(jìn)行拼接,用和${}來(lái)界定。
在ES5時(shí)我們通過(guò)反斜杠來(lái)做多行字符串拼接。ES6反引號(hào) `` 直接搞定。
更多 ES6 標(biāo)簽?zāi)0孀址梅ㄔ斠?jiàn) ES6寫(xiě)法優(yōu)化 字符串模板 共同學(xué)習(xí)共同進(jìn)步
// es5
var name1 = "bai";
console.log('hello' + name1);
// es6
const name2 = "ming";
console.log(`hello${name2}`)
// es5
var msg = "Hi \
man!";
// es6
const template = `<div>
<span>hello world</span>
</div>`;
// includes:判斷是否包含然后直接返回布爾值
let str = 'hahah';
console.log(str.includes('y')); // false
// repeat: 獲取字符串重復(fù)n次
let s = 'he';
console.log(s.repeat(3)); // 'hehehe'
-
destructuring ( 解構(gòu) )
解構(gòu)能讓我們從對(duì)象或者數(shù)組里取出數(shù)據(jù)存為變量以數(shù)組為例
更多 ES6 解構(gòu)用法詳見(jiàn) ES6 對(duì)象、數(shù)組解構(gòu) 共同學(xué)習(xí)共同進(jìn)步
const numbers = [ 'one', 'two', 'three', 'four' ];
const [one, , three, , five = 'have no five'] = numbers; // 相對(duì)應(yīng)位置的值 默認(rèn)值寫(xiě)法同對(duì)象一樣用=
console.log(one, three, five); // one three have no five
-
Promise 用同步的方式去寫(xiě)異步代碼
更多 ES6 Promise 用法詳見(jiàn) ES6 Promise 共同學(xué)習(xí)共同進(jìn)步
// 發(fā)起異步請(qǐng)求
fetch('/api/todos')
.then(res => res.json())
.then(data => ({
data
}))
.catch(err => ({
err
}));
-
ES6 Generator 生成器控制 ajax 工作流
用 Generator 生成器來(lái)達(dá)到 Promise 的效果,控制 ajax 工作流,代碼有更好的可讀性,從上到下,一氣呵成。
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
function ajax(url) { // 創(chuàng)建 ajax 請(qǐng)求流程
axios.get(url).then(res => userGen.next(res.data));
}
function* steps() { // 創(chuàng)建生成器函數(shù)
console.log('ajax start users')
const users = yield ajax('https://api.github.com/users');
console.log(users, 'ajax start firstUser')
const firstUser = yield ajax(`https://api.github.com/users/${users[0].login}`);
console.log(firstUser, 'ajax start followers')
const followers = yield ajax(firstUser.followers_url);
console.log(followers, 'ajax end')
}
const userGen = steps();
userGen.next(); // 流程開(kāi)啟
</script>
-
使用嚴(yán)格的條件判斷符
用 === 代替 == ,用 !== 代替 != ,避免在條件判斷時(shí)掉入 == 造成的陷阱
// 這樣的一些值表示 false 。
null
undefined 與 null 相等
字符串 ''
數(shù)字 0
NaN
(function () {
var undefined;
undefined == null; // true
1 == true; //true
2 == true; // false
0 == false; // true
0 == ''; // true
NaN == NaN;// false
[] == false; // true
[] == ![]; // true
})();
5、關(guān)于VUE的開(kāi)發(fā)規(guī)范
- 數(shù)據(jù)管理優(yōu)先使用 Vuex ,通用組件選擇性使用 props 方式
- store 的定義可以以組件的維度做好分解,在入口處做好聚合
- api 接口模塊管理--統(tǒng)一管理 api 請(qǐng)求
- vue 生命鉤子

vue 生命鉤子
- vue文件基本結(jié)構(gòu)
<template>
<div>
<!--必須在div中編寫(xiě)頁(yè)面-->
</div>
</template>
<script>
export default {
components : {},//5.注冊(cè)需要用到的組件
props:{},//7.傳遞到本組件的props
data () {//8.組件的 data 必須是一個(gè)函數(shù)
return {
}
},
computed:{},//8
watch:{},//9
//所有的鉤子函數(shù):如created
created(){},//9
methods: {//10
},
}
</script>
<!--聲明語(yǔ)言,并且添加scoped-->
<style lang="scss" scoped>
</style>...
...
- vue文件方法聲明順序
1.副作用 (觸發(fā)組件外的影響)
--el
2.全局感知 (要求組件以外的知識(shí))
--name
--parent
3.組件類型 (更改組件的類型)
--functional
4.模板修改器 (改變模板的編譯方式)
--delimiters
--comments
5.模板依賴 (模板內(nèi)使用的資源)
--components
--directives
--filters
6.組合 (向選項(xiàng)里合并屬性)
--extends
--mixins
7.接口 (組件的接口)
--inheritAttrs
--model
--props/propsData
8.本地狀態(tài) (本地的響應(yīng)式屬性)
--data
--computed
9.事件 (通過(guò)響應(yīng)式事件觸發(fā)的回調(diào))
--watch
生命鉤子函數(shù)
---beforeCreate
---created
---beforeMount
---mounted
---beforeUpdate
---updated
---activated
---deactivated
---beforeDestroy
---destroyed
10.非響應(yīng)式的屬性 (不依賴響應(yīng)系統(tǒng)的實(shí)例屬性)
--methods
11.渲染 (組件輸出的聲明式描述)
--template/render
--renderError
- 元素特性的順序
- v-for
- v-if / v-show
- id
- ref / key / slot
- v-model
- v-on//強(qiáng)烈建議用簡(jiǎn)寫(xiě) @,如@change
-
單文件組件的頂級(jí)元素的順序
單文件組件應(yīng)該總是讓<script>、<template> 和 <style> 標(biāo)簽的順序保持一致。且 <style> 要放在最后,因?yàn)榱硗鈨蓚€(gè)標(biāo)簽至少要有一個(gè)。
<!-- ComponentA.vue -->
<template>...</template>
<script>/* ... */</script>
<style>/* ... */</style>
-
多個(gè)特性的元素
多個(gè)特性的元素應(yīng)該分多行撰寫(xiě),每個(gè)特性一行。
<img
src="https://vuejs.org/images/logo.png"
alt="Vue Logo"
>
<MyComponent
foo="a"
bar="b"
baz="c"
/>
-
模板中簡(jiǎn)單的表達(dá)式
組件模板應(yīng)該只包含簡(jiǎn)單的表達(dá)式,復(fù)雜的表達(dá)式則應(yīng)該重構(gòu)為計(jì)算屬性或方法。
復(fù)雜表達(dá)式會(huì)讓你的模板變得不那么聲明式。我們應(yīng)該盡量描述應(yīng)該出現(xiàn)的是什么,而非如何計(jì)算那個(gè)值。而且計(jì)算屬性和方法使得代碼可以重用。
<!-- 在模板中 -->
{{ 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(' ')
}
}
- 簡(jiǎn)單的計(jì)算屬性
computed: {
basePrice: function() {
return this.manufactureCost / (1 - this.profitMargin)
},
discount: function() {
return this.basePrice * (this.discountPercent || 0)
},
finalPrice: function() {
return this.basePrice - this.discount
}
}
- 謹(jǐn)慎使用 ( 有潛在危險(xiǎn)的模式 )
// 如果一組 v-if + v-else 的元素類型相同,最好使用 key (比如兩個(gè) <div> 元素)。
<div
v-if="error"
key="search-status"
>
錯(cuò)誤:{{ error }}
</div>
<div
v-else
key="search-results"
>
{{ results }}
</div>
// 元素選擇器應(yīng)該避免在 scoped 中出現(xiàn)。在 scoped 樣式中,類選擇器比元素選擇器更好,因?yàn)榇罅渴褂迷剡x擇器是很慢的。
<template>
<button class="btn btn-close">X</button>
</template>
<style scoped>
.btn-close {
background-color: red;
}
</style>
// 隱性的父子組件通信 應(yīng)該優(yōu)先通過(guò) prop 和事件進(jìn)行父子組件之間的通信,而不是 this.$parent 或改變 prop。
Vue.component('TodoItem', {
props: {
todo: {
type: Object,
required: true
}
},
template: `
<input
:value="todo.text"
@input="$emit('input', $event.target.value)"
>
`
})
// 非 Flux 的全局狀態(tài)管理 應(yīng)該優(yōu)先通過(guò) Vuex 管理全局狀態(tài),而不是通過(guò) this.$root 或一個(gè)全局事件總線。
// store/modules/todos.js
export default {
state: {
list: []
},
mutations: {
REMOVE_TODO (state, todoId) {
state.list = state.list.filter(todo => todo.id !== todoId)
}
},
actions: {
removeTodo ({ commit, state }, todo) {
commit('REMOVE_TODO', todo.id)
}
}
}
<!-- TodoItem.vue -->
<template>
<span>
{{ todo.text }}
<button @click="removeTodo(todo)">
X
</button>
</span>
</template>
<script>
import { mapActions } from 'vuex'
export default {
props: {
todo: {
type: Object,
required: true
}
},
methods: mapActions(['removeTodo'])
}
</script>
6、CSS 書(shū)寫(xiě)規(guī)范
- webApp 自適應(yīng)布局 -- 使用 rem 。
使用 rem 單位可以讓我們的設(shè)計(jì)更加靈活,能夠控制元素整體放大縮小,而不是固定大小。 我們可以使用這種靈活性,使我們?cè)陂_(kāi)發(fā)期間,能更加快速靈活的調(diào)整,允許瀏覽器用戶調(diào)整瀏覽器大小來(lái)達(dá)到最佳體驗(yàn)。 - class 與 id 的使用:id 是唯一的并是父級(jí)的,class 是可以重復(fù)的并是子級(jí)的,所以 id 僅使用在大的模塊上,class 可用在重復(fù)使用率高及子級(jí)中。
- class 命名,體現(xiàn)嵌套統(tǒng)一使用 - 來(lái)連接,參考 TTK 框架 企業(yè)開(kāi)發(fā)平臺(tái),每一個(gè)app的最外層與文件夾保持一致,header、content、footer 依次排列層級(jí)分明
避免使用通配規(guī)則和相鄰兄弟選擇符、子選擇符,、后代選擇符、屬性選擇符等選擇器
不要限定 id 選擇符,如 div#header(提權(quán)的除外)
不要限定類選擇器,如 ul.recommend(提權(quán)的除外)
不要使用 ul li a 這樣長(zhǎng)的選擇符
避免使用標(biāo)簽子選擇符,如 #header > li > a
// dom 結(jié)構(gòu)對(duì)應(yīng) css className
name: 'root',
component: 'Layout',
className: 'open-portal-config-project-list', // app 名稱
children: [{
name: 'header',
component: 'Layout',
className: 'open-portal-config-project-list-header',
...
name: 'content',
component: 'Layout',
className: 'open-portal-config-project-list-content',
children: [{
...
name: 'footer',
component: 'Layout',
_visible: false,
className: 'open-portal-config-project-list-footer',
...
// 對(duì)應(yīng) less 文件結(jié)構(gòu)
.open-portal-config-project-list{
align-items: center;
margin: 0 auto;
width: 100%;
height: 100%;
background-color: #fff;
&-header{ // 盡量減少樣式 class 嵌套 方便解析查找以及日后修改
width: 100%;
flex: initial;
flex-direction: row;
justify-content: space-between;
line-height: 40px;
padding: 10px;
.mk-input {
width: 200px;
margin-right: 10px;
}
}
&-content {
flex: 1;
width: 100%;
}
&-footer {
flex: initial;
width: 100%;
padding: 10px;
.mk-pagination {
justify-content: flex-end;
}
}
}
- 書(shū)寫(xiě)代碼前,提高樣式重復(fù)使用率。充分利用 html 自身屬性及樣式繼承原理減少代碼量。
- 樣式表中中文字體名,請(qǐng)務(wù)必轉(zhuǎn)碼成 unicode 碼,以避免編碼錯(cuò)誤時(shí)亂碼。
- 減少使用影響性能的屬性,比如 position:absolute || float。
- 兼容多個(gè)瀏覽器時(shí),將標(biāo)準(zhǔn)屬性寫(xiě)在底部。
-moz-border-radius: 15px; /* Firefox */
-webkit-border-radius: 15px; /* Safari和Chrome */
border-radius: 15px; /* Opera 10.5+, 以及使用了IE-CSS3的IE瀏覽器 */ //標(biāo)準(zhǔn)屬性
- 盡量避免使用CSS Hack。
property:value; /* 所有瀏覽器 */
+property:value; /* IE7 */
_property:value; /* IE6 */
*property:value; /* IE6/7 */
property:value\9; /* IE6/7/8/9,即所有IE瀏覽器 */
7、注釋規(guī)范
- 單行注釋
單獨(dú)一行:// ( 雙斜線 ) 與注釋文字之間保留一個(gè)空格
在代碼后面添加注釋:// ( 雙斜線 ) 與代碼之間保留一個(gè)空格,并且 // ( 雙斜線 ) 與注釋文字之間保留一個(gè)空格。
注釋代碼:// ( 雙斜線 ) 與代碼之間保留一個(gè)空格。
// 調(diào)用了一個(gè)函數(shù);1)單獨(dú)在一行
setTitle();
var maxCount = 10; // 設(shè)置最大量;2)在代碼后面注釋
// setName(); // 3)注釋代碼
- 多行注釋
若開(kāi)始和結(jié)束都在一行,推薦采用單行注釋
若至少三行注釋時(shí),第一行為 / ,最后行為 / ,其他行以開(kāi)始,并且注釋文字與 * 保留一個(gè)空格。
/*
* 代碼執(zhí)行到這里后會(huì)調(diào)用setTitle()函數(shù)
* setTitle():設(shè)置title的值
*/
setTitle();
- 函數(shù) ( 方法 ) 注釋
/**
* 函數(shù)說(shuō)明
* @關(guān)鍵字
*/
8、HTML 書(shū)寫(xiě)規(guī)范
- 文檔類型聲明及編碼:統(tǒng)一為 html5 聲明類型。書(shū)寫(xiě)時(shí)利用 IDE 實(shí)現(xiàn)層次分明的縮進(jìn) ( 默認(rèn)縮進(jìn)4空格 ) 。
- 非特殊情況下 CSS 文件放在 body 部分 <meta> 標(biāo)簽后。非特殊情況下大部分 JS 文件放在 <body> 標(biāo)簽尾部 ( 如果需要界面未加載前執(zhí)行的代碼可以放在 head 標(biāo)簽后 ) 避免行內(nèi) JS 和 CSS 代碼。
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<!-- 邏輯代碼 -->
<!-- 邏輯代碼底部 -->
<script src="lib/jquery/jquery-2.1.1.min.js"></script>
</body>
</html>
- 所有編碼需要遵循 html ( XML ) 標(biāo)準(zhǔn),標(biāo)簽 & 屬性 & 屬性命名必須由小寫(xiě)字母及下劃線數(shù)字組成,且所有標(biāo)簽必須閉合,包括 br(),hr() 等。屬性值用雙引號(hào)。應(yīng)當(dāng)按照以下給出的順序依次排列,來(lái)確保代碼的易讀性。
class
id 、 name
data-*
src、for、 type、 href
title、alt
aria-*、 role
- 引入 JS 庫(kù)文件,文件名須包含庫(kù)名稱及版本號(hào)及是否為壓縮版,比如 jquery-1.4.1.min.js。引入插件,文件名格式為庫(kù)名稱 + 插件名稱,比如 jQuery.bootstrap.js。
jQuery-1.8.3.min.js
- 書(shū)寫(xiě)頁(yè)面過(guò)程中,請(qǐng)考慮向后擴(kuò)展性。class & id 參見(jiàn) css 書(shū)寫(xiě)規(guī)范。
- 語(yǔ)義化 html,如標(biāo)題根據(jù)重要性用 h* ( 同一頁(yè)面只能有一個(gè) h1 ) ,段落標(biāo)記用 p ,列表用 ul ,內(nèi)聯(lián)元素中不可嵌套塊級(jí)元素。
- 盡可能減少 div 多層級(jí)嵌套。
- 書(shū)寫(xiě)鏈接地址時(shí),必須避免重定向,例如:href="https://github.com/thethreekingdoms/
",即須在 URL 地址后面加上 “ / ” 。 - 在頁(yè)面中盡量避免使用 style 屬性,即 style = " … " 。
- 能以背景形式呈現(xiàn)的圖片,盡量寫(xiě)入 css 樣式中。
- 重要圖片必須加上 alt 屬性。給重要的元素和截?cái)嗟脑丶由?title 。
- 給區(qū)塊代碼及重要功能 ( 比如循環(huán) ) 加上注釋,方便后臺(tái)添加功能。
- 特殊符號(hào)使用:盡可能使用代碼替代:比如 <(<)&>(>)& 空格 ()&?(?) 等等。
- 語(yǔ)義化 html ( HTML5 新增要求,減少 div 和 span 等無(wú)特定語(yǔ)義的標(biāo)簽使用 )