LOGv:20171214

Vuexやってみた

ドキュメント

  • store(ストア)とはアプリケーションの状態(ステート:state)を保持するコンテナ
  • storeの構造は以下の通り
store : {
  state     : {...},
  mutations : {...},
  getters   : {...},
  actions   : {...},
  modules   : {...},
  plugins   : [...]
}
  • storeを直接変更することはできない
  • mutation(ミューテーション)をコミットすることによってのみstoreの状態を変更できる
  • 1つのアプリケーションは1つのstoreしか持たない (単一ステートツリー:single state tree)
  • storeにはstate, getters, mutations, actions, modulesが定義できる
  • コンポーネントが複数のstateプロパティやgetter(ゲッター)を必要としている場合、mapStateヘルパを使うと便利
  • コンポーネントのcomputedプロパティ(算出プロパティ)とstoreのgetterをマッピングさせるmapGettersヘルパがある
  • getterへのアクセス方法は2種類プロパティスタイルとメソッドスタイルがある。
getters: {
    getTodoById : state => id => {
        return state.todos.find(todo => todo.id === id)
    }
}
  • 関数を返すgetterを設定すればメソッドスタイルでアクセス可能であるが、キャッシュはされない
  • mutationはイベントに近い概念
  • 各mutationはtype(タイプ)とhandler(ハンドラ)を持つ
  • mutation handlerを直接呼ぶことはできない(ハンドラなので)
  • typeはイベントタイプのようなもの
let store = new Vuex.store({
    state : {
        count : 1
    },
    mutations : {
        add (state, payload) { // キーがtypeで値がhandler
            state.count += payload.num;
        }
    }
});

store.commit('increment', { num : 2 });
  • handler関数はVuexのstate(状態)を第1引数に取り、第2引数にデータを取ることができる。このデータを特定のmutationに対するpayload(ペイロード:伝送するデータ)と呼ぶ
  • ペイロードの型はほとんどの場合オブジェクトにすべき
  • コミットをオブジェクトスタイルにすることもできる
// オブジェクトスタイルの場合はtypeプロパティが必須
// オブジェクトスタイルでコミットするとオブジェクト全体がpayloadとしてmutation handlerに渡される
store.commit({
    type : 'add',
    num  : 2
});
  • Vuex storeの状態はVueによってリアクティブになっているので、値に注意を払う必要がある
    • 必要なフィールドの定義と初期値を設定しておく
    • 新しいプロパティをオブジェクトに追加するにはVue.set()メソッド使用するか、全く新しいオブジェクトで書き換えるか、新しいオブジェクトで既存のオブジェクトを書き換える。
  • mutationは同期的でなければならない。

  • actionとmutationの違いは以下の通り。
    • actionはmutationをcommitする。
    • actionは非同期処理を含むことができる。
    • 第1実引数にstoreのコンテキスト(ストアインスタンスではない)を受け取る。
  • actionはstore.dispatchがトリガーとなり実行される。
  • dispatchもcommit同様オブジェクトスタイルとペイロード形式に対応している。
  • moduleのmutationやgetterでの第1引数のstateはローカルステートになっている。
  • actionではcontext.stateでローカルステートになりルートのステートへはcontext.rootStateでアクセスできる。
  • getterでは第3引数でrootStateにアクセスできる。(第2引数はgetter)
  • module内部のmutation/getter/actionは全てグローバル名前空間の元に登録されるがnamespacedプロパティをtrueにすることでmoduleの名前空間に入れることができる。
    • 名前空間が付いたmoduleのgetterは第3引数rootState第4引数rootGetterが渡される
    • グローバル空間にdispatch、commitしたい場合はdispatch,commitの第3引数に{ root : true }を渡す
  • 名前空間があるmoduleのバインディングはbinding helperに名前空間の文字列を渡し、そのコンテキストとしてバインディングを行うことができる。
computed : {
  ...mapState('some/nested/module', {
    a: state => state.a,
    b: state => state.b
  })
}
  • createNamespacedHelpersを使うと名前空間付けされたbinding helperを作成できる。
  • 動的にmoduleを登録するにはstore.registerModule()メソッドを利用し、ネストされたmoduleを登録したい場合は配列で指定する
store.registerModule(['nested', 'myModule'], {
  // ...
})
// この時 nestedを先に登録しておかないと何も登録されない。
  • store.unregisterModule()メソッドを使い動的に登録したmodileを削除できる。
    • 静的なmoduleは削除できない。
  • 状態を保持して新しいmoduleを登録したい場合はstore.registerModule()メソッドの第3引数に{ preserveState : true }を渡す。
  • strictモードを有効にするとVuexの状態がmutationハンドラ外で変更された際、エラーを投げる

binding helper対応表

store propertiesbinding helpercomponent properties
store.state← mapState →コンポーネントのcomputed
store.getters← mapGetters →コンポーネントのcomputed
store.commit← mapMutations →コンポーネントのmethods

open close