使用vuex的store的過程當中,發現了一些不是很優雅的地方:javascript
針對這3個問題,制定了3條重構方案。vue
按照聚類分層思想,當業務複雜後,須要經過必定的聚類特徵對扁平化的結構進行分層。java
這裏按照數據的用途分了page、components、domain、other這四類,page存儲頁面組件的數據,components存儲基礎組件的數據,domain存儲實體的數據,other存儲其餘全局數據。vuex
以前的modulestypescript
以後的modules bash
store劃分module是由於不一樣的數據有不一樣的歸屬。dom
若是想要每一個module都能響應全局action的話,不須要加namespace,可是咱們並無沒有一個action對應多個module的action handler的狀況。反而由於沒有加namespace,致使組件裏的多個module的getter、action、mutation都扁平的堆在一塊兒,結構混亂、不清晰。模塊化
...mapMutations([
changeisIceTree: 'changeisIceTree',
changeIceTreeStatus: 'changeIceTreeStatus',
showToast: 'showToast',
changeremainingfronzeTime: 'changeremainingfronzeTime',
decreaseremainingfronzeTime: 'decreaseremainingfronzeTime',
changeiceTreeFadeout: 'changeiceTreeFadeout',
changeiceTreeFadeIn: 'changeiceTreeFadeIn',
changefrozenTimes: 'changefrozenTimes',
changetreecurTime: 'changetreecurTime',
changequickTreeMedal:'changequickTreeMedal',
changequickHonorMedal:"changequickHonorMedal",
upDatePopUpOptionStatus: 'upDatePopUpOptionStatus'
}),
複製代碼
一堆的mutation讓人迷惑,結構很不清晰,哪一個mutation是哪一個module必須去store中找。post
加上namespace以後,每一個mutaion屬於一個namespace,每一個namespace表明一個module,在組件裏就能夠輕鬆的根據namespace區分出哪一個module來。ui
...mapGetters('aaaaa',[
'mutation111111',
'mutation22222',
'mutation33333'
]);
...mapMutations('aaaaa',[
'mutation111111',
'mutation22222',
'mutation33333'
]);
...mapMutations('bbbbb',[
'mutation4444444',
'mutation555555',
'mutation666666',
]);
複製代碼
這樣重構以後,組件用到再多module的action、getter、mutation也不會混亂了。
mutation type和action type的名字可能會寫錯,由於沒有使用typescript,沒有類型約束,若是寫錯了,編譯時沒法檢查出來,只能在運行時檢查。解決這個問題或者使用ts,或者所有的mutation type和action type從枚舉常量中取。
store中的數據是模塊化的,mutation type 和action type的枚舉常量天然也是,可是vuex的module並不會處理這二者,想把這些模塊化的motation type和action type掛到store實例上,能夠經過vuex插件來解決。
我發現社區並無我須要的vuex插件,因而我本身封裝了一個
/** * 生成文件對應的模塊 * * @param {*} dirPath 文件夾路徑 */
const generateModules = (files) => {
const modules = {}
files.keys().forEach(key => {
modules[key.replace(/(\.\/|\.js)/g, '')] = files(key).default
})
return modules;
}
/** * 全部file * */
const allFiles = {
page: require.context('../modules/page', false, /\.js$/),
components: require.context('../modules/components', false, /\.js$/),
domain: require.context('../modules/domain', false, /\.js$/),
other: require.context('../modules/other', false, /\.js$/)
}
/** * 全部module * */
const allModules = {
page: generateModules(allFiles.page),
components: generateModules(allFiles.components),
domain: generateModules(allFiles.domain),
other: generateModules(allFiles.other)
}
/** * 根據types獲取modules下的多個模塊的結構化數據 * @param {*} types module type * @param {*} fieldName 字段名 */
const getStructuredData = (types, fieldNames) => {
const structuredData = {};
types.forEach(type => {
const modules = allModules[type];
const structuredModuleData = Object.keys(modules).map(moduleName => {
const fields = fieldNames.map(fieldName => modules[moduleName][fieldName])
return {
[moduleName]: Object.assign(...fields)
}
});
structuredData[type]= structuredModuleData && structuredModuleData.length ? Object.assign(...structuredModuleData): {};
})
return structuredData
}
const enumTypePlugin = store => {
const mutationTypeEnum = getStructuredData(['page','components','domain','other'], ['mutationTypes']);
const actionTypeEnum = getStructuredData(['page','components','domain','other'], ['actionTypes']);
store.mutationTypes = mutationTypeEnum;
store.actionTypes = actionTypeEnum;
}
module.exports = enumTypePlugin;
複製代碼
添加到vuex的plugins中
import typeEnumPlugin from './type-enum-plugin';
new Vuex.Store(
modules,
plugins: [typeEnumPlugin]
)
複製代碼
module定義時導出mutation types和action types
module.exports = {
state,
getters,
mutations,
actions,
mutationTypes,
actionTypes
}
複製代碼
在組件裏面就可使用action type和mutation type來mapAction,mapMutation
...mapActions({
mutation1: this.$store.mutationTypes.page.aaa.mutation1,
mutation2: this.$store.mutationTypes.page.aaa.mutation2,
mutation3: this.$store.mutationTypes.page.aaa.mutation3
})
...mapActions({
action1: this.$store.actionTypes.page.aaa.action1,
action2: this.$store.actionTypes.page.aaa.action2,
action3: this.$store.actionTypes.page.aaa.action3
})
複製代碼
或者像下面這樣所有導入
...mapMutations(this.$store.mutationTypes.page.aaa)
...mapActions(this.$store.actionTypes.page.aaa)
複製代碼
這樣就避免了手寫字符串可能出錯的問題。
針對vuex store的module過多,組件裏沒法區分出getter、action、mutation屬於哪個module,mutation type和action type無約束這3個問題,針對性的提出了3條解決方案:
module聚類分層,分紅page、components、domain、other四個文件夾存放module;
添加namespace,組件中使用mapGetters、mapActions、mapMuatations時加上namespace區分;
module定義時導出mutation types和action types,並經過vuex的插件掛到store上,組件中使用mapMutations和mapActions再也不經過字符串取對應值。