前端團隊代碼評審 CheckList 清單

前言

前端團隊有評審代碼的要求,但因爲每一個開發人員的水平不一樣,技術關注點不一樣,因此對代碼評審的關注點不一樣,爲了保證代碼質量,團隊代碼風格統一,特此擬定一份《前端團隊代碼評審 CheckList 清單》,這樣代碼評審人員在評審代碼時,能夠參照這份清單,對代碼進行評審。從而輔助整個團隊提升代碼質量、統一代碼規範。若是你的團隊尚未這麼一份代碼評審 CheckList 清單,也許這正是你須要的;若是你的團隊已經有了代碼評審參照標準,這份清單也許能起到錦上添花的效果。javascript

辛苦整理良久,還望手動點贊鼓勵~css

github地址爲:github.com/fengshi123/…,若是喜歡或者有所啓發,請幫忙給個 star ~,對做者也是一種鼓勵。前端

1、代碼靜態檢查工具

1.一、使用 eslint 工具對 javascript 代碼進行檢查

eslint 檢查的規範繼承自 eslint-config-standard 檢驗規則,具體的規則介紹參照連接:cn.eslint.org/docs/rules/ ,這裏及如下部分再也不重複介紹這些檢驗規則。
vue

1.二、使用 stylelint 工具對 css 樣式代碼進行檢查

stylelint 檢查的規範繼承自 stylelint-config-standard 檢驗規則,具體的規則介紹參照連接:www.npmjs.com/package/sty… ,這裏及如下部分再也不重複介紹這些檢驗規則。
java

2、命名規範

2.一、JS 採用 Camel Case 小駝峯式命名

推薦:git

studentInfot複製代碼

2.二、避免名稱冗餘

推薦:github

const Car = {
  make: "Honda",
  model: "Accord",
  color: "Blue"
};複製代碼

不推薦:vuex

const Car = {
  carMake: "Honda",
  carModel: "Accord",
  carColor: "Blue"
};複製代碼

2.三、CSS 類名採用 BEM 命名規範

推薦:
npm

.block__element{} 
.block--modifier{}複製代碼

2.四、命名符合語義化

命名須要符合語義化,若是函數命名,能夠採用加上動詞前綴:
編程

動詞 含義
can 判斷是否可執行某個動做
has 判斷是否含有某個值
is 判斷是否爲某個值
get 獲取某個值
set 設置某個值

推薦:

//是否可閱讀 
function canRead(){ 
   return true; 
} 
//獲取姓名 
function getName{
   return this.name 
} 複製代碼

3、JS 推薦寫法

3.一、每一個常量都需命名

每一個常量應該命名,否則看代碼的人不知道這個常量表示什麼意思。

推薦:

const COL_NUM = 10;
let row = Math.ceil(num/COL_NUM);複製代碼

不推薦:

let row = Math.ceil(num/10);複製代碼

3.二、推薦使用字面量

建立對象和數組推薦使用字面量,由於這不只是性能最優也有助於節省代碼量。

推薦:

let obj = {   
     name:'tom',     
     age:15,     
     sex:'男' 
} 複製代碼

不推薦:

let obj = {};
obj.name = 'tom';
obj.age = 15;
obj.sex = '男';複製代碼

3.三、對象設置默認屬性的推薦寫法

推薦:

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);
複製代碼

3.四、將對象的屬性值保存爲局部變量

對象成員嵌套越深,讀取速度也就越慢。因此好的經驗法則是:若是在函數中須要屢次讀取一個對象屬性,最佳作法是將該屬性值保存在局部變量中,避免屢次查找帶來的性能開銷。

推薦:

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)
    }
} 
複製代碼

3.五、字符串轉爲整型

當須要將浮點數轉換成整型時,應該使用Math.floor()或者Math.round(),而不是使用parseInt()將字符串轉換成數字。Math 是內部對象,因此Math.floor()其實並無多少查詢方法和調用時間,速度是最快的。

推薦:

let num = Math.floor('1.6');複製代碼

不推薦:

let num = parseInt('1.6');複製代碼

3.六、函數參數

函數參數越少越好,若是參數超過兩個,要使用 ES6的解構語法,不用考慮參數的順序。

推薦:

function createMenu({ title, body, buttonText, cancellable }) {
  // ...
}

createMenu({
  title: 'Foo',
  body: 'Bar',
  buttonText: 'Baz',
  cancellable: true
});
複製代碼

不推薦:

function createMenu(title, body, buttonText, cancellable) {
  // ...
}
複製代碼

3.七、使用參數默認值

使用參數默認值 替代 使用條件語句進行賦值。

推薦:

function createMicrobrewery(name = "Hipster Brew Co.") {
  // ...
}
複製代碼

不推薦:

function createMicrobrewery(name) {
  const breweryName = name || "Hipster Brew Co.";
  // ...
}複製代碼

3.八、最小函數準則

這是一條在軟件工程領域流傳久遠的規則。嚴格遵照這條規則會讓你的代碼可讀性更好,也更容易重構。若是違反這個規則,那麼代碼會很難被測試或者重用 。

3.九、不要寫全局方法

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));
};

複製代碼

 3.十、推薦函數式編程

函數式變編程可讓代碼的邏輯更清晰更優雅,方便測試。

推薦:

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;
}複製代碼

3.十一、使用多態替換條件語句

爲了讓代碼更簡潔易讀,若是你的函數中出現了條件判斷,那麼說明你的函數不止幹了一件事情,違反了函數單一原則 ;而且絕大數場景可使用多態替代

推薦:

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();
    }
  }
}複製代碼

3.十二、定時器是否清除

代碼中使用了定時器 setTimeoutsetInterval,須要在不使用時進行清除。

4、SCSS 推薦寫法

4.一、變量 $ 使用

利用scss中的變量配置,能夠進行項目的顏色、字體大小統一更改(換膚),有利於後期項目的維護。

推薦:

$--color-success: #67C23A;
$--color-warning: #E6A23C;
$--color-danger: #F56C6C;
$--color-info: #909399;
複製代碼

4.二、@import 導入樣式文件

scss中的@import規則在生成css文件時就把相關文件導入進來。這意味着全部相關的樣式被概括到了同一個css文件中,而無需發起額外的下載請求,在構建咱們本身的組件庫時推薦使用。

@import "./base.scss";
@import "./pagination.scss";
@import "./dialog.scss";
@import "./autocomplete.scss";
@import "./dropdown.scss";
@import "./dropdown-menu.scss";

複製代碼

4.三、局部文件命名的使用

scss局部文件的文件名如下劃線開頭。這樣,scss就不會在編譯時單獨編譯這個文件輸出css,而只把這個文件用做導入。

推薦:


4.四、父選擇器標識符 & 實現BEM 命令規範

scss的嵌套和父選擇器標識符 & 能解決BEM命名的冗長,且使樣式可讀性更高。

推薦:

.el-input {
​  display: block;
​  &__inner {
​     text-align: center;
​  }
}複製代碼

4.五、@mixin 混合器的使用

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);
  } 

複製代碼

4.六、@extend 指令的使用

(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;
​}

複製代碼

4.七、#{} 插值的使用

插值能動態定義類名的名稱,當有兩個頁面的樣式相似時,咱們會將相似的樣式抽取成頁面混合器,但兩個不一樣的頁面樣式的命名名稱根據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;
​    }
  }
}

複製代碼

 4.八、each遍歷、map數據類型、@mixin/@include混合器、#{}插值 結合使用

可經過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);
  }
}

複製代碼

4.九、scss 自帶函數的應用

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;
​    }
}

複製代碼

4.十、gulp-sass的使用

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']);
});
複製代碼

5、Vue 推薦寫法

5.一、組件名爲多個單詞

咱們開發過程當中自定義的組件的名稱須要爲多個單詞,這樣作能夠避免跟現有的以及將來的HTML元素相沖突,由於全部的 HTML 元素名稱都是單個單詞的。

推薦:

Vue.component('todo-item', {
  // ...
})

export default {
  name: 'TodoItem',
  // ...
}複製代碼

不推薦:

Vue.component('todo', {
  // ...
})

export default {
  name: 'Todo',
  // ...
}

複製代碼

5.二、組件的 data 必須是一個函數

當在組件中使用 data 屬性的時候 (除了 new Vue 外的任何地方),它的值必須是返回一個對象的函數。 由於若是直接是一個對象的話,子組件之間的屬性值會互相影響。

推薦:

export default {
  data () {
​    return {
​      foo: 'bar'
​    }
  }
}複製代碼

不推薦:

export default {
  data: {
​    foo: 'bar'
  }
}複製代碼

5.三、Prop定義應該儘可能詳細

prop 的定義應該儘可能詳細,至少須要指定其類型。

推薦:

props: {
  status: String
}

// 更好的作法!
props: {
  status: {
​    type: String,
​    required: true,
​    validator: function (value) {
​      return [
​        'syncing',
​        'synced',
​        'version-conflict',
​        'error'
​      ].indexOf(value) !== -1
​    }
  }
}複製代碼

不推薦:

props: ['status'] 複製代碼

5.四、爲 v-for 設置鍵值

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>複製代碼


5.五、完整單詞的組件名

組件名應該傾向於完整單詞而不是縮寫,編輯器中的自動補全已經讓書寫長命名的代價很是之低了,而其帶來的明確性倒是很是寶貴的。不經常使用的縮寫尤爲應該避免。

推薦:

components/ 
|- StudentDashboardSettings.vue 
|- UserProfileOptions.vue 複製代碼

不推薦:

components/ 
|- SdSettings.vue 
|- UProfOpts.vue 複製代碼

5.六、多個特性元素的每一個特性分行

JavaScript 中,用多行分隔對象的多個屬性是很常見的最佳實踐,由於這樣更易讀。

推薦:

<MyComponent
  foo="a"
  bar="b"
  baz="c"
/>複製代碼

不推薦:

<MyComponent foo="a" bar="b" baz="c"/> 複製代碼

5.七、模板中簡單的表達式

組件模板應該只包含簡單的表達式,複雜的表達式則應該重構爲計算屬性或方法。複雜表達式會讓你的模板變得不那麼聲明式。咱們應該儘可能描述應該出現的是什麼,而非如何計算那個值。並且計算屬性和方法使得代碼能夠重用。

推薦:

<!-- 在模板中 -->
{{ 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(' ')
}}複製代碼

5.八、簡單的計算屬性

應該把複雜計算屬性分割爲儘量多的更簡單的屬性。

推薦:

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)
​    )
  }
}複製代碼

5.九、指令縮寫

指令推薦都使用縮寫形式,(用 : 表示 v-bind: 、用 @ 表示 v-on: 和用 # 表示 v-slot:)。

推薦:

<input
  @input="onInput"
  @focus="onFocus"
>複製代碼

不推薦:

<input
  v-on:input="onInput"
  @focus="onFocus"
>複製代碼

5.十、標籤順序保持一致

單文件組件應該老是讓標籤順序保持爲 <template> 、<script>、 <style> 。

推薦:

<!-- ComponentA.vue -->

<template>...</template>
<script>/* ... */</script>
<style>/* ... */</style>複製代碼

不推薦:

<!-- ComponentA.vue -->

<template>...</template>
<style>/* ... */</style>
<script>/* ... */</script>複製代碼

5.十一、組件之間通訊

父子組件的通訊推薦使用 propemit ,而不是this.​$parent或改變 prop

兄弟組件之間的通訊推薦使用 EventBus(on),而不是濫用 vuex

祖孫組件之間的通訊推薦使用​listeners provide / inject(依賴注入) ,而不是濫用 vuex

5.十二、頁面跳轉數據傳遞

頁面跳轉,例如 A 頁面跳轉到 B 頁面,須要將 A 頁面的數據傳遞到 B 頁面,推薦使用 路由參數進行傳參,而不是將須要傳遞的數據保存 vuex,而後在 B 頁面取出 vuex的數據,由於若是在 B 頁面刷新會致使 vuex 數據丟失,致使 B 頁面沒法正常顯示數據。

推薦:

let id = ' 123';
this.$router.push({name: 'homeworkinfo', query: {id:id}}); 複製代碼

 5.1三、script 標籤內部聲明順序

script 標籤內部的聲明順序以下:

data > prop > components > filter > computed >  watch > 
鉤子函數(鉤子函數按其執行順序)> methods複製代碼

5.1四、計算屬性 VS 方法 VS 偵聽器

  • (1)推薦使用計算屬性:計算屬性基於響應式依賴進行緩存,只在相關響應式依賴發生改變時它們纔會從新求值;相比之下,每次調用方法都會再次執行方法;

  • (2)推薦使用計算屬性:而不是根據 Watch 偵聽屬性,進行回調; 可是有計算屬性作不到的:當須要在數據變化時執行異步或開銷較大的操做時,偵聽器是最有用的。

5.1五、v-if VS v-show

  • v-if 是「真正」的條件渲染,由於它會確保在切換過程當中條件塊內的事件監聽器和子組件適當地被銷燬和重建。 v-if 也是惰性的:若是在初始渲染時條件爲假,則什麼也不作——直到條件第一次變爲真時,纔會開始渲染條件塊。

  • 相比之下,v-show 就簡單得多——無論初始條件是什麼,元素老是會被渲染,而且只是簡單地基於 CSS 的屬性 display 進行切換。

推薦:

若是運行時,須要很是頻繁地切換,推薦使用 v-show 比較好;若是在運行時,條件不多改變,則推薦使用 v-if 比較好。

6、團隊其它規範

6.一、儘可能不手動操做 DOM

由於團隊如今使用 vue 框架,因此在項目開發中儘可能使用 vue 的特性去知足咱們的需求,儘可能(不到萬不得已)不要手動操做DOM,包括:增刪改dom元素、以及更改樣式、添加事件等。

6.二、刪除棄用代碼

不少時候有些代碼已經沒有用了,可是沒有及時去刪除,這樣致使代碼裏面包括不少註釋的代碼塊,好的習慣是提交代碼前記得刪除已經確認棄用的代碼,例如:一些調試的console語句、無用的棄用代碼。

6.三、保持必要的註釋

代碼註釋不是越多越好,保持必要的業務邏輯註釋,至於函數的用途、代碼邏輯等,要經過語義化的命令、簡單明瞭的代碼邏輯,來讓閱讀代碼的人快速看懂。


辛苦整理良久,若是對你有幫助,還望手動點贊鼓勵~~~~~~

github地址爲:github.com/fengshi123/…,若是喜歡或者有所啓發,請幫忙給個 star ~,對做者也是一種鼓勵。


參考文獻

一、clean-code-javascriptgithub.com/ryanmcdermo…

二、SCSS — 縮減50%的樣式代碼 : juejin.im/post/5c4888…

三、vue cookbookcn.vuejs.org/v2/cookbook…

相關文章
相關標籤/搜索