今回はVue.jsで使用できる拡張ライブラリの一つVuexについて解説します。
具体例と画像を交えてできる限りわかりやすく解説しました。
Vuexとは?
VuexとはVue.jsの拡張ライブラリの一つです。
Vuexの主な機能は、アプリケーションのデータの状態を「一元管理」できるというもの。
以下の記事で紹介した、props、emitを使った値の受け渡しでもコンポーネント間の通信は可能でしたね。
小規模なアプリケーションならprops、emitだけでも問題有りません。
しかし、アプリケーションが大規模になるにつれて、コンポーネント間の構造や親子関係は複雑になっていきます。
そんな時にいちいちコンポーネント間でデータをやり取りするのではなく、アプリケーション全体で共有できるデータ管理システムがあれば便利です。
それがまさにVuexです。データのやり取りをアプリケーション全体で可能にしたものというイメージがわかりやすいかと思います。
Vuexの考え方
Vuexの概念は以下の画像のとおりです。(公式サイトより)

①dispatchでactionsを呼び出す。
②commitでmutationsを呼び出す。
③mutationsはstateを更新する。
④コンポーネントでstateを参照する。
基本的にこの流れに沿って状態管理が行われます。
「全然イメージわかない、、、」
ということで、できるだけイメージが湧きやすいように実際のWebアプリでの挙動を参考に考えていきましょう。

タスクを追加すると即座にその上のタスク一覧に反映されていますね。
このタスク管理アプリもVuexを利用して実装しています。
では「タスクを追加する」ボタンを押したときに何が起きているのか詳しく解説していきます。
改めてVuexってどういう仕組み?
公式のイメージ図はシンプル過ぎて初心者には概念がつかみにくいと感じたので、さっきのTodoアプリを参考に書き換えてみました。

だいぶ分かりやすくなったかと思います。
Form.vueはタスクを追加するときのフォームコンポーネント。
List.vueはタスクの一覧表示をしているリストのコンポーネントを表しています。
順を追ってみていきましょう。
コンポーネントからアクションを呼び出す

この概念図の①dispatchで呼ぶ。の部分です。
コンポーネントからアクションを呼び出すことをdispatch(ディスパッチ)というので覚えておきましょう。
「タスクを追加する」のボタンが押された時、inputタグ内の情報(this.new_task)を引数にしつつdispatchでアクションを呼び出します。
async addTask() {
await this.$store.dispatch('task/add', this.new_task)
},
アクション内でAPIにアクセスして、ミューテーションを呼び出す
Form.vueから呼び出されたアクション内ではAPIへのアクセスとミューテーションの呼び出しを行います。

②axiosでアクセスする。③jsonデータが返ってくる。④commitでjsonデータを渡す。の部分ですね。
今回想定するAPIは以下のような感じです。
ここはLaravelのコードなので、あまり理解できなくでも大丈夫ですが、新しいタスクを追加して、その後にタスクの一覧をjsonで返していると思って下さい。
public function store(TaskRequest $request, Task $task)
{
$task->fill($request->all());
$task->save();
$tasks = Task::all();
return $tasks;
}
アクションの関数では第一引数にミューテーションを呼び出すためのcontext、第二引数にコンポーネントから渡されたdataが入ります。
今回、アクションを呼び出すときに渡したのはthis.new_taskだったのでdataにはthis.new_taskが入っています。
まずはaxiosでdataを引数に渡しつつ、APIにpostしています。
async add(context, data) {
const response = await axios.post("/api/tasks/add", data);
context.commit('setTasks', response.data)
},
apiから返ってくるjsonデータはresponse.dataでとれるので、それを引数にミューテーションを呼び出しています。
(今回返ってくるjsonデータはタスクの一覧なのでresponse.data=タスクの一覧です。)
アクション内からミューテーションを呼び出すことをcommit(コミット)と言うので覚えておきましょう。
ミューテーション内でステートを更新
アクションで呼び出されたミューテーションの中で実際にステートを更新します。

画像の⑤jsonデータを元にstateを更新。の部分ですね。
ミューテーションで定義されたsetTasks関数では第一引数に現在のステート、第二引数にアクションから渡されたデータが入ります。
今回アクションでcommitするときにresponse.data(タスク一覧のjson)を引数で渡したので、ミューテーションの第二引数にはタスクの一覧が入っています。
setTasks(state, tasks) {
state.tasks = tasks
},
つまり、ここではアクションから渡されたデータ(=response.data=タスクの一覧)でstateを更新しています。
Vuexにはミューテーション内ではステートの更新のみを行うというルールがあるので覚えておきましょう。
コンポーネント内でステートを参照する
最後にList.vueコンポーネント内でmapState関数を使うことでVuexのstateを参照できます。
ここではVuexのstateから参照したタスク一覧をv-forでループさせる、ということを行っています。
<template>
<ul>
<li v-for=task in allTasks>{{task.body}}<li>
<ul>
<template>
<script>
import { mapState } from 'vuex'
export default {
computed: {
...mapState({
allTasks: state => state.task.tasks
})
},
}
<script>

ここまでがVuexによる状態管理の一連の流れでした。
「全てのタスク一覧」という状態(state)をactionsからmutationsの流れで更新したり、mapStateを使ってどのコンポーネントからでも参照できるようになっています。
最後に
今回はVuexによる状態管理を解説しました。
最初は丈長で書くのが面倒だと感じるかもしれませんが、ぜひ習得してみてください!
Vue.js関連の人気記事はこちら!
Vue.jsのおすすめ書籍はこちら!