状态管理之Vuex (三) store利用module拆分

Module介绍

当所有状态都集中到一个比较大的对象时,应用就会变的非常复杂,store也会变得十分臃肿。
比方说:
一家公司只有老板一个人来管理一样。如果小公司倒还好,公司要是稍微大一点,那就麻烦了。这个时候,老板就会成立各大部门,并给各大部门安排一个主管,把管理的任务分派下去,然后有什么事情需要处理的话,只需要跟这几个主管沟通,由主管再把任务分配下去就行了,这就大大提高了工作效率,也减轻了老板的负担。
那么同样的道理,Module 其实就承担了部门管理员的角色,而 store 就是老板。

为了解决这些问题,Vuex可以将store分割成模块。每个模块拥有自己的statemutationactiongetter

创建Module state进行操作

我需要将用户的state放到用户里去,订单的放到订单里面去, 于是

module-code

这个时候,在组件里面已经可以使用到module里面的数据了, 例如我的user.js module

  • user.js
user-module

可以看到这里面声明了一些store的基本属性,stateactions

  • src/components/VuexDemo/VuexDemo.vue
<template>
    <div class="VuexDemo">
        <div>{{nameOfUserModule}}</div>
        <div>real name {{realName}}</div>
        <button @click="changeUserModuleName">修改user module里面的name</button>
    </div>
</template>
<script>
    // import store from '../../store/index'; 因为在main.js 里面引入了store 所以这里就不需要了 直接this.$store就可以了
    import { mapState, mapActions, mapGetters } from 'vuex';

    export default {
        created() {
            this.getUserList();
        },

        computed: {
            ...mapState(['userList']),
            ...mapGetters(['userCount', 'realName']),   // realName是user module里面的getter

            nameOfUserModule: function() {
                return this.$store.state.user.name      // 这里就直接将user的state获取出来了
            },
        },

        methods: {
            ...mapActions(['getUserList']),
            changeUserModuleName() {
                this.$store.dispatch('changeName', '命名空间'); // 这里调用的是user里面的 action
            }
        }
    };
</script>

由以上的例子可以知道: vuex里面默认mutationactiongetter等都全局的,可以随意调用,但是state还是私有的

可以看到,这样虽然是将代码拆分了,但是并没有达到真正的拆分,action等还都是全局的。还没有结束,Vuex还给我们提供了namespace(命名空间),这样的话就不用管命名的问题了

Module命名空间

要在module里面使用命名空间,先要在module里面设置属性namespaced: true

user-module-namespace

这样调用actiongetter等就不能直接调用了,这个时候的actiongetter已经不是全局,你在调用action的时候还需要带命名空间

user-module-namespace-code

上面是自己去控制前面的命名空间,还有一种简写的办法,可以不用在mapAction等函数带命名空间,例如:

namespace简写
  • user.js

参数接受 这是映射是这么写 如果不是mapAction的话直接payload就是值

changeName({commit, rootState}, payload) {
    commit('setName', payload.payload);
},
  • 效果
效果

还有个需要注意的地方: 我们知道module里面的state是私有的,那有些场景需要依赖于全局的state,那怎么获取? 从user module的截图里面可以看到,在action、getter参数中有rootState 这个就是根状态 大家可以去玩一下,这里就不做介绍了

模块动态注册

这个基本在项目中很少使用,所以我不做讲解,有兴趣的可以了解一下。我直接把官网的例子搬过来,方便各位看官观看

store 创建之后,你可以使用 store.registerModule 方法注册模块:

// 注册模块 `myModule`
store.registerModule('myModule', {
  // ...
})
// 注册嵌套模块 `nested/myModule`
store.registerModule(['nested', 'myModule'], {
  // ...
})

之后就可以通过 store.state.myModulestore.state.nested.myModule 访问模块的状态。

模块动态注册功能使得其他 Vue 插件可以通过在 store 中附加新模块的方式来使用 Vuex 管理状态。例如,vuex-router-sync 插件就是通过动态注册模块将 vue-routervuex 结合在一起,实现应用的路由状态管理。

你也可以使用 store.unregisterModule(moduleName) 来动态卸载模块。注意,你不能使用此方法卸载静态模块(即创建 store 时声明的模块)。

模块重用

就一点,重用会导致模块中的数据 state 被污染,所以和 Vue 中的 data 一样,也使用一个函数来申明 state 即可。(引用数据类型,基础知识,大家可以再回顾一下 这不做讲解)

const MyModule = {
  state () {
    return {
      foo: 'bar'
    }
  },
  //...
}

Thanks

至此,Vuex核心概念基本完了,如果再出Vuex文章,我会写一些再项目中的坑,避免大家浪费不必要的时间,好的 结束。

本文为作者原创,手码不易,允许转载,转载后请以链接形式说明文章出处。

您的支持是对我最大的鼓励!

发表于: 作者:憧憬。
关注互联网以及分享全栈工作经验的原创个人博客和技术博客,热爱编程,极客精神
Github 新浪微博 SegmentFault 掘金专栏