Vue.js Logo

前から気になっていたVuexを始めました。

Vuexとは

公式サイト(Vuex とは何か? · GitBook)には以下のように書かれている。

Vuex は Vue.js アプリケーションのための 状態管理パターン + ライブラリです。

Fluxを参考に作られているらしいけど、Fluxとはなんだろう?という疑問が出てきた。

Fluxとは

結局FluxやらReduxやらって何なのか個人的なまとめ - Qiitaが分かりやすい。

Facebookが提唱しているアーキテクチャで、JavaScriptのデータの流れを分かりやすく整理するために使われます。

フロントエンド周りはビューが複雑に絡み合い、データがどう動くのか分からなくなることが多い。一つのデータを変更すると、それを参照している複数のビューが表示を変え、そして別のイベントが発火され・・という感じでカオスな状態になるのが目に見える。

データの流れを整理することで、このカオスな状態を整理整頓するということだ。ところで、Fluxの読み方は”フラックス”である。

Vuexの仕組み

Vuexの話に戻ってくるが、Vuexの仕組みは以下の通り。

vuex

Actionの役割は、データを取ってきたり、計算を行う(非同期処理が可能)。Mutationの役割は、Stateの状態を変更する。Stateの役割はデータを保持すること。コンポーネントはStateのデータを表示し、ユーザ操作があればActionを呼び出す。

シンプルで簡単だな、という印象。

Vuexを始める

vue-cliを使ってプロジェクトを作成し、vuexをセットアップする。

プロジェクト作成

vue-cliを使うと、コマンドで一発である。

npm install --global vue-cli
vue init webpack todo_vue
  ? Project name todo_vue
  ? Project description todo webapp
  ? Author ei <ei.email.com>
  ? Vue build standalone
  ? Install vue-router? Yes
  ? Use ESLint to lint your code? Yes
  ? Pick an ESLint preset Standard
  ? Setup unit tests with Karma + Mocha? Yes
  ? Setup e2e tests with Nightwatch? Yes

cd todo_vue
npm install

以下のファイルが作成された。
todo_vue at a205fa61ac5ae1ece8142f8a7daa52d154317e4f

vuexのセットアップ

npmコマンドでvuexをセットアップ。

npm install --save vuex

バージョンは2.3.1がインストールされた。

Vuexで作るファイル

アプリケーションの構造 · GitBookを参考にし、以下のファイルを作成する。

  • store/index.js
  • store/actions.js
  • store/getters.js
  • store/mutation-types.js
  • store/modules/todo.js

Vuexを使ったTODOアプリ

vuex/examples/shopping-cartが参考になる。難しいことはせずに、TODOの一覧が出るところまでを作ることにした。

src/main.js

storeを使えるようにする。
main.js at 3e7b05975a9ff171977ba908c02a05e2a8e20bbc

import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store'

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  store,
  router,
  template: '<App/>',
  components: { App }
})

/src/store/modules/todo.js

ここがメインの処理。

stateに保持したいデータを保持。gettersで出力の管理。actionsからmutationsを呼び出すときは、commitを使ってやりとりする。actionsとmutationsの書き方は覚える!

todo.js at 3e7b05975a9ff171977ba908c02a05e2a8e20bbc

import * as types from '../mutation-types'

// initial state
const state = {
  all: ['todoA', 'todoB', 'todoC']
}

// getters
const getters = {
  allTodos: state => state.all
}

// actions
const actions = {
  getAllTodos ({commit}) {
    commit(types.RECEIVE_TODOS, {todos: ['todo1', 'todo2', 'todo3']})
  }
}

// mutations
const mutations = {
  [types.RECEIVE_TODOS] (state, {todos}) {
    state.all = todos
  }
}

export default {
  state,
  getters,
  actions,
  mutations
}

/src/store/mutation-types.js

上のtodo.js内でタイプを使っているところの定義。
mutation-types.js at 3e7b05975a9ff171977ba908c02a05e2a8e20bbc

export const RECEIVE_TODOS = 'RECEIVE_TODOS'

コンポーネント

コンポーネントからtodo.jsのgetterを呼び出し、TODOを表示する。また、コンポーネント作成時に、Actionを呼び出して、TODOの値を変更している(APIで取得する代わり)。
Top.vue at 3e7b05975a9ff171977ba908c02a05e2a8e20bbc

import { mapGetters, mapActions } from 'vuex'
export default {
  name: 'top',
  methods: {
    ...mapActions([
    ]),
    goNewTask: function () {
      this.$router.push('Hello')
    }
  },
  computed: mapGetters({
    todos: 'allTodos'
  }),
  created () {
    this.$store.dispatch('getAllTodos')
  }
}

終わりに

簡単にVuexは取り入れることができる。今回のtodo.jsが、エンティティクラスのような扱いで、ここで集中管理していくことになる。小規模なアプリだと少しめんどくさいけど、Vuexを使っておく方が良いと思う。

一部、書き方を覚えないといけないところがあるが、サンプルを参考にしながら一回書けば、次からは難なく書けるだろう。

以下のページが参考になった。
Vue.js + Vuexで開発をしてみよう! - Tech Blog - Recruit Lifestyle Engineer
構造の複雑さとVuex書き分け - Qiita