Vuex 模块化modules和命名空间namespaced | 青训营

104 阅读2分钟

Vuex 模块化和命名空间

  • 在大型应用中,随着应用变得越来越复杂,我们需要管理越来越多的状态和数据。
  • 多个模块之间的状态可能会相互依赖。
  • 如果多个模块的字段名重复,容易造成很多错误。

为了解决上述问题,我们使用模块化+命名空间,将store对象分块,实现对不同模块管理。

1. 模块化

官方文档:

  • 由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
  • 为了解决以上问题,Vuex 允许我们将 store 分割成模块(module) 。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割。

举例:

  import Vue from 'vue';
  import Vuex from 'vuex';
  ​
  Vue.use(Vuex);
  ​
  import home from './home'
  import search from './search'export default new Vuex.Store({
      // 实现Vuex仓库模块
      modules:{
          home,
          search
      }
  });
  
  const state = {
  ​
  };
  const mutations = {
  ​
  };
  const actions = {
  ​
  };
  const getters = {
  ​
  };
  ​
  export default {
      // namespaced: true, // 是否开启命名空间
      state,
      mutations,
      actions,
      getters
  }

2. 命名空间

官方文档:

  • 默认情况下,模块内部的 action 和 mutation 仍然是注册在全局命名空间的——这样使得多个模块能够对同一个 action 或 mutation 作出响应。
  • 如果希望你的模块具有更高的封装度和复用性,你可以通过添加 namespaced: true 的方式使其成为带命名空间的模块。当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名。
  
  const store = createStore({
    modules: {
      account: {
        namespaced: true,
  ​
        // 模块内容(module assets)
        state: () => ({ ... }), // 模块内的状态已经是嵌套的了,使用 `namespaced` 属性不会对其产生影响
        getters: {
          isAdmin () { ... } // -> getters['account/isAdmin']
        },
        actions: {
          login () { ... } // -> dispatch('account/login')
        },
        mutations: {
          login () { ... } // -> commit('account/login')
        },
  ​
        // 嵌套模块
        modules: {
          // 继承父模块的命名空间
          myPage: {
            state: () => ({ ... }),
            getters: {
              profile () { ... } // -> getters['account/profile']
            }
          },
  ​
          // 进一步嵌套命名空间
          posts: {
            namespaced: true,
  ​
            state: () => ({ ... }),
            getters: {
              popular () { ... } // -> getters['account/posts/popular']
            }
          }
        }
      }
    }
  })
  • 带命名空间的模块,具有更高的封装度和复用性
  • 当模块被注册后,它的所有 getteractionmutation 都会自动根据模块注册的路径调整命名。

使用方法:

  • state: $store.state.模块名.属性名
  • getter: $store.getters.['模块名/属性名']
  • action: $store.dispatch('模块名/action名')
  • mutation: $store.commit('模块名/mutation名')