前端團隊有評審代碼的要求,但因爲每一個開發人員的水平不一樣,技術關注點不一樣,因此對代碼評審的關注點不一樣,爲了保證代碼質量,團隊代碼風格統一,特此擬定一份《前端團隊代碼評審 CheckList 清單》,這樣代碼評審人員在評審代碼時,能夠參照這份清單,對代碼進行評審。從而輔助整個團隊提升代碼質量、統一代碼規範。若是你的團隊尚未這麼一份代碼評審 CheckList 清單,也許這正是你須要的;若是你的團隊已經有了代碼評審參照標準,這份清單也許能起到錦上添花的效果。javascript
辛苦整理良久,還望手動 Star 鼓勵~
github地址爲:https://github.com/fengshi123...,若是喜歡或者有所啓發,請幫忙給個 star ~,對做者也是一種鼓勵。css
eslint 檢查的規範繼承自 eslint-config-standard 檢驗規則,具體的規則介紹參照連接:https://cn.eslint.org/docs/ru... ,這裏及如下部分再也不重複介紹這些檢驗規則。前端
stylelint 檢查的規範繼承自 stylelint-config-standard 檢驗規則,具體的規則介紹參照連接:https://www.npmjs.com/package... ,這裏及如下部分再也不重複介紹這些檢驗規則。vue
推薦:java
studentInfot
推薦:git
const Car = { make: "Honda", model: "Accord", color: "Blue" };
不推薦:github
const Car = { carMake: "Honda", carModel: "Accord", carColor: "Blue" };
推薦:vuex
.block__element{} .block--modifier{}
命名須要符合語義化,若是函數命名,能夠採用加上動詞前綴:npm
動詞 | 含義 |
---|---|
can | 判斷是否可執行某個動做 |
has | 判斷是否含有某個值 |
is | 判斷是否爲某個值 |
get | 獲取某個值 |
set | 設置某個值 |
推薦:編程
//是否可閱讀 function canRead(){ return true; } //獲取姓名 function getName{ return this.name }
每一個常量應該命名,否則看代碼的人不知道這個常量表示什麼意思。
推薦:
const COL_NUM = 10; let row = Math.ceil(num/COL_NUM);
不推薦:
let row = Math.ceil(num/10);
建立對象和數組推薦使用字面量,由於這不只是性能最優也有助於節省代碼量。
推薦:
let obj = { name:'tom', age:15, sex:'男' }
不推薦:
let obj = {}; obj.name = 'tom'; obj.age = 15; obj.sex = '男';
推薦:
const menuConfig = { title: "Order", // User did not include 'body' key buttonText: "Send", cancellable: true }; function createMenu(config) { config = Object.assign( { title: "Foo", body: "Bar", buttonText: "Baz", cancellable: true }, config ); // config now equals: {title: "Order", body: "Bar", buttonText: "Send", cancellable: true} // ... } createMenu(menuConfig);
不推薦:
const menuConfig = { title: null, body: "Bar", buttonText: null, cancellable: true }; function createMenu(config) { config.title = config.title || "Foo"; config.body = config.body || "Bar"; config.buttonText = config.buttonText || "Baz"; config.cancellable = config.cancellable !== undefined ? config.cancellable : true; } createMenu(menuConfig);
對象成員嵌套越深,讀取速度也就越慢。因此好的經驗法則是:若是在函數中須要屢次讀取一個對象屬性,最佳作法是將該屬性值保存在局部變量中,避免屢次查找帶來的性能開銷。
推薦:
let person = { info:{ sex:'男' } } function getMaleSex(){ let sex = person.info.sex; if(sex === '男'){ console.log(sex) } }
不推薦:
let person = { info:{ sex:'男' } } function getMaleSex(){ if(person.info.sex === '男'){ console.log(person.info.sex) } }
當須要將浮點數轉換成整型時,應該使用Math.floor()
或者Math.round()
,而不是使用parseInt()
將字符串轉換成數字。Math是內部對象,因此
Math.floor()`其實並無多少查詢方法和調用時間,速度是最快的。
推薦:
let num = Math.floor('1.6');
不推薦:
let num = parseInt('1.6');
函數參數越少越好,若是參數超過兩個,要使用 ES6的解構語法,不用考慮參數的順序。
推薦:
function createMenu({ title, body, buttonText, cancellable }) { // ... } createMenu({ title: 'Foo', body: 'Bar', buttonText: 'Baz', cancellable: true });
不推薦:
function createMenu(title, body, buttonText, cancellable) { // ... }
使用參數默認值 替代 使用條件語句進行賦值。
推薦:
function createMicrobrewery(name = "Hipster Brew Co.") { // ... }
不推薦:
function createMicrobrewery(name) { const breweryName = name || "Hipster Brew Co."; // ... }
這是一條在軟件工程領域流傳久遠的規則。嚴格遵照這條規則會讓你的代碼可讀性更好,也更容易重構。若是違反這個規則,那麼代碼會很難被測試或者重用 。
在 JavaScript 中,永遠不要污染全局,會在生產環境中產生難以預料的 bug。舉個例子,好比你在 Array.prototype
上新增一個 diff
方法來判斷兩個數組的不一樣。而你同事也打算作相似的事情,不過他的 diff
方法是用來判斷兩個數組首位元素的不一樣。很明顯大家方法會產生衝突,遇到這類問題咱們能夠用 ES2015/ES6 的語法來對 Array
進行擴展。
推薦:
class SuperArray extends Array { diff(comparisonArray) { const hash = new Set(comparisonArray); return this.filter(elem => !hash.has(elem)); } }
不推薦:
Array.prototype.diff = function diff(comparisonArray) { const hash = new Set(comparisonArray); return this.filter(elem => !hash.has(elem)); };
函數式變編程可讓代碼的邏輯更清晰更優雅,方便測試。
推薦:
const programmerOutput = [ { name: 'Uncle Bobby', linesOfCode: 500 }, { name: 'Suzie Q', linesOfCode: 1500 }, { name: 'Jimmy Gosling', linesOfCode: 150 }, { name: 'Gracie Hopper', linesOfCode: 1000 } ]; let totalOutput = programmerOutput .map(output => output.linesOfCode) .reduce((totalLines, lines) => totalLines + lines, 0)
不推薦:
const programmerOutput = [ { name: 'Uncle Bobby', linesOfCode: 500 }, { name: 'Suzie Q', linesOfCode: 1500 }, { name: 'Jimmy Gosling', linesOfCode: 150 }, { name: 'Gracie Hopper', linesOfCode: 1000 } ]; let totalOutput = 0; for (let i = 0; i < programmerOutput.length; i++) { totalOutput += programmerOutput[i].linesOfCode; }
爲了讓代碼更簡潔易讀,若是你的函數中出現了條件判斷,那麼說明你的函數不止幹了一件事情,違反了函數單一原則 ;而且絕大數場景可使用多態替代
推薦:
class Airplane { // ... } // 波音777 class Boeing777 extends Airplane { // ... getCruisingAltitude() { return this.getMaxAltitude() - this.getPassengerCount(); } } // 空軍一號 class AirForceOne extends Airplane { // ... getCruisingAltitude() { return this.getMaxAltitude(); } } // 賽納斯飛機 class Cessna extends Airplane { // ... getCruisingAltitude() { return this.getMaxAltitude() - this.getFuelExpenditure(); } }
不推薦:
class Airplane { // ... // 獲取巡航高度 getCruisingAltitude() { switch (this.type) { case '777': return this.getMaxAltitude() - this.getPassengerCount(); case 'Air Force One': return this.getMaxAltitude(); case 'Cessna': return this.getMaxAltitude() - this.getFuelExpenditure(); } } }
代碼中使用了定時器 setTimeout 和 setInterval,須要在不使用時進行清除。
利用scss中的變量配置,能夠進行項目的顏色、字體大小統一更改(換膚),有利於後期項目的維護。
推薦:
$--color-success: #67C23A; $--color-warning: #E6A23C; $--color-danger: #F56C6C; $--color-info: #909399;
scss中的@import規則在生成css文件時就把相關文件導入進來。這意味着全部相關的樣式被概括到了同一個css文件中,而無需發起額外的下載請求,在構建咱們本身的組件庫時推薦使用。
@import "./base.scss"; @import "./pagination.scss"; @import "./dialog.scss"; @import "./autocomplete.scss"; @import "./dropdown.scss"; @import "./dropdown-menu.scss";
scss局部文件的文件名如下劃線開頭。這樣,scss就不會在編譯時單獨編譯這個文件輸出css,而只把這個文件用做導入。
推薦:
scss的嵌套和父選擇器標識符&能解決BEM命名的冗長,且使樣式可讀性更高。
推薦:
.el-input { display: block; &__inner { text-align: center; } }
mixin混合器用來實現大段樣式的重用,減小代碼的冗餘,且支持傳參。
@mixin button-size($padding-vertical, $padding-horizontal, $font-size, $border-radius) { padding: $padding-vertical $padding-horizontal; font-size: $font-size; border-radius: $border-radius; &.is-round { padding: $padding-vertical $padding-horizontal; } } @include m(medium) { @include button-size($--button-medium-padding-vertical, $--button-medium-padding-horizontal, $--button-medium-font-size, $--button-medium-border-radius); } @include m(small) { @include button-size($--button-small-padding-vertical, $--button-small-padding-horizontal, $--button-small-font-size, $--button-small-border-radius); }
(1)使用@extend產生 DRY CSS風格的代碼(Don't repeat yourself)
(2)@mixin主要的優點就是它可以接受參數。若是想傳遞參數,你會很天然地選擇@mixin而不是@extend
推薦:
.common-mod { height: 250px; width: 50%; background-color: #fff; text-align: center; } .show-mod--right { @extend .common-mod; float: right; } .show-mod--left { @extend .common-mod; }
插值能動態定義類名的名稱,當有兩個頁面的樣式相似時,咱們會將相似的樣式抽取成頁面混合器,但兩個不一樣的頁面樣式的命名名稱根據BEM命名規範不能同樣,這時咱們可以使用插值進行動態命名。
推薦:
@mixin home-content($class) { .#{$class} { position: relative; background-color: #fff; overflow-x: hidden; overflow-y: hidden; &--left { margin-left: 160px; } &--noleft { margin-left: 0; } } }
可經過each遍歷、map數據類型、@mixin/@include混合器、#{}插值 結合使用,從而減小冗餘代碼,使代碼更精簡。
推薦:
$img-list: ( (xlsimg, $papers-excel), (xlsximg, $papers-excel), (gifimg, $papers-gif), (jpgimg, $papers-jpg), (mp3img, $papers-mp3), (mp4img, $papers-mp3), (docimg, $papers-word), (docximg, $papers-word), (rarimg, $papers-zip), (zipimg, $papers-zip), (unknownimg, $papers-unknown) ); @each $label, $value in $img-list { .com-hwicon__#{$label} { @include commonImg($value); } }
scss自帶函數的應用,從而進行相關的計算,例如 mix函數的使用以下。
@include m(text) { &:hover, &:focus { color: mix($--color-white, $--color-primary, $--button-hover-tint-percent); border-color: transparent; background-color: transparent; } &:active { color: mix($--color-black, $--color-primary, $--button-active-shade-percent); border-color: transparent; background-color: transparent; } }
gulp-sass插件能實時監測scss代碼檢查其語法錯誤並將其編譯成css代碼,幫助開發人員檢查scss語法的準確性,且其是否符合咱們的預期,相關配置以下:
gulp.task('gulpsass', function() { return gulp.src('src/style/components/hwIcon.scss') .pipe(gulpsass().on('error', gulpsass.logError)) .pipe(gulp.dest('src/style/dest')); }); gulp.task('watch', function() { gulp.watch('src/style/components/hwIcon.scss', ['gulpsass']); });
咱們開發過程當中自定義的組件的名稱須要爲多個單詞,這樣作能夠避免跟現有的以及將來的HTML元素相沖突,由於全部的 HTML 元素名稱都是單個單詞的。
推薦:
Vue.component('todo-item', { // ... }) export default { name: 'TodoItem', // ... }
不推薦:
Vue.component('todo', { // ... }) export default { name: 'Todo', // ... }
當在組件中使用 data
屬性的時候 (除了 new Vue
外的任何地方),它的值必須是返回一個對象的函數。 由於若是直接是一個對象的話,子組件之間的屬性值會互相影響。
推薦:
export default { data () { return { foo: 'bar' } } }
不推薦:
export default { data: { foo: 'bar' } }
prop 的定義應該儘可能詳細,至少須要指定其類型。
推薦:
props: { status: String } // 更好的作法! props: { status: { type: String, required: true, validator: function (value) { return [ 'syncing', 'synced', 'version-conflict', 'error' ].indexOf(value) !== -1 } } }
不推薦:
props: ['status']
v-for 中老是有設置 key 值。在組件上老是必須用 key
配合 v-for
,以便維護內部組件及其子樹的狀態。
推薦:
<ul> <li v-for="todo in todos" :key="todo.id"> {{ todo.text }} </li> </ul>
不推薦:
<ul> <li v-for="todo in todos"> {{ todo.text }} </li> </ul>
組件名應該傾向於完整單詞而不是縮寫,編輯器中的自動補全已經讓書寫長命名的代價很是之低了,而其帶來的明確性倒是很是寶貴的。不經常使用的縮寫尤爲應該避免。
推薦:
components/ |- StudentDashboardSettings.vue |- UserProfileOptions.vue
不推薦:
components/ |- SdSettings.vue |- UProfOpts.vue
在 JavaScript 中,用多行分隔對象的多個屬性是很常見的最佳實踐,由於這樣更易讀。
推薦:
<MyComponent foo="a" bar="b" baz="c" />
不推薦:
<MyComponent foo="a" bar="b" baz="c"/>
組件模板應該只包含簡單的表達式,複雜的表達式則應該重構爲計算屬性或方法。複雜表達式會讓你的模板變得不那麼聲明式。咱們應該儘可能描述應該出現的是什麼,而非如何計算那個值。並且計算屬性和方法使得代碼能夠重用。
推薦:
<!-- 在模板中 --> {{ normalizedFullName }} // 複雜表達式已經移入一個計算屬性 computed: { normalizedFullName: function () { return this.fullName.split(' ').map(function (word) { return word[0].toUpperCase() + word.slice(1) }).join(' ') } }
不推薦:
{{ fullName.split(' ').map(function (word) { return word[0].toUpperCase() + word.slice(1) }).join(' ') }}
應該把複雜計算屬性分割爲儘量多的更簡單的屬性。
推薦:
computed: { basePrice: function () { return this.manufactureCost / (1 - this.profitMargin) }, discount: function () { return this.basePrice * (this.discountPercent || 0) }, finalPrice: function () { return this.basePrice - this.discount } }
不推薦:
computed: { price: function () { var basePrice = this.manufactureCost / (1 - this.profitMargin) return ( basePrice - basePrice * (this.discountPercent || 0) ) } }
指令推薦都使用縮寫形式,(用 : 表示 v-bind: 、用 @ 表示 v-on: 和用 # 表示 v-slot:)。
推薦:
<input @input="onInput" @focus="onFocus" >
不推薦:
<input v-on:input="onInput" @focus="onFocus" >
單文件組件應該老是讓標籤順序保持爲 <template> 、<script>、 <style> 。
推薦:
<!-- ComponentA.vue --> <template>...</template> <script>/* ... */</script> <style>/* ... */</style>
不推薦:
<!-- ComponentA.vue --> <template>...</template> <style>/* ... */</style> <script>/* ... */</script>
父子組件的通訊推薦使用 prop和 emit ,而不是this.$parent或改變 prop;
兄弟組件之間的通訊推薦使用 EventBus($emit / $on),而不是濫用 vuex;
祖孫組件之間的通訊推薦使用 $attrs / $listeners 或 provide / inject(依賴注入) ,而不是濫用 vuex;
頁面跳轉,例如 A 頁面跳轉到 B 頁面,須要將 A 頁面的數據傳遞到 B 頁面,推薦使用 路由參數進行傳參,而不是將須要傳遞的數據保存 vuex,而後在 B 頁面取出 vuex的數據,由於若是在 B 頁面刷新會致使 vuex 數據丟失,致使 B 頁面沒法正常顯示數據。
推薦:
let id = ' 123'; this.$router.push({name: 'homeworkinfo', query: {id:id}});
script 標籤內部的聲明順序以下:
data > prop > components > filter > computed > watch > 鉤子函數(鉤子函數按其執行順序) > methods
推薦:
若是運行時,須要很是頻繁地切換,推薦使用 v-show 比較好;若是在運行時,條件不多改變,則推薦使用 v-if 比較好。
由於團隊如今使用 vue 框架,因此在項目開發中儘可能使用 vue 的特性去知足咱們的需求,儘可能(不到萬不得已)不要手動操做DOM,包括:增刪改dom元素、以及更改樣式、添加事件等。
不少時候有些代碼已經沒有用了,可是沒有及時去刪除,這樣致使代碼裏面包括不少註釋的代碼塊,好的習慣是提交代碼前記得刪除已經確認棄用的代碼,例如:一些調試的console語句、無用的棄用代碼。
代碼註釋不是越多越好,保持必要的業務邏輯註釋,至於函數的用途、代碼邏輯等,要經過語義化的命令、簡單明瞭的代碼邏輯,來讓閱讀代碼的人快速看懂。
辛苦整理良久,還望手動 Star 鼓勵~
github地址爲:https://github.com/fengshi123...,若是喜歡或者有所啓發,請幫忙給個 star ~,對做者也是一種鼓勵。