深入理解Vuex 模塊化(module)
一、為什么需要模塊化
前面我們講到的例子都在一個(gè)狀態(tài)樹里進(jìn)行,當(dāng)一個(gè)項(xiàng)目比較大時(shí),所有的狀態(tài)都集中在一起會(huì)得到一個(gè)比較大的對(duì)象,進(jìn)而顯得臃腫,難以維護(hù)。為了解決這個(gè)問題,Vuex允許我們將store分割成模塊(module),每個(gè)module有自己的state,mutation,action,getter,甚至還可以往下嵌套模塊,下面我們看一個(gè)典型的模塊化例子
const moduleA = { state: {....}, mutations: {....}, actions: {....}, getters: {....} } const moduleB = { state: {....}, mutations: {....}, actions: {....}, getters: {....} } const store = new Vuex.Store({ modules: { a: moduleA, b: moduleB } }) store.state.a // moduleA的狀態(tài) store.state.b // moduleB的狀態(tài)
二、模塊的局部狀態(tài)
模塊內(nèi)部的mutation和getter,接收的第一參數(shù)(state)是模塊的局部狀態(tài)對(duì)象,rootState
const moduleA = { state: { count: 0}, mutations: { increment (state) { // state是模塊的局部狀態(tài),也就是上面的state state.count++ } }, getters: { doubleCount (state, getters, rootState) { // 參數(shù) state為當(dāng)前局部狀態(tài),rootState為根節(jié)點(diǎn)狀態(tài) return state.count * 2 } }, actions: { incremtnIfOddRootSum ( { state, commit, rootState } ) { // 參數(shù) state為當(dāng)前局部狀態(tài),rootState為根節(jié)點(diǎn)狀態(tài) if ((state.cont + rootState.count) % 2 === 1) { commit('increment') } } } }
三、命名空間(這里一定要看,不然有些時(shí)候會(huì)被坑)
上面所有的例子中,模塊內(nèi)部的action、mutation、getter是注冊(cè)在全局命名空間的,如果你在moduleA和moduleB里分別聲明了命名相同的action或者mutation或者getter(叫some),當(dāng)你使用store.commit('some'),A和B模塊會(huì)同時(shí)響應(yīng)。所以,如果你希望你的模塊更加自包含和提高可重用性,你可以添加namespaced: true的方式,使其成為命名空間模塊。當(dāng)模塊被注冊(cè)后,它的所有g(shù)etter,action,mutation都會(huì)自動(dòng)根據(jù)模塊注冊(cè)的路徑調(diào)用整個(gè)命名,例如:
const store = new Vuex.Store({ modules: { account: { namespaced: true, state: {...}, // 模塊內(nèi)的狀態(tài)已經(jīng)是嵌套的,namespaced不會(huì)有影響 getters: { // 每一條注釋為調(diào)用方法 isAdmin () { ... } // getters['account/isAdmin'] }, actions: { login () {...} // dispatch('account/login') }, mutations: { login () {...} // commit('account/login') }, modules: { // 繼承父模塊的命名空間 myPage : { state: {...}, getters: { profile () {...} // getters['account/profile'] } }, posts: { // 進(jìn)一步嵌套命名空間 namespaced: true, getters: { popular () {...} // getters['account/posts/popular'] } } } } } })
啟用了命名空間的getter和action會(huì)收到局部化的getter,dispatch和commit。你在使用模塊內(nèi)容時(shí)不需要再同一模塊內(nèi)添加空間名前綴,更改namespaced屬性后不需要修改模塊內(nèi)的代碼。
四、在命名空間模塊內(nèi)訪問全局內(nèi)容(Global Assets)
如果你希望使用全局state和getter,roorState和rootGetter會(huì)作為第三和第四參數(shù)傳入getter,也會(huì)通過context對(duì)象的屬性傳入action若需要在全局命名空間內(nèi)分發(fā)action或者提交mutation,將{ root: true }作為第三參數(shù)傳給dispatch或commit即可。
modules: { foo: { namespaced: true, getters: { // 在這個(gè)被命名的模塊里,getters被局部化了 // 你可以使用getter的第四個(gè)參數(shù)來(lái)調(diào)用 'rootGetters' someGetter (state, getters, rootSate, rootGetters) { getters.someOtherGetter // -> 局部的getter, ‘foo/someOtherGetter' rootGetters.someOtherGetter // -> 全局getter, 'someOtherGetter' } }, actions: { // 在這個(gè)模塊里,dispatch和commit也被局部化了 // 他們可以接受root屬性以訪問跟dispatch和commit smoeActino ({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 } } } }
五、帶命名空間的綁定函數(shù)
前面說(shuō)過,帶了命名空間后,調(diào)用時(shí)必須要寫上命名空間,但是這樣就比較繁瑣,尤其涉及到多層嵌套時(shí)(當(dāng)然開發(fā)中別嵌套太多,會(huì)暈。。)
下面我們看下一般寫法
computed: { ...mapState({ a: state => state.some.nested.module.a, b: state => state.some.nested.module.b }), methods: { ...mapActions([ 'some/nested/module/foo', 'some/nested/module/bar' ]) } }
對(duì)于這種情況,你可以將模塊的命名空間作為第一個(gè)參數(shù)傳遞給上述函數(shù),這樣所有的綁定會(huì)自動(dòng)將該模塊作為上下文。簡(jiǎn)化寫就是
computed: { ...mapStates('some/nested/module', { a: state => state.a, b: state => state.b }) }, methods: { ...mapActions('some/nested/module',[ 'foo', 'bar' ]) }
六、模塊重用
有時(shí)我們可能創(chuàng)建一個(gè)模塊的多個(gè)實(shí)例,例如:
- 創(chuàng)建多個(gè)store,他們共用一個(gè)模塊
- 在一個(gè)store中多次注冊(cè)同一個(gè)模塊
如果我們使用一個(gè)純對(duì)象來(lái)聲明模塊的狀態(tài),那么這個(gè)狀態(tài)對(duì)象會(huì)通過引用被共享,導(dǎo)致數(shù)據(jù)互相污染。
實(shí)際上Vue組件內(nèi)data是同樣的問題,因此解決辦法也是一樣的,使用一個(gè)函數(shù)來(lái)聲明模塊狀態(tài)(2.3.0+支持)
const MyModule = { state () { return { foo: 'far' } } }
七、總結(jié)
到這里模塊化(module)的內(nèi)容就已經(jīng)講完了,本次主要講解了module出現(xiàn)的原因,使用方法,全局和局部namespaced模塊命名空間,局部訪問全局內(nèi)容,map函數(shù)帶有命名空間的綁定函數(shù)和模塊的重用。
引用
https://vuex.vuejs.org Vuex官方文檔
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Element input樹型下拉框的實(shí)現(xiàn)代碼
這篇文章主要介紹了Element input樹型下拉框的實(shí)現(xiàn)代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧2018-12-12Vue項(xiàng)目中實(shí)現(xiàn)AES加密解密的全過程
AES算法是一種對(duì)稱加密算法,用于加密和解密數(shù)據(jù),下面這篇文章主要給大家介紹了關(guān)于Vue項(xiàng)目中實(shí)現(xiàn)AES加密解密的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-08-08Vue項(xiàng)目報(bào)錯(cuò):Uncaught?SyntaxError:?Unexpected?token?'<&a
最近在做vue項(xiàng)目時(shí),需要引入一個(gè)第三方的js文件,在index.html中通過以下方式引入JS文件編譯后就報(bào)了這個(gè)問題,這篇文章主要給大家介紹了關(guān)于Vue項(xiàng)目報(bào)錯(cuò):Uncaught?SyntaxError:?Unexpected?token?'<'的解決方法,需要的朋友可以參考下2022-08-08Vue實(shí)現(xiàn)圖片預(yù)覽功能的詳細(xì)指南
在現(xiàn)代 web 應(yīng)用程序中,圖片預(yù)覽功能提升了用戶體驗(yàn),使用戶可以在上傳圖片之前查看圖片內(nèi)容,本文將詳細(xì)介紹如何在 Vue.js 應(yīng)用中實(shí)現(xiàn)圖片預(yù)覽功能,包括基本實(shí)現(xiàn)、進(jìn)階功能、與 Element UI 的集成、常見優(yōu)化技巧以及與其他庫(kù)的結(jié)合使用,需要的朋友可以參考下2024-09-09vue3.0 proxy設(shè)置代理不成功的問題及解決方案
這篇文章主要介紹了vue3.0 proxy設(shè)置代理不成功的問題及解決方案,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2023-12-12Vue.js基礎(chǔ)學(xué)習(xí)之class與樣式綁定
這篇文章主要為大家介紹了Vue.js的Class與樣式綁定,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03Vue項(xiàng)目history模式下微信分享爬坑總結(jié)
這篇文章主要介紹了Vue項(xiàng)目history模式下微信分享爬坑總結(jié),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧2019-03-03Vue實(shí)現(xiàn)簡(jiǎn)單網(wǎng)頁(yè)計(jì)算器
這篇文章主要為大家詳細(xì)介紹了Vue實(shí)現(xiàn)簡(jiǎn)單網(wǎng)頁(yè)計(jì)算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04