對於vue這類mvvm框架來說,其核心就是組件與數據,因此做好相應的數據管理極為重要。這里分享下vuex數據模塊化管理的方法,有利於搭建便於維護、協作的vue項目。
vuex管理基本方法和使用
模塊化的概念已經在js、css中大量的用到,已不再陌生,其可增加代碼的復用、擴展性、維護性等,對於一個大型的系統來說,必不可少。這里也希望提供一種有效的模塊化數據管理方式,讓協作變的更為高效。
- 首先看看vuex的四個對象
state: {}, // 存儲數據的狀態
getters: {}, // 獲取vuex數據(state)的統一接口
mutations: {}, // 存vuex數據(state)的統一接口
actions: {}, // vuex內的異步操作接口
- 再看某種應用方式
項目有兩個模塊,一個home頁面,一個poetry頁面,對應不同的vuex數據模塊,其vuex的管理方式如下:
// home.js
export default new Vuex.Store({
state: {...},
mutations: {...}
})
// poetry.js
export default new Vuex.Store({
state: {...},
getters: {...}
})
// vuex調用
if (pathname.indexOf('/home') >= 0) {
store = require('/vuex/home').default
} else if (pathname.indexOf('/poetry') >= 0) {
store = require('/vuex/home').default
}
由於每個單頁對應會生成一個全新的vuex,這樣就會造成vuex數據的丟失(單頁跳轉、回退時),這就是沒有實現vuex的模塊化管理及數據共享共享。那么怎么樣進行模塊化管理呢?
簡單的vuex模塊化
簡單的vuex管理代碼如下:
// home.js
...
export default {
state,
getters,
actions,
mutations
}
// poetry.js
...
同home.js~~
// index.js
...
import common from './common'
import home from './home'
import poetry from './poetry'
Vue.use(Vuex)
export default new Vuex.Store({
state: {},
getters: {},
mutations: {},
actions: {},
modules: {
common,
home,
poetry
}
})
// 調用方法如下
import store from 'src/store/index'
如此,vuex模塊化后的結構如下:
圖一 vuex模塊化的結構
一個獨立項目,僅有一處進行new Vuex操作,防止vuex丟失。但上圖的方法,可以實現簡單項目的管理,在多人協作下仍然存在數據操作隱患。首先來看下重名狀態下,各個屬性的表現。
方法重名的表現及帶來的問題
重名的情況下,state會自動根據模塊確認命名空間(獨立的屬性調用)。再看getters、mutations、actions,其與state不同,會引發重名問題,具體表現如下:
-
getters
在重名的情況下,僅首先注冊的getters會生效,同時報錯,提示重名。
錯誤如下:
圖二 getters重名報錯圖
-
mutations/action
在重名情況下,多個重名方法都將被調用。(以mutations為例)
this.updateInitInfo('poetry string’) // home.js const mutations = { updateInitInfo(state, string) { state.initInfo = string console.log('home update', string) } } // poetry.js const mutations = { updateInitInfo(state, string) { state.pageName = string console.log('poetry update', string) } }
在poetry中調用,執行結果如下:
圖3 mutations的重命名執行結果
由圖3,可以得出結論,方法會按序執行,且無報錯和警告。
對於這類方法的重名調用,比較難察覺,多人協作時,較容易出現數據共享錯誤,所以需要用另外的方法來加強配置,使得強調 單一調用 的協作場景,也可以高效的展開。
vuex數據模塊化管理方案
vuex自帶模塊化方法,為namespaced:true。通過對模塊進行命名空間設置,就能分模塊進行管理。
-
目錄結構
圖4 vuex的目錄結構
其中address模塊的增加,是為了適應更為復雜的應用需求。相關設置代碼如下:
// address/index.js
import addr1 from './addr1'
import addr2 from './addr2'
import addrList from './addrList'
export default {
namespaced: true,
modules: {
addr1,
addr2,
addrList
}
}
// home.js
const state = {
initInfo: 'hello hity'
}
const getters = {
initInfo(state, getters) {
return state.initInfo
}
}
const actions = {
getInfo({commit, state}) {
commit('updateInitInfo', 'getInfo')
}
}
const mutations = {
updateInitInfo(state, string) {
state.initInfo = string
console.log('home update', string)
}
}
export default {
namespaced: true,
state,
getters,
actions,
mutations
}
// index.js
......
export default new Vuex.Store({
state: {},
getters: {},
mutations: {},
actions: {},
modules: {
common,
home,
poetry,
address
}
})
運行結果vuex視圖如下:
圖5 vuex運行后的結構圖
由上圖可見,通過命名空間設置的getters、mutaions、actions都可以生成自己獨有的方法名,從而實現模塊化。這樣的方法名,如何調用呢?調用方法有如下幾種[以貼出代碼的home模塊為例]:
// xxx.vue中調用
a、通過store直接調用:
state:this.$store.state.home.initInfo
getters: this.$store.getters['home/initInfo']
mutations: this.$store.commit('home/updateInitInfo', 'set home init info')
actions: this.$store.dispatch('home/getInfo')
b、配合vuex的createNamespacedHelpers方法使用
import { createNamespacedHelpers } from 'vuex'
const { mapActions, mapState, mapMutations, mapGetters } = createNamespacedHelpers('home')
computed: {
...mapState({
initInfoState: state => state.initInfo
}),
...mapGetters([
'initInfo'
])
},
methods: {
...mapMutations([
'updateInitInfo'
]),
...mapActions([
'getInfo'
])
}
c、使用原始的mapX方法
import { mapActions, mapState, mapMutations, mapGetters } from 'vuex'
computed: {
...mapState({
initInfoState: state => state.home.initInfo
}),
...mapGetters('home', [
'initInfo'
])
}
methods: {
...mapMutations('home', [
'updateInitInfo'
]),
...mapActions('home', [
'getInfo'
])
}
從vuex運行后的結構圖可以看出,state的模塊名成為其屬性名,從而實現模塊化;而getters、mutations、actions的模塊名,則成為方法名的前綴,通過'/'分隔,從而實現模塊化。從調用方法上可以看出,更容易看出兩者的區別。如果你的代碼是從非模塊化,到模塊化的改造,且都是使用的mapX方法進行方法管理,那么使用方案b的state方法,結合方案c的mapGetters、mapMutations、mapActions,將使得改造成本最小化。
tips:使用vuex的項目,建議使用mapX方法進行統一的管理,對vuex的調用較為直觀,也便於將來的擴展和改造。