层次和约束:项目中使用vuex的3条优化方案

栏目: JavaScript · 发布时间: 6年前

内容简介:使用vuex的store的过程中,发现了一些不是很优雅的地方:针对这3个问题,制定了3条重构方案。按照聚类分层思想,当业务复杂后,需要通过一定的聚类特征对扁平化的结构进行分层。

使用vuex的store的过程中,发现了一些不是很优雅的地方:

  1. store层module太多,找state、getter、mutation、action对应的module比较慢。
层次和约束:项目中使用vuex的3条优化方案
  1. 组件里面mapGetters、mapActions、mapMutations过多,分不清getter、action、mutation属于哪个module,比较混乱。
层次和约束:项目中使用vuex的3条优化方案
  1. 没有使用mutation type 和action type的枚举常量来约束action type和mutation type取值,字符串方式容易出错。(如上图)

解决方案

针对这3个问题,制定了3条重构方案。

1. module聚类分层

按照聚类分层思想,当业务复杂后,需要通过一定的聚类特征对扁平化的结构进行分层。

这里按照 数据的用途 分了page、components、domain、other这四类,page存储页面组件的数据,components存储基础组件的数据,domain存储实体的数据,other存储其他全局数据。

之前的modules

层次和约束:项目中使用vuex的3条优化方案

之后的modules

层次和约束:项目中使用vuex的3条优化方案

目前还没有存储实体数据的module,所以暂时为空

2.module添加namespace

store划分module是因为不同的数据有不同的归属。

如果想要每个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中找。

加上namespace之后,每个mutaion属于一个namespace,每个namespace代表一个module,在组件里就可以轻松的根据namespace区分出哪个module来。

...mapGetters('aaaaa',[
   'mutation111111',
   'mutation22222',
   'mutation33333'
]);
...mapMutations('aaaaa',[
   'mutation111111',
   'mutation22222',
   'mutation33333'
]);
...mapMutations('bbbbb',[
   'mutation4444444',
   'mutation555555',
   'mutation666666',
]);
复制代码

这样重构之后,组件用到再多module的action、getter、mutation也不会混乱了。

3.mutation type和action type使用枚举常量约束

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聚类分层,添加namespace,module定义时导出mutation type和action type,并通过vuex的插件挂到store上。


以上所述就是小编给大家介绍的《层次和约束:项目中使用vuex的3条优化方案》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Advanced Web Metrics with Google Analytics

Advanced Web Metrics with Google Analytics

Brian Clifton / Sybex / 2008 / USD 39.99

Are you getting the most out of your website? Google insider and web metrics expert Brian Clifton reveals the information you need to get a true picture of your site's impact and stay competitive usin......一起来看看 《Advanced Web Metrics with Google Analytics》 这本书的介绍吧!

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

MD5 加密
MD5 加密

MD5 加密工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具