Code Review總結一些Vue開發規範經驗

規範與每一個團隊和我的都是息息相關的,由於其影響的不僅是隻是代碼的維護和理解成本,嚴重的時候是會影響成員開發的心情css

一個團隊的編碼規範、git規範等,並無絕對的最優解,內心要清楚明白沒有銀彈,規範是爲了讓團隊統一,提升代碼閱讀性、下降代碼維護成本等,本文是記錄一些在項目code review中常見的規範,僅供參考html

JS部分

和渲染無關的數據

vuedata的數據默認便會進行雙向數據綁定,如果將大量的和渲染無關的數據直接放置在data中,將會浪費雙向數據綁定時所消耗的性能,將這些和渲染無關的數據進行抽離並配合Object.freeze進行處理前端

tablecolumns數據能夠單獨提取一個外部js文件做爲配置文件,也能夠在當前.vue文件中定義一個常量定義columns數據,由於不管如何都是固定且不會修改的數據,應該使用Object.freeze進行包裹,既能夠提升性能還能夠將固定的數據抽離,一些下拉框前端固定的數據也建議此操做vue

const columnList = Object.freeze([
  { title: '姓名', key: 'name', align: 'center' },
  { title: '性別', key: 'gender', align: 'center' }
])
複製代碼

須要注意的是 Object.freeze() 凍結的是值,這時仍然能夠將變量的引用替換掉,還有確保數據不會變纔可使用這個語法,若是要對數據進行修改和交互,就不適合使用凍結了。git

Modal框的控制

一個頁面種一般會存在不少個不一樣功能的彈框,如果每個彈框都設置一個對應的變量來控制其顯示,則會致使變量數量比較冗餘和命名困難,可使用一個變量來控制同一頁面中的全部Modal彈框的展現web

好比某個頁面中存在三個Modal彈框ajax

// bad
// 每個數據控制對應的Modal展現與隱藏
new Vue({
    data() {
        return {
            modal1: false,
            modal2: false,
            modal3: false,
        }
    }
})

// good
// 當modalType爲對應的值時 展現其對應的彈框
new Vue({
    data() {
        return {
            modalType: '' // modalType值爲 modal1,modal2,modal3
        }
    }
})
複製代碼

debounce使用

例如遠程搜索時須要經過接口動態的獲取數據,如果每次用戶輸入都接口請求,是浪費帶寬和性能的json

當一個按鈕屢次點擊時會致使屢次觸發事件,能夠結合場景是否當即執行immediate瀏覽器

<Select :remote-method="remoteMethod">
    <Option v-for="item in temoteList" :value="item.value" :key="item.id">{{item.label}}</Option>
</Select>
複製代碼
import {debounce} from 'lodash'

methods:{
    remoteMethod: debounce(function (query) {
        // to do ...
      	// this 的指向沒有問題
    }, 200),
}
複製代碼

圖片

功能的開發過程當中,圖片的處理每每是比較容易被忽略的環節,也會在必定程度影響開發的效率和頁面的性能bash

  • 圖片壓縮問題,除非特別要求圖片必須高質量的顯示,不然都應該進行對應的壓縮處理

  • 不一樣業務場景進行圖片格式的選型

    • JPG 適用於呈現色彩豐富的圖片,JPG 圖片常常做爲大的背景圖、輪播圖或 Banner 圖出現等
    • Logo、顏色簡單且對比強烈的圖片或背景、須要透明度等
    • 將經常使用且變更頻率很低的小圖片進行合併成雪碧圖,對於變更比較頻繁和小於6KB的圖片進行base64處理
    • 根據項目圖片數量和項目的用戶機型分佈等,考慮採起webp進行圖片的處理

路由組件傳參

在組件中使用 $route 會使之與其對應路由造成高度耦合,從而使組件只能在某些特定的 URL 上使用,限制了其靈活性。

使用 props 將組件和路由解耦:

取代與 $route 的耦合

const User = {
  template: '<div>User {{ $route.params.id }}</div>'
}
const router = new VueRouter({
  routes: [
    { path: '/user/:id', component: User }
  ]
})
複製代碼

經過 props 解耦

這樣你即可以在任何地方使用該組件,使得該組件更易於重用和測試。

const User = {
  props: ['id'],
  template: '<div>User {{ id }}</div>'
}
const router = new VueRouter({
  routes: [
    { path: '/user/:id', component: User, props: true },

    // 對於包含命名視圖的路由,你必須分別爲每一個命名視圖添加 `props` 選項:
    {
      path: '/user/:id',
      components: { default: User, sidebar: Sidebar },
      props: { default: true, sidebar: false }
    }
  ]
})
複製代碼

參考:路由組件傳參

Vue生命週期

在父子組件中,掌握父子組件對應的生命週期鉤子加載順序可讓開發者在更合適的時候作適合的事情 父組件

<template>
  <div>
    <h3>home</h3>
    <list @hook:mounted="listMounted" />
  </div>
</template>

<script>
import List from './list'

export default {
  name: "home",
  components: {
    List
  },
  methods: {
    listMounted(){
      console.log('------------ listMounted');
    }
  },
  beforeCreate() {
    console.log("home beforeCreate");
  },
  created() {
    console.log("home created");
  },
  beforeMount() {
    console.log("home beforeMount");
  },
  mounted() {
    console.log("home mounted");
  },
  beforeDestroy() {
    console.log("home beforeDestroy");
  },
  destroyed() {
    console.log("home destroyed");
  }
}
</script>
複製代碼

子組件

<template>
  <div>
    list
  </div>
</template>

<script>
export default {
  naem: "list",
  beforeCreate() {
    console.log("list beforeCreate");
  },
  created() {
    console.log("list created");
  },
  beforeMount() {
    console.log("list beforeMount");
  },
  mounted() {
    console.log("list mounted");
  },
  beforeDestroy() {
    console.log("list beforeDestroy");
  },
  destroyed() {
    console.log("list destroyed");
  }
}
</script>
複製代碼

加載時父子組件的加載順序

home beforeCreate --> home created --> home beforeMount --> list created --> list beforeMount --> list mounted
複製代碼

銷燬時父子組件的銷燬順序

home beforeDestroy --> list beforeDestroy --> list destroyed --> home destroyed
複製代碼

實際開發過程當中會遇到當子組件某個生命週期完成以後通知父組件,而後在父組件作對應的處理

emit up

// 子組件在對應的鉤子中發佈事件
created(){
  this.$emit('done')
}

// 父組件訂閱其方發
<list @done="childDone">
複製代碼

hook

經過@hook監聽子組件的生命週期

<list @hook:mounted="listMounted" />
複製代碼

Select優化

下拉框遍歷時,須要注意options標籤保持同一行,如果存在換行,會致使選中時的值存在多餘的空白

<!-- bad -->
<Select :remote-method="remoteMethod">
    <Option v-for="item in temoteList" :value="item.value" :key="item.id">
        {{item.label}}
    </Option>
</Select>
複製代碼

須要將Options和下拉框的值保持在同一行

<!-- good -->
<Select :remote-method="remoteMethod">
    <Option v-for="item in temoteList" :value="item.value" :key="item.id">{{item.label}}</Option>
</Select>
複製代碼

data數據層級

data數據具備數據層級結構,切勿過分扁平化或者嵌套層級過深,如果過分扁平化會致使數據命名空間衝突,參數傳遞和處理,如果層級嵌套過深也會致使vue數據劫持的時候遞歸層級過深,如果嵌套層級喪心病狂那種的,當心遞歸爆棧的問題。並且層級過深會致使數據操做和處理不便,獲取數據作容錯處理也比較繁瑣。通常層級保持2-3層最好。

如果只有一層數據,過於扁平

{
    name: '',
    age: '',
    gender: ''
}
複製代碼

致使處理不方便

// 做爲接口參數傳遞
ajax({
	this.name, this.age, this.gender
})

// 接口獲取數據,批量處理
ajax().then(res => {
	const {name, age, gender} = res.data
    this.name = name
    this.age = age
    this.gender = gender
})
複製代碼

適當的層級結構不只增長代碼的維護和閱讀性,還能夠增長操做和處理的便捷性

{
    person: { // 我的信息
        name: '',
        age: '',
        gender: ''
    }
}
複製代碼

能夠針對person進行操做

// 做爲接口參數傳遞
ajax(this.person)

// 接口獲取數據,批量處理
ajax().then(res => {
	const {name, age, gender} = res.data
    this.$set(this, 'person', {name, age, gender})
})
複製代碼

策略模式

策略模式的使用,避免過多的if else判斷,也能夠替代簡單邏輯的switch

const formatDemandItemType = (value) => {
    switch (value) {
        case 1:
            return '基礎'
        case 2:
            return '高級'
        case 3:
            return 'VIP'
    }
}

// 策略模式
const formatDemandItemType2 = (value) => {
    const obj = {
        1: '基礎',
        2: '高級',
        3: 'VIP',
    }
    
    return obj[value]
}
複製代碼

解構

解構賦值以及默認值,當解構的數量小於多少時適合直接解構並賦值默認值,數據是否進行相關的聚合處理

const {
  naem = '',
  age = 10,
  gender = 'man'
} = res.data

// bad
this.name = name
this.age = age
this.gender = gender

// good
this.person = {
  naem,
  age,
  gender
}
複製代碼

職責單一

任什麼時候候儘可能是的一個函數就作一件事情,而不是將各類邏輯所有耦合在一塊兒,提升單個函數的複用性和可讀性

每一個頁面都會在加載完成時進行數據的請求並展現到頁面

created() {
  this.init();
},
methods: {
  // 將所有的請求行爲聚合在init函數中
  // 將每一個請求單獨拆分
  init() {
    this.getList1()
    this.getList2()
  },
  getList1() {
    // to do ...
  },
  getList2() {
    // to do ...
  }
}
複製代碼

v-bind

HTML部分

html書寫

編寫template模板時,屬性過多時,是否換行

<template>
  <!-- 不換行 -->
  <VueButton class="icon-button go-up" icon-left="keyboard_arrow_up" v-tooltip="$t('org.vue.components.folder-explorer.toolbar.tooltips.parent-folder')" @click="openParentFolder" />

  <!-- 換行 -->
  <VueButton
    class="icon-button go-up"
    icon-left="keyboard_arrow_up"
    v-tooltip="$t('org.vue.components.folder-explorer.toolbar.tooltips.parent-folder')"
    @click="openParentFolder"
  />
</template>
複製代碼

實體使用

html中展現一些如<>,&等字符時,使用字符實體代替

<!-- bad -->
<div>
  > 1 & < 12
</div>
  
<!-- bad -->
<div>
  &gt; 1 &amp; &lt; 12
</div>
複製代碼

CSS部分

樣式穿透

在開發中修改第三方組件樣式是很常見,但因爲 scoped 屬性的樣式隔離,可能須要去除 scoped 或是另起一個 style 。這些作法都會帶來反作用(組件樣式污染、不夠優雅),樣式穿透在css預處理器中使用才生效。

  • less使用 /deep/
<style scoped lang="less">
.content /deep/ .el-button {
	 height: 60px;
}
</style>
複製代碼
  • scss使用 ::v-deep
<style scoped lang="scss">
.content ::v-deep .el-button {
  height: 60px;
}
</style>

複製代碼
  • stylus使用 >>>
<style scoped ang="stylus">
外層 >>> .custon-components{
  height: 60px;
}
</style>
複製代碼

空格

適當的空格能夠提高代碼的閱讀體驗,顯得更爲優雅和美觀

選擇器後、屬性值

.custom-style { // 選擇器和{ 之間空格
  margin: 0; // 屬性值前
  transform: scale(1.5, 2.2); // 逗號以後增長空格
}
複製代碼

換行

html類型,當某行的屬性不少,適當的換行能夠提升閱讀和美觀

.custom-style{
  // 能夠在一次聲明中定義一個或多個屬性
  background: background-clip
    background-color
    background-image
    background-origin
    background-position
    background-repeat
    background-size;
}
複製代碼

當一個規則包含多個選擇器時,每一個選擇器聲明必須獨佔一行,過長致使須要橫向滾動閱讀剩餘的內容,應該儘可能使得閱讀順序縱向化

.custom .header .title.other .header .title {
  color: #f0f;
}
複製代碼

嵌套層級

瀏覽器在解析css時,是按照從右到左遞歸匹配的,過深的層級嵌套不只影響性能,並且還會致使樣式閱讀性和代碼維護性下降,通常層架控制在5層以內

雙引號

屬性選擇器中的值必須用雙引號包圍,不容許使用單引號,也不容許不使用引號,html的屬性值也是推薦使用雙引號,js中使用單引號

.custom-style{
	font-family: "PingFang SC", "STHeitiSC-Light";  
}
複製代碼

屬性順序

同一 規則下的屬性在書寫時,應按功能進行分組。 並以 Formatting Model(佈局方式、位置) > Box Model(尺寸) > Typographic(文本相關) > Visual(視覺效果) 的順序書寫,以提升代碼的可讀性。

解釋

  • Formatting Model 相關屬性包括:position / top / right / bottom / left / float / display / overflow 等
  • Box Model 相關屬性包括:border / margin / padding / width / height 等
  • Typographic 相關屬性包括:font / line-height / text-align / word-wrap 等
  • Visual 相關屬性包括:background / color / transition / list-style 等

另外,爲增長可讀性,若是包含 content 屬性,應放在屬性的最前面。

參考

相關文章
相關標籤/搜索