我之前釋出了一篇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先不用管。如圖:

index.js
根檔案中,(以前我們是導出mutations等方法,現在這個檔案中,我隻引入了子產品,是以隻需要導出子產品),如圖: 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子產品化的開發寫法,希望看完,你們會有所收獲。有錯誤的地方請指出,我們及時更正。