Vuexで状態管理を楽にする


Vuexとは?

Vuexはすべてのコンポーネントでデータを一元管理するための仕組みです。

Vuexがない環境ではコンポーネント間のデータの受け渡しには、propsやemitによるイベントを利用して行います。しかし、コンポーネント間でのデータ受け渡しが頻繁に行われたり階層が増えてくるとporpsや$emitでのデータ管理が難しくなります。

その問題を解決するための仕組みがVuexです。Vuexという一つの入れ物にデータを入れることでどこからでもVuex内のデータへのアクセスが可能になります。

VuexをインストールしてVueアプリの状態管理をしやすくする

まずは、Vuexをインストールします。

npm i -S vuex vuex-router-sync

vuexのインストールと一緒に「vuex-router-sync」というライブラリも一緒にインポートしておきました。

このライブラリは、Vuexで使うstore(mutationやgetter,actions)の中でroute情報を使えるようにするライブラリです。Vuexを使う際は、便利なので、一緒に入れておくと良いでしょう。

必要なライブラリをインポート出来たところで、main.jsを以下に書き換えます。

main.js
import Vue from 'vue';
import VueRouter from 'vue-router';
import App from './App.vue';
import { routes } from './routes';
import store from './store/store';
import { sync } from 'vuex-router-sync'

Vue.use(VueRouter);

const router = new VueRouter({
  routes
});

sync(store, router);

new Vue({
  el: '#app',
  router,
  store,
  render: h => h(App)
})

Vuexで状態管理をする「store/store.js」のインポート、vuex-router-syncのインポート、vuex-router-syncを使って、router(ルーティング)とstore(状態)を結びつける処理を追記。

Vuexで状態(store)管理

Vuexで状態管理をするためにstoreというディレクトリを作り、以下のフォルダ構成にしました。

store
├── modules
│   └── counter.js
└── store.js

基本的には、modules内にVuexで管理するstoreやstoreの状態を変更するmutations、mutationsに命令を出すactionsを書いたファイルを入れていきます。そして、store.jsはそれらのモジュールをまとめて、main.jsにexportします。

全てのモジュールファイルをまとめて、main.jsにエクスポートするstore.jsは以下です。

store.js
import Vue from 'vue';  /*vueとvuexをインポート*/
import Vuex from 'vuex';

import counter from './modules/counter';  /*vueとvuexをインポート*/

Vue.use(Vuex);

export default new Vuex.Store({
  modules: {
    counter                    /*vueとvuexをインポート*/
  }
});

次にVuexの本体となる状態管理を担うファイル「modules/counter.js」は以下のような記述になっています。

counter.js
import Vue from 'vue'

const state = {
  count: 0
};

const mutations = {
  'CHANGE_COUNT' (state) {
    state.count = state.count + 1;
  },
};

const actions = {
  plusCount: ({commit}) => {
    commit('CHANGE_COUNT');
  }
};

const getters = {
  currentCount: state => {
    return state.count;
  }
}

export default {
  state,
  mutations,
  actions,
  getters
}

今回は訪問者をカウントする機能で数字(count)をVuexのstateで管理して、View側からボタンを押すと管理している数字が上がっていく処理を作成しました。

state:管理したい値をここにobject形式で記載していきます

mutations:stateの値を変更したいときはmutationsに命令を出して、mutationsからstateの値を変更します

actions:Viewなどから状態変更やAPI通信をしたいときに、ここで定義したactionを呼び出します。

getters:stateで管理している値を参照したいときに、gettersにアクセスします(直接stateの値を参照しないのは、gettersでmapやfloorの処理などを挟むことによって、リファクタリングしやすくしたり、様々な形式でデータにアクセスできるようにするため。)

以上がVuexの役割です。

次にVuexで管理している値を参照したり、値を変更するボタンを設置しているファイルを紹介します。

新たにCounter.vueファイルを以下のように変更しました。

Counter.vue
<template>
  <div>
    <button @click="countUp">add count</button>
    <div>{{currentCount}}</div>
  </div>
</template>

<script>
  export default {
    computed: {
      currentCount() {
        return this.$store.getters.currentCount;
      }
    },
    methods: {
      countUp() {
        this.$store.dispatch("plusCount");
      }
    }
  }
</script>

このVueコンポーネントを見るとわかるように、

ボタンを押すと「this.$store.dispatch(“plusCount”);」にてplusCountアクションにアクセス
「this.$store.getters.currentCount」にて、Vuexで管理しているstoreを参照(gettersのcurrentCountにアクセス)
コンポーネントから、plusCountアクションに「this.$store.dispatch(“plusCount”);」にてアクセスして、そのplusCountアクションがCHANGE_COUNT mutationsに命令を出し、stateのcountを変更します。

何となくVuexの状態管理がわかってきましたね

最後に

Vuexを使って、どのComponentからも共通のstateにアクセスできるようになったおかげで、Component間でデータを受け渡ししまくる非効率なアプリケーション構築から解放されましたね!

Vuexの恩恵は大規模な開発になってくると格段に出てくると思うので学んでおいて損はないと感じました。