search
LoginSignup
106
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

クラウドワークス Advent Calendar 2015 Day 25

posted at

updated at

Vue.js用のFluxライクなライブラリVuexを試してみる

まえがき

Vue.js用のFluxライクなライブラリVuexを試してみました。

Vuex

注意:まだ開発中でAPIも変わる可能性があります(2015/12/25)

2017/12/17 追記

改めて学び直してみました。

データの流れ

詳しくはドキュメントを読んだ方が正確だけど、この図だけ見れば何となくやりたいことがわかるはず。

vuex.png

何となくFluxっぽいですね。

自分の理解としては

  1. コンポーネントからActionを呼び出してそこで外部のAPIと通信してデータを取得
  2. Mutationでデータをセット
  3. Stateがコンポーネントの数値をアップデート

という流れ(間違ってたらすみません)。

Vue.jsは値の取得に対しては関与しないフレームワークですが、Vuexを入れることにより値の取得からセットまでライブラリで制御できるので、無秩序になりがちだったVue.jsを使ったアプリケーションに秩序をもたらすことが出来そうです。

作った物

作った物はおなじみToDoList。横着して値の追加しか対応していません。

vuex.gif

コードと解説

Vueifyを使ってコンパイルすることを前提としているので、.vueなる拡張子が出てくるので注意。

まずはstoreから

index.js
import Vue from 'vue'
import Vuex from 'vuex'
import actions from './actions'
import mutations from './mutations'

Vue.use(Vuex);

const state = {
  input: "",
  todos: []
}

export default new Vuex.Store({
  state,
  actions,
  mutations
})

actions.js
export default {
  addTodo: 'ADD_TODO'
}
mutations.js
export default {
  ADD_TODO (state, text) {
    state.todos.push(text)
  }
}

Vue.use(Vuex)でセットアップします。

stateだけここで定義してactionsとmutationsは別ファイルにしていますが、ここは好みだと思います。

actionsではここは簡単にADD_TODOにdispatchしています。外部からajaxで値を持ってくるときなどはここに書くと良さそうです。

mutationsではADD_TODOを定義しています。これはinputタグのkeyupに紐付けられた関数から呼び出されてstatetodosに値を追加することを想定して作られています。

次に親VieModel。

index.js
import Vue      from 'Vue';
import TextForm from './components/TextForm.vue';
import ToDoList from './components/ToDoList.vue';
import store    from './store/';

window.onload = function(){
  var main = new Vue({
    el: "body",
    data: store.state,
    components: {
      "text-form": TextForm,
      "to-do-list": ToDoList
    }
  })
}

Vueとコンポーネント、それとVuexで作ったstoreを読み込みます。
そして親ViewMoelにstoreとコンポーネントをセットします。

data属性にはstore.stateを入れることで動的にstateの中身を変えたときに各コンポーネントに反映するようにしています。

次にコンポーネント。

TextForm.vue
<template>
  <div>
    <input type="text" v-model="input" @keyup.enter="addTodo"/>
  </div>
</template>

<script>
  import store from '../store/';

  export default {
    props: ['input'],
    methods: {
      addTodo: function(e){
        var text = e.target.value;
        store.actions.addTodo(text);
        e.target.value = '';
      }
    }
  }
</script>
ToDoList.vue
<template>
  <ul>
    <li v-for="todo in todos">{{todo}}</li>
  </ul>
</template>

<script>
  export default {
    props: ['todos']
  }
</script>

コンポーネントはpropsで渡したデータを元に描画を行っています。

actionsで定義したaddToDoをここで呼び出しています。

気をつけることとして、mutationsで定義したaddToDostatetextの二つの引数を必要としていたのですが、actions経由で呼び出すときには引数はtextだけでいいと言うことです。ちょっと調べ切れていないのですが、actionsで呼び出すかていでよろしくやっているもと思われます(詳しくはコードを読んでみよう)。一瞬ちょっと違和感を感じてしまいますね。

addToDoに渡されたデータを使ってtodosが更新され、Todoリストが更新されるようになっています。

おわり・感想

まだ使ってみたレベルの話ですが、うまく使えばVue.jsをつかってやっていた開発の辛いところを解消が出来る感触があります。

Vueを使ってFluxをやるときはReduxを使うというやり方もありますが(Vue.jsにreduxを載せた話)。Vue独自のFluxライクな実装が出てきたことにより、Vueに適したやり方も出来るようになってきたのではないでしょうか。

これ以上ライブラリが増えて辛いという面もありますが、追っていくのも楽しそうです。

参考URL

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
106
Help us understand the problem. What are the problem?