vuex中modules的使用场景和注意事项

store 拆分红 modules 过程

以前的项目一直是store下面放各类js文件(index.js、state.js、getter.js、mutation-types.js、mutations.js、action.js); 以下图javascript

└── store
    ├── index.js          # 咱们组装模块并导出 store 的地方
    ├── actions.js        # 根级别的 action
    ├── mutations.js      # 根级别的 mutation
    ├── state.js          # 根级别的 state
    └── getter.js
复制代码

使用单一的状态树,应用的全部状态都会集中在一个比较大的对象上面,随着项目需求的不断增长,状态树也会变得愈来愈臃肿,增长了状态树维护的复杂度,并且代码变得沉长;所以咱们须要modules来为咱们的状态树分隔成不一样的模块,每一个模块拥有本身的state,getters,mutations,actions;并且容许每一个module里面嵌套子module;以下:html

└── store
    ├── index.js          # 咱们组装模块并导出 store 的地方
    ├── actions.js        # 根级别的 action
    ├── mutations.js      # 根级别的 mutation
    ├── state.js          # 根级别的 state
    └── modules
        ├── module1.js   # 模块1的state树
        └── module2.js   # 模块2的state树
复制代码

模块module1.js内部的代码结构以下vue

import { WIDTH_ADD } from '@/store/mutation-types.js'  // 引入事件类型

export default {
    namespaced: true,
    state: {
        width: 100,
        height: 50
    },
    getters: {
        modulegGetWidth(state, getters, rootState) {
            return state.width
        },
        modulegetHeight(state, getters, rootState) {
            return state.height
        }
    },
    mutations: {
        [WIDTH_ADD](state) {   // 使用常量替代 Mutation 事件类型
            return state.width++
        },
        addHeight(state) {    // 不使用常量
            return state.height++
        }
    },
    actions: {
        
    }
}
复制代码

注册到根state。
index.js以下java

import state from './state'
import getters from './getters'
import mutations from './mutations'
import actions from './actions'
import module1 from './modules/module1.js'  // 引入module1

export default {
    state,
    getters,
    mutations,
    actions,
    modules: {
        module1  // 注册完成
    }
}
复制代码

在组件内打印state。vuex

console.log(this.$store.state)
复制代码

如图 bash

Alt text

由上图,能够看到,module1已经被咱们添加到了当前的store.state内;

须要注意的ide

  1. Vuex在组件中computed中使用的时候,计算属性不能和state的数据项同名(同名了也不会报错,就是获取不了数据了)
  2. 有一点值得注意的是:当咱们在组件的计算属性中使用module里面的getters的时候,计算属性不和state的数据项同名这条规则貌似不生效,具体缘由还不知道,若是有知道的大佬帮忙指点一下
  3. 默认状况下,没有设置命名空间的时候,模块内部的 action、mutation 和 getter 是(除了state)注册在全局命名空间的(若是有重名就会报错 [vuex] duplicate getter key: [method])——这样使得多个模块可以对同一 mutation 或 action 做出响应。

解决方法是加命名空间 namespaced: trueui

如何在页面里面引用modulethis

  1. 在modules内的每一个模块加入命名空间
namespaced: true
复制代码

在vue文件内也能够这样spa

import { createNamespacedHelpers } from 'vuex'
const { mapState, mapActions } = createNamespacedHelpers('mudole1')
复制代码
  1. 注册到组件中
import { mapState, mapMutations } from "vuex"
computed: {
    ...mapState('module1', {
        width: state => state.width,  // 关联, 此处的state 为 module1/state
        height: state => state.height
    })
    },
methods: {
    ...mapMutations('module1', {  // 命名空间module1
        widthAdd: 'WIDTH_ADD',  // 经过mutation-types.js
        addHeight: 'addHeight'  // 直接加在mutations上面的方法
    }),
}
复制代码
  1. 注册完成,使用
created() {
    this.widthAdd()   // 将 `this.widthAdd()` 映射为 `this.$store.commit('module1/widthadd')`
    console.log(this.width)  // this.width已经变为commit之后的值
}
复制代码

如何在模块中访问全局内容?

若是你但愿使用全局 state 和 getter,rootState 和 rootGetter 会做为第三和第四参数传入 getter,也会经过 context 对象的属性传入 action。

若须要在全局命名空间内分发 action 或提交 mutation,将 { root: true } 做为第三参数传给 dispatch 或 commit 便可。
其实这块,做者在文档中已经说明的很清楚了,具体的连接: 详细连接

划分模块的好处

  • state更为容易管理,尤为在团队人数多的时候,本身负责本身的state,既保证store了完整的状态树,又避免了相互之间的state冲突
  • 无论是命名,或是操做 state 都会变得更加扁平和直观
相关文章
相关标签/搜索