天天看點

Vuex進階篇——Module子產品化學習(前端必會)

我之前釋出了一篇vuex的基礎,如果你巧妙的将它遺忘, 這是個傳送門,點選複習。 我也是一直在看vuex,裡邊需要了解的知識其實不少,但是因為項目并不常用,是以也總是忘記,今天整理下來,和大家談談 vueX

的子產品化開發。這個重要不? 這麼說:大廠必會,項目必備!若是不會,學!(●'◡'●)

寫前吐槽:我參考了很多人寫的部落格,并不是很清晰,甚至有人直接把vue官網複制到了部落格,浏覽了一下,居然一個字都不差。是以部落客很是無語,今天就說一下vuex的子產品化。寫這篇文章,部落客的頭發又掉了一根,先哭一會。。。

問題:什麼是vuex module,為什麼要使用vuex子產品化?

答: 子產品化,就是将vuex分為不同的子產品,無論從項目上還是結構上,都容易維護,我們再平時寫的vuex中,都是在一個檔案中,寫state,getters,mutations,actions。想象一下,如果我們的項目特别大,比如淘寶那麼大,那麼我們vuex中要維護的内容會特别多的時候,例如“購物車”需要用到vuex,“設定”需要用到vuex,“首頁”也需要用到vuex。那麼如果我們都寫到一個檔案中,就會出現代碼相當的“臃腫”。這一個store檔案最後好幾萬行代碼,還怎麼維護?

是以,我們vue官網就給出了辦法,使用vuex子產品化開發。

今天我們簡單學習使用,學會後,你要查閱官網,深入學習,才能提高這個技術。

子產品化有很多寫法,今天按照我的習慣,簡單的寫一下,我們和以前一樣,需要下載下傳vuex,會得到一個store檔案夾,内部我們有一個index根檔案。并且,我們需要自己建立一個module檔案夾,裡邊放入我們想要區分的js子產品檔案,你想分成多少個子產品,就分成多少個,我目前寫了兩個子產品,一個是購物車car.js,一個是我的my.js,type.js先不用管。如圖:

Vuex進階篇——Module子產品化學習(前端必會)
首先我們需要先将module中的所有檔案引入到

index.js

根檔案中,(以前我們是導出mutations等方法,現在這個檔案中,我隻引入了子產品,是以隻需要導出子產品),如圖:
Vuex進階篇——Module子產品化學習(前端必會)
然後我們就可以在每個子產品當中,寫入獨立的state,mutations等等。。。這樣我們在使用的時候,購物車就用car.js;我的就用my.js。用購物車car.js舉例(其他檔案同理),如圖:
Vuex進階篇——Module子產品化學習(前端必會)
這裡就可以像以前一樣寫我們的vuex方法了。細心的同學會注意到,我們導出時,會多出一個

namespaced: true

,一般我們在子產品使用時,都會加入這個屬性。

命名空間:namespaced: true:

當子產品被注冊後,它的所有 getter、action 及 mutation 都會自動根據子產品注冊的路徑調整命名,也就是說,我們在調用這些方法時,需要加上這個檔案的路徑(比如我要通路這個檔案中的state裡邊的某個屬性:

this.$store.state.car

。後邊這個car就是多了個car.js子產品名,因為如果不加子產品名,那我們會通路所有子產品中的屬性,那就亂了),是以我們要加上命名空間,相當于獨立的區塊去使用,子產品和子產品之間互不幹擾。

和平時一樣,我們跟個案例:

點選增加數值:

-----------------car.js中

// car.js

const state = {
  number: 100
}
const getters = {

}
const mutations = {
  add () {
    state.number++
  }
}

export default {
  namespaced: true,
  state,
  getters,
  mutations
}           

我們重點說一下vue中怎麼擷取子產品中的内容。我們可以和平常一樣,直接用

this.$store.state.car.number

來擷取到state中的number内容。我們今天說說在項目中最常使用的:輔助函數

mapState

mapGetters

mapActions

mapMutations

不一一舉例,簡單說兩個

mapState

mapActions

,深入了解可去

看官網

我們在使用時,需要先引入:

import { mapState,mapActions } from 'vuex'           

這兩個函數,前者寫在計算屬性computed中,後寫是方法,寫在 methods中;

在寫入時,需要用到展開符

...

,它可以将内容一 一的展開

舉例:var a = [1,2,3] var b = [4,5,6] var c = [...a,...b] // 列印c為:[1,2,3,4,5,6]

那我們擷取一下state中的number:

computed: {
    ...mapState({
      a: state => state.car.number
    })
  },

 methods: {
    ...mapMutations(['car/add']),
    add () {
      this['car/add']() // 注意,這裡this後沒有點
    }
  }           

展開mapState,定義一個a,然後傳回state中的car子產品下的number常量。

展開mapMutations,傳回是個數組,數組中是個字元串,傳回car子產品下的add方法,定義一個add,直接觸發就可以。有人會問,觸發mutations中的方法不是應該用commit嗎,答案是我們用了mapMutations,它會将這個路徑直接映射成commit方法,是以我們直接用就行,這也是與原來的差別。,

我們定義的這個a,就是想要的數值,可以在标簽中展示出來,add也直接使用:

<template>
  <div class="home">

    <div>{{a}}</div>
    <div @click="add">點選增加</div>

  </div>
</template>           

這樣寫出來,是好用的,但是看起來會有問題。想一下,car是個子產品,我們現在隻是舉例而已,但是如果,我們在開發中,這個子產品下命名空間比較深入,還有其他子產品,一層一層比較多,就會變成這個樣子:

computed: {
    ...mapState({

      a: state => state.car.xx.xx.xx.number
      // 如果下邊還有很多,就要寫很多重複的 car.xx.xx.xx,如:
      b: state => state.car.xx.xx.xx.name
      c: state => state.car.xx.xx.xx.key
    })
  },

 methods: {
    ...mapMutations(['car/xx/xx/xx/add']),
    add () {
      this['car/xx/xx/xx/add']()
    }
  }           

這個層層的嵌套,那就要寫很多重複的car/xx/xx/xx/,是以我們可以,将這個子產品當作字元串提取出來,換個寫法,按照我們的舉例:

computed: {
    // 第一個參數,我們放子產品,将它提取出來,統一寫在這裡。這樣下邊就不用重複的去寫了。
    ...mapState('car', {
      a: state => state.number
    })
  },
  methods: {
    ...mapMutations('car', ['add'])
  }           

如上所示,我們可以将他作為參數,放到前面,這樣所有綁定都會自動将該子產品作為上下文,寫出來也簡單不少。當然我們還可以再簡化一些。我們可以通過使用

createNamespacedHelpers

建立基于某個命名空間輔助函數。它傳回一個對象,對象裡有新的綁定在給定命名空間值上的元件綁定輔助函數。

就是我們可以從vuex中引入

createNamespacedHelpers

,然後将剛才的字元串作為參數,傳進來,如下:

<template>
  <div class="home">

    <div>{{a}}</div>
    <div @click="add">點選增加</div>

  </div>
</template>
// 這裡引入createNamespacedHelpers 
import { createNamespacedHelpers } from 'vuex'
// 定義mapState, mapMutations ,并将car 傳入 createNamespacedHelpers
const { mapState, mapMutations } = createNamespacedHelpers('car')
// import { mapState, mapMutations } from 'vuex'

export default {

  computed: {
    ...mapState({
      a: state => state.number
    })
  },

  methods: {
    // 這裡可以直接使用add
    ...mapMutations(['add'])
  }
}
           

這就是vuex子產品化,寫法都很多,看我們自己的習慣,當然了,我們在子產品中,還可以使用常量替代 Mutation 事件類型。在多人開發時,我們知道 mutations 中放入了方法,如果有很多方法,多人協作時找起來會比較麻煩,那我們可以建立一個放入常量的檔案(前文中我們建立的 type.js 檔案),在裡邊我們可以定義常量,但注意的是,我們開發中習慣常量要大寫,單詞之間用下劃線分開。并且,在子產品中引入這個文:

一、首先,我們建立一個js檔案 ,我們前文圖檔中的 type.js,在裡邊建立一個常量,開發時前後要一緻,并加以标注:

// 前後都要大寫,一般前後名稱一緻,但是為了我們能夠了解,本次我們寫兩個不一緻的。

// 開發中,我們應該這樣寫:export const ADD_NUMBER = 'ADD_NUMBER'

// 本次我們定義前後不一樣的

export const ADD_NUMBER = 'AAA' // 點選增加數字
           

二、在car子產品中引入 type.js 并使用引入進來的常量:

import { ADD_NUMBER } from './type' // 按需引入常量

const state = {
  number: 100
}
const getters = {

}
const mutations = {

  // 使用常量命名,注意,這裡 [ADD_NUMBER] 映射出來的名稱,其實是 AAA
  // 我們寫成固定的數字,也可以設定參數,靈活傳參
  // 第一個參數是state,第二個參數是傳入參數payload
  
  [ADD_NUMBER](state, payload) {
    state.number += payload
  }
}

const actions = {

}

export default {
  namespaced: true,
  state,
  getters,
  mutations,
  actions
}
           

三、vue頁面,由于剛才我們用了payload參數,是以我們也需要傳入參數,然後我們可以思考下,我們觸發的名稱應該寫哪一個?

methods: {
  
    // 思考一下問号的地方,應該寫 ADD_NUMBER 還是 AAA ?
    ...mapMutations(['???'])
  }           

這個問題也就是我剛才故意在常量中,前後不一樣的原因,由于我們前後都寫一樣,有些小白會不知道,這裡定義的到底是前邊的名稱, 還是後邊字元串的名稱。答案是 AAA,也是ES6中

對象的擴充寫法

最後的寫法是這樣的:

<template>
  <div class="home">
    <div>{{a}}</div>
    <!-- mutations 中的payload 參數,可以在這裡直接傳遞 -->
    <div @click="aaa(100)">點選增加</div>
  </div>
</template>

<script>
import { createNamespacedHelpers } from 'vuex'
const { mapState, mapMutations } = createNamespacedHelpers('car')
// import { mapState, mapMutations } from 'vuex'
export default {
  computed: {
    ...mapState({
      a: state => state.number
    })
  },
  methods: {
    // 我們除了可以寫成數組,還可以用對象的寫法
    ...mapMutations({
      aaa: 'AAA'
    })

    // 你也可以按照原始寫法寫,當然要去掉div标簽中的參數,參數改成在下邊傳遞。
    //aaa () {
    //  this.$store.commit('car/AAA', 100)
    //}

  }
}
</script>
           

這就是module子產品化的開發寫法,希望看完,你們會有所收獲。有錯誤的地方請指出,我們及時更正。

繼續閱讀