とあるWeb屋の備忘録

とあるWeb屋の備忘録。たまに雑記。

Vuexのモジュール分割について

Vuexでストアを管理していると、アプリケーションが大きくなるにつれてストアが肥大化し、見通しが悪くなる問題が起こります。
それを回避するためにストアを分割できるようになっています。例えばアプリケーションの機能ごとやページごとにストアを分割していれば、コードの見通しがよくなりますし、プロジェクトメンバーで共同で作業しやすくなります。

以下にストアを分割する方法を記載します。

// ストア側

import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);

const moduleA = {
  namespaced: true,
  state: {...},
  getters: {...},
  mutations: {...},
  actions: {...}
}

const moduleB = {
  namespaced: true,
  state: {...},
  getters: {...},
  mutations: {...},
  actions: {...}
}

export default new Vuex.Store({
  modules: {
    aaa: moduleA,
    bbb: moduleB
  }
});

これでストア分割完了です。
ポイントは各モジュールを定義するときに、namespacedオプションをtrueに設定することです。
モジュール分割をすると、同一のミューテーションタイプやアクションタイプが指定できることになります。そのため、どちらか一方を呼び出したときに、同一のタイプはすべて呼び出されることになります。それを避けるために、namespacedtrueにすることで影響範囲を限定することができます。

namespaceを与えたときは以下のように、各モジュールのミューテーションタイプ、アクションタイプを指定して呼び出します。

// コンポーネント側
this.$store.commit('aaa/設定したミューテーションタイプ')

this.$store.dispatch('bbb/設定したアクションタイプ')

this.$store.getters['ccc/設定したゲッター'] // これはゲッターの例

このようにnamespaceを設定することでモジュールごとのミューテーション、アクション、ゲッターを呼び出せます。
マップヘルパーにnamespaceを登録すればモジュール名を省略して呼び出せます。その場合はヘルパーの第一引数にnamespaceを指定します。

computed: {
  ...mapMutations("aaa",["設定したミューテーションタイプ"]),
  this.[設定したミューテーションタイプ]

}

ちなみにモジュール分割はネストもできるので、以下のように書くことも可能です。

const moduleA = {
  namespaced: true,
  state: {...},
  getters: {
    parentGet: ...
  },
  mutations: {...},
  actions: {...},

  modules: {
    page01: { // 親のnamespaceを継承するので、例えばゲッターを指定したいときは親モジュールのゲッターの呼び方と同じでOK(下記★参照)
      state: {...},
      getters: {
        get: // ゲッターの処理書く
      },
      mutations: {...},
      actions: {...},

      modules: {
        namespaced = true
        layer01: { // namespacedを指定しているので、例えばゲッターを指定したいときは親モジュールから相対パスで指定して呼び出す(下記♦参照)
          namespaced: true,
          state: {...},
          getters: {
            get: // ゲッターの処理書く
          },
          mutations: {...},
          actions: {...},
        }
      }
    }
  }
}

★の呼び出し方

...mapGetters("aaa", ["parentGet", "get"]), // マップヘルパー使ったとき

this.get // これで子のget呼べる
this.$store.getters.parentGet // マップヘルパー使わない場合

♦の呼び出し方

...mapGetters("aaa", ["parentGet", "get", "layer01/get"]), // マップヘルパー使ったとき

this['layer01/get'] // これで孫のget呼べる
this.$store.getters['form/layerPage/profile'] // マップヘルパー使わない場合は親からの相対パスで呼ぶ

モジュール分割は他にも例えば別モジュールに登録された処理を呼び出したり、ルートに登録されたモジュールを呼べたりするので、公式ドキュメント載せておきます。

参考資料
モジュール | Vuex