?? 上面我們介紹如何拆分項(xiàng)目怕犁,采用的是按屬性的方式去拆分,將getters/actions/mutations等屬性拆分到不同的文件中慷荔,以及介紹了常量代替XXX事件類型耗跛;接下來,我們介紹一下按另外的一個維度去拆分我們的store节芥,‘按功能’在刺,按功能拆分的話,就是我們的標(biāo)題Module(模塊)头镊。
-
?? 我們先來看下官方文檔是怎么介紹Module的:
image.png- 看了圖中的描述蚣驼,你或許已經(jīng)區(qū)分了這里使用的按功能拆分Module和我們上次介紹的按屬性拆分的異同了;就像圖中的場景一樣相艇,我們有一個總store颖杏,在這里面根據(jù)不同的功能,我們加了兩個不同的store坛芽,每個store里面維護(hù)自己的state留储,以及自己的actions/mutations/getters翼抠。
?? 不說廢話,我們用代碼實(shí)現(xiàn)一下
-
- 我們在之前的store上获讳,增加一個子模塊机久,名字叫mutou,主要代碼如下:
- 目錄結(jié)構(gòu)如下
store |___index.js |___state.js |___mutations.js |___getters.js |___actions.js |___mutation-types.js |___getter-types.js |___action-types.js |___mutou <---新增mutou文件夾 |___index.js <---新增index.js文件赔嚎,新增的模塊我們暫時先不按屬性進(jìn)行拆分了柑船,其實(shí)是完全可以再按屬性進(jìn)行拆分吟税,屬性拆分和功能拆分是完全可以合在一起的
- index.js文件如下:
import mutou2 from './mutou2/index' const mutou = { state: { name:'i am mutou', }, mutations: { changeName(state,payload){ console.log(payload.name); } }, getters:{}, } export default mutou
- store/index.js文件修改如下蚌父,引入我們新創(chuàng)建的mutou模塊:
import Vue from 'vue' import Vuex from 'vuex' import state from './state' import getters from './getters' import mutations from './mutations' import actions from './actions' import mutou from './mutou/index' <--- 引入mutou模塊 Vue.use(Vuex) const store = new Vuex.Store({ modules:{mutou}, <--- 將木頭模塊裝載上 state, getters, mutations, actions, }) export default store
- 訪問state -- 我們在App.vue測試訪問mutou模塊中的state中的name撮慨,結(jié)果如下:
console.log(this.$store.state.mutou.name);
image.png - 訪問mutation -- 我們在App.vue測試提交mutou模塊中的mutation中的changeName,結(jié)果如下:
this.$store.commit('changeName',{where:'我是從App.vue進(jìn)來的'})
image.png
-
?? 1. 模塊的局部狀態(tài)
我們通過下面的代碼可以了解到在不同的屬性里是怎么訪問模塊內(nèi)的狀態(tài)或者根狀態(tài):mutations: { changeName(state,payload){ // state 局部狀態(tài) console.log(state) console.log(payload.where); } }, getters:{ testGetters (state, getters, rootState) { // state 局部狀態(tài) console.log(state) // 局部 getters, console.log(getters) // rootState 根節(jié)點(diǎn)狀態(tài) console.log(rootState) } }, actions: { increment ({ state, commit, rootState }) { // state 局部狀態(tài) console.log(state) // rootState 根節(jié)點(diǎn)狀態(tài) console.log(rootState) } }
-
?? 2. 命名空間
默認(rèn)情況下损晤,模塊內(nèi)部的 action软棺、mutation 和 getter 是注冊在全局命名空間的——這樣使得多個模塊能夠?qū)ν?mutation 或 action 作出響應(yīng)。如果希望你的模塊具有更高的**封裝度**和**復(fù)用性**尤勋,你可以通過添加 ```namespaced: true``` 的方式使其成為帶命名空間的模塊喘落。當(dāng)模塊被注冊后,它的所有 getter最冰、action 及 mutation 都會自動根據(jù)模塊注冊的路徑調(diào)整命名瘦棋。例如:
const mutou = { namespaced:true, <--- 增加namespaced屬性,值為true state: { name:'i am mutou', }, ......
此時暖哨,再次commit我們剛才的changeName的mutation赌朋,瀏覽器會報(bào)找不到mutation的錯誤:
this.$store.commit('changeName',{where:'我是從App.vue進(jìn)來的'})
image.png
此時,我們修改為下面的模式篇裁,加上命名空間的路徑即可恢復(fù)正常沛慢。
this.$store.commit('mutou/changeName',{where:'我是從App.vue進(jìn)來的'})
其余的getters、actions同mutation一樣达布,具體使用可以參考vuex的官方文檔官方文檔的Module在這里团甲。
-
?? 3. 在帶命名空間的模塊內(nèi)訪問全局內(nèi)容
如果你希望使用全局 state 和 getter,rootState 和 rootGetters 會作為第三和第四參數(shù)傳入 getter黍聂,也會通過 context 對象的屬性傳入 action躺苦。
若需要在全局命名空間內(nèi)分發(fā) action 或提交 mutation,將 { root: true } 作為第三參數(shù)傳給 dispatch 或 commit 即可分冈。
-
比較簡單圾另,直接貼官方示例代碼:
modules: { foo: { namespaced: true, getters: { // 在這個模塊的 getter 中霸株,`getters` 被局部化了 // 你可以使用 getter 的第四個參數(shù)來調(diào)用 `rootGetters` someGetter (state, getters, rootState, rootGetters) { getters.someOtherGetter // -> 'foo/someOtherGetter' rootGetters.someOtherGetter // -> 'someOtherGetter' }, someOtherGetter: state => { ... } }, actions: { // 在這個模塊中雕沉, dispatch 和 commit 也被局部化了 // 他們可以接受 `root` 屬性以訪問根 dispatch 或 commit someAction ({ dispatch, commit, getters, rootGetters }) { getters.someGetter // -> 'foo/someGetter' rootGetters.someGetter // -> 'someGetter' dispatch('someOtherAction') // -> 'foo/someOtherAction' dispatch('someOtherAction', null, { root: true }) // -> 'someOtherAction' commit('someMutation') // -> 'foo/someMutation' commit('someMutation', null, { root: true }) // -> 'someMutation' }, someOtherAction (ctx, payload) { ... } } } }
-
?? 4. 在帶命名空間的模塊注冊全局 action
- 若需要在帶命名空間的模塊注冊全局 action,你可添加 root: true去件,并將這個 action 的定義放在函數(shù) handler 中坡椒。
- 我們來實(shí)踐一下扰路,在mutou/index.js的action里面加上:
globalAction: { root: true, handler (namespacedContext, payload) { console.log('i am in global action...'); } // -> 'someAction' }
- 在App.vue里運(yùn)行,注意倔叼,我沒有加mutou/XXX汗唱,沒有加命名空間的路徑,如果能正常訪問丈攒,即代表該action的確注冊到了全局上哩罪。
this.$store.dispatch('globalAction')
image.png
-
?? 5.帶命名空間的綁定函數(shù)
- 當(dāng)使用 mapState, mapGetters, mapActions 和 mapMutations 這些函數(shù)來綁定帶命名空間的模塊時,寫起來可能比較繁瑣:
computed: { ...mapState({ a: state => state.some.nested.module.a, b: state => state.some.nested.module.b }) }, methods: { ...mapActions([ 'some/nested/module/foo', // -> this['some/nested/module/foo']() 'some/nested/module/bar' // -> this['some/nested/module/bar']() ]) }
- 對于這種情況巡验,你可以將模塊的空間名稱字符串作為第一個參數(shù)傳遞給上述函數(shù)际插,這樣所有綁定都會自動將該模塊作為上下文。于是上面的例子可以簡化為:
computed: { ...mapState('some/nested/module', { a: state => state.a, b: state => state.b }) }, methods: { ...mapActions('some/nested/module', [ 'foo', // -> this.foo() 'bar' // -> this.bar() ]) }
- 而且显设,你可以通過使用 createNamespacedHelpers 創(chuàng)建基于某個命名空間輔助函數(shù)框弛。它返回一個對象,對象里有新的綁定在給定命名空間值上的組件綁定輔助函數(shù):
import { createNamespacedHelpers } from 'vuex' const { mapState, mapActions } = createNamespacedHelpers('some/nested/module') export default { computed: { // 在 `some/nested/module` 中查找 ...mapState({ a: state => state.a, b: state => state.b }) }, methods: { // 在 `some/nested/module` 中查找 ...mapActions([ 'foo', 'bar' ]) } }
- 當(dāng)使用 mapState, mapGetters, mapActions 和 mapMutations 這些函數(shù)來綁定帶命名空間的模塊時,寫起來可能比較繁瑣:
?? 以上是對module的簡單介紹捕捂,其實(shí)這里就是一種思想瑟枫,分而治之嘛,將復(fù)雜的進(jìn)行拆分指攒,可以更有效的管理慷妙,上面介紹的一些方法就是在拆分后,應(yīng)該注意哪些點(diǎn)允悦,哪些點(diǎn)是因?yàn)椴鸱侄枰驮瓉淼牟徊鸱值倪壿嬜鰠^(qū)分的景殷,哪些是可以避免重復(fù)代碼的操作等等。
其實(shí)以上并不是module的全部澡屡,還有一些比如‘模塊動態(tài)注冊’猿挚、‘模塊重用’等方法這里就沒介紹,如果你在項(xiàng)目中使用到了驶鹉,再進(jìn)行查閱即可绩蜻,有時候不需要完全理解,知道有這個東西就行室埋,知道出了問題的時候該去哪查資料就夠啦办绝。??