组织 Vuex store 模块

在一个 Vue 应用程序中,只要你遵守我们在前面章节中介绍的强制规则,对于如何组织你的 store 并没有严格的限制。根据你的 store 的复杂程度,本书推荐了两种结构,你可以在接下来的章节中使用它们。让我们开始吧。

创建一个简单的 store 模块结构

在这个简单的模块结构中,你可以拥有一个 /store/ 目录,其中包含一个 /modules/ 目录,用于存放所有的模块。以下是创建这个简单项目结构的步骤:

  1. 创建一个 /store/ 目录,并在其中创建一个 /modules/ 目录,用于存放 store 模块,如下所示:

    // vuex-sfc/structuring-modules/basic/
    ├── index.html
    ├── entry.js
    ├── components
    │   ├── app.vue
    │   └── ...
    └── store
        ├── index.js
        ├── actions.js
        ├── getters.js
        ├── mutations.js
        └── modules
            ├── module1.js
            └── module2.js

    在这个简单的结构中,/store/index.js 用于从 /modules/ 目录组装模块,并导出 store,以及根级别的 stateactionsgettersmutations,如下所示:

    // store/index.js
    import Vue from 'vue'
    import actions from './actions'
    import getters from './getters'
    import mutations from './mutations'
    import module1 from './modules/module1'
    import module2 from './modules/module2'
    import Vuex from 'vuex'
    
    Vue.use(Vuex)
    
    export default new Vuex.Store({
      state: {
        number: 3
      },
      actions,
      getters,
      mutations,
      modules: {
        a: module1,
        b: module2
      }
    })
  2. 将根级别的 actionsmutationsgetters 分割到单独的文件中,并在根目录的 index 文件中组装它们,如下所示:

    // store/mutations.js
    export default {
      mutation1 (state) {
        //...
      },
      mutation2 (state, n) {
        //...
      }
    }
  3. .js 文件中创建模块,包含它们的 statesactionsmutationsgetters,就像你在前面的章节中学到的那样,如下所示:

    // store/modules/module1.js
    export default {
      namespaced: true,
      state: {
        number: 1
      },
      mutations: { ... },
      getters: { ... },
      actions: { ... }
    }

    如果一个模块文件变得太大,我们可以将模块的 stateactionsmutationsgetters 分割到单独的文件中。这就引出了一个高级的 store 模块结构,我们将在下一节中介绍它。让我们来看看。

创建一个高级的 store 模块结构

在这个高级的模块结构中,你可以拥有一个 /store/ 目录,其中包含一个 /modules/ 目录,用于将所有模块保存在此文件夹的子文件夹中。我们可以将一个模块的 stateactionsmutationsgetters 分割到单独的文件中,然后将它们保存在模块文件夹中,步骤如下:

  1. 创建一个 /store/ 目录,其中包含一个用于存放 store 模块的 /modules/ 目录,如下所示:

    // vuex-sfc/structuring-modules/advanced/
    ├── index.html
    ├── entry.js
    ├── components
    │   └── app.vue
    └── store
        ├── index.js
        ├── action.js
        └── ...
        ├── module1
        │   ├── index.js
        │   ├── state.js
        │   ├── mutations.js
        │   └── ...
        └── module2
            ├── index.js
            ├── state.js
            ├── mutations.js
            └── ...

    在这个更复杂的项目结构中,/store/module1/index.js 用于组装 module1,而 /store/module2/index.js 用于组装 module2,如下所示:

    // store/module1/index.js
    import state from './state'
    import getters from './getters'
    import actions from './actions'
    import mutations from './mutations'
    
    export default {
      namespaced: true,
      state,
      getters,
      actions,
      mutations
    }

    我们也可以将模块的 state 分割到一个单独的文件中,如下所示:

    // store/module1/state.js
    export default () => ({
      number: 1
    })
  2. 将模块的 actionsmutationsgetters 分割到单独的文件中,以便在前面的模块 index 文件中组装它们,如下所示:

    // store/module1/mutations.js
    export default {
      mutation1 (state) {
        //...
      },
      mutation2 (state, n) {
        //...
      }
    }
  3. 导入模块的 index 文件到 store 根目录,我们在那里组装模块并导出 store,如下所示:

    // store/index.js
    import module1 from './module1'
    import module2 from './module2'
  4. 开启严格模式以确保 storestate 只能在 mutations 属性中被修改,如下所示:

    const store = new Vuex.Store({
      strict: true,
      // ...
    })

    使用严格模式是一个好的实践,它可以提醒我们任何 state 的修改都应该在 mutations 属性内部进行。因此,在开发过程中,每当在 mutations 属性之外修改 storestate 时,都会抛出一个错误。然而,我们应该在生产环境中禁用它,因为它在 store 中存在大量 state mutations 时会影响性能。因此,我们可以使用构建工具动态地关闭它,如下所示:

    // store/index.js
    import Vue from 'vue'
    import Vuex from 'vuex'
    import module1 from './module1'
    import module2 from './module2'
    
    Vue.use(Vuex)
    
    const debug = process.env.NODE_ENV !== 'production'
    
    export default new Vuex.Store({
      modules: {
        a: module1,
        b: module2
      },
      strict: debug,
      // ... 其他根级别的 state、actions 等
    })

然而,在 store 中使用严格模式处理表单时存在一个注意事项,我们将在下一节中介绍它。