🔫

Nuxt.jsによるVuexのストア分割の仕組み

2022/04/30に公開

ストアによるデータ管理のメリットは?

以下の二つだと考えています。

  • コンポーネント間の値の受け渡しが必要ない
  • コンポーネントのビジネスロジックをストアに切り出せる

Vuexでは値をstateで保持し、getterでコンポーネント側から取得。mutationsで値を変更し、API通信や外部ストレージへのアクセスなどmutationsの責務外の処理をactionsで行う、といったことをしています。

つまりストアを利用することで、これらコンポーネント側のビジネスロジックがストアに集約でき、管理が容易になります。

また、データをグローバルに持つことができるので親コンポーネントから子コンポーネントにpropsで値を渡したりといった処理が必要ありません。

なぜストア内の処理を分割管理したいのか?

アプリケーションが大きくなり成長していくにつれて、ストアに色々な処理やデータが集まるようになり管理が煩雑になることが考えられます。
これを解決するには、ストアーを分割して管理する必要があるからです。

ただ、書籍「Vue.js入門 基礎から実践アプリケーション開発まで」には以下のような記述があります。

Vuexは信頼できる唯一の情報源であることを前提に実装されています。アプリケーション内でただ1つのストアのみが存在するようにします。

ストアを分割することは上記に反するような気がしますが、Vuexにはそれを考慮した上で分割するためのモジュール機能が用意されています。

モジュールに分けるには

以下のように、modulesというオプションを使うことで分割が可能です。

namespaced: trueに設定しているので、コンポーネント側からはthis.$store.getters('users/getUser')といった形式で定義したモジュール名を含めて呼び出します。このオプションにより名前空間が作られるので、同名のメソッドが定義されていてもどちらも呼ばれてしまうようなことが起きない仕組みになっています。

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

export default new Vuex.Store({
    modules: {
        users: {
            namespaced: true,
            state: {
                user: "taro"
            },
            getters: {
                getUser(state) {
                    return state.user
                }
            },
            mutations: {...},
            actions: {...}
        },
    },
    teams: {
        namespaced: true,
        state: {...},
        getters: {...},
        mutations: {...},
        actions: {...}
    },
});

→上記をインスタンス化する際に引数としてまとめてモジュールを渡しているのでみずらいですが、ファイル分割するなどで管理しやすくすることもできます。

https://vuex.vuejs.org/ja/guide/modules.html

Nuxt.jsのVuexに用意されたモード

Vuexにはクラシックモードとモジュールモードの2つ存在しています。(クラシックモードはNuxt3では廃止予定)

クラシックモード => ストアの処理を1つのファイルで管理(store/index.js
モジュールモード => ストアの処理を複数のファイルで管理(store/*.js

モジュールモードを使うには?

上記のようなストアの分割をするために、store/配下に {モジュール名}.jsというファイルを作るだけで、Nuxt.jsが勝手にモジュールを生成しコンポーネント側から利用できるようにしてくれます。
このフレームワークの機能を使って何気なく書いていると、ここまで書いた内容をほぼ意識する必要がないですよね。

また、モジュールモードと明示的に記述するわけでなく、以下が満たされていると自動的にNuxt.jsがモジュールモードと認識してくれるみたいです。

  • index.jsがstoreオブジェクトをexportしていない
  • store/index.js が存在しない

https://develop365.gitlab.io/nuxtjs-2.8.X-doc/ja/guide/vuex-store/

Discussion