概要
Vue.jsの状態管理のVuexを学んでいきます。
Vue CLIを使い開発していきます。
前提知識
Vue.jsの基礎的な知識
そもそもVuexって???
こういったツリー構造があったときにAからBにデータを受け渡すには$emitで親にバケツリレーし、さらにそれをpropsでバケツリレーすることになります。
これは非常に冗長で、かなり管理のしずらいコードになってしまします。
そんな時に使うのがVuexです!
これをvuexを使うとこんな感じになります。
まーつまりAからVuexにデータをわたし、それを直接VuexからBに渡せると言うことです。
概要がわかったのでさっそく実装にうつっていきましょう!!!
早速やってみる
Vue CLIはinstallされている前提で話を進めていきます。
npm install --save vuex
まずはvuexをインストールしましょう!!
touch src/store.js
src配下にsrtore.jsを作成していきます。
Vuexは基本的にこのstore.jsに設定を書いていきます。
store.jsの名前は任意ですが、基本のお作法はstore.jsでやることが多いみたいです。
import Vue from "vue";
import Vuex from "vuex"
Vue.use(Vuex);
export default new Vuex.Store({
state: {
//処理
},
})
これがまず基本形になります。
上から説明するとまずVuexをimportして使えるようにします。
Vue.useはVue.jsのライブラリの関数を使用する時に使うもの程度に覚えておきましょう。(自分はそれくらいの理解で使っています)
Vuexを使うためには
new Vuex.Store
を使っていきます。
これにexport defaultを使うことによって外部で使用できるようにします。
import Vue from "vue"
import Vuex from "vuex"
Vue.use(Vuex);
export default new Vuex.Store({
state: {
count: 2
}
})
今回はcountに2を設定していきます。
これを呼び出すためには
<p>{{$store.state.count}}</p>
こんな感じで呼び出すことができます!!!
Vuex.storeは$storeで表すことができあとはstate.countで受け取っているイメージです。
これをどこのファイルでも使用することが可能になります。
では今度はこの数字を変更して表示させてみましょう。
変更するにはcomputedプロパティが使用できそうです。
<template>
<p>{{doubleCount}}</p>
</template>
<script>
export default {
data() {
return {
title: "welcom to tokyo",
subTitle: "sub title"
}
},
computed: {
doubleCount() {
return this.$store.state.count * 2
}
},
}
</script>
こんな感じでいけるのではないでしょうか。
しかしこれでは仮に*3, *4が欲しくなった時にひたすらcomputedで追加していく処理が必要になってしまいます。
そんな時に使えるのがgettersです
gettersとは
gettersを使うことでvuex上で処理をまとめることができます。
import Vue from "vue"
import Vuex from "vuex"
Vue.use(Vuex);
export default new Vuex.Store({
state: {
count: 2
},
getters: {
doubleCount: state => state.count * 2,
tripleCount: state => state.count * 3
}
})
イメージとしてはこんな感じです。
gettersで処理を一つにまとめてあげます。
ちなみに中身はアロー関数を省略記法でかいています
doubleCount: (state) => { return state.count * 2 },
省略しないとこんな感じです。
これをどう受け取るかと言うとvuexのmapGettersを使用していきます
<script>
import {mapGetters} from "vuex"
export default {
computed: {
...mapGetters(["doubleCount", "tripleCount"]),
},
}
</script>
何とこれでおっけいです!
どういった状態かと言うと
まずimport でvuexからmapGettersをインポートします。
その後mapGettersをcomputedないで配列で受け取ります。
スプレット演算子でcomputedに格納しています。
computedプロパティの中は基本的にオブジェクト出なければいけないので、スプレット演算子を使うことでオブジェクトにmapGettersを取りこんでいます。
ミューテーションを使ってみる!
現在の状態だとstateの状態が変更されてしまうと全体の値が変更されてしまいとても冗長になっています。
これを解消するためにvuexにはmutationというものが用意されています。
mutations: {
関数名(state, 任意の引数) {
}
}
のような書き方で記述することができます。
今回はincrementというカウントアップしていく関数を定義して行こうと思います。
import Vue from "vue"
import Vuex from "vuex"
Vue.use(Vuex);
export default new Vuex.Store({
state: {
count: 2
},
getters: {
doubleCount: state => state.count * 2,
tripleCount: state => state.count * 3
},
mutations: {
increment(state, number) {
state.count += number;
}
}
})
先ほどの文法通りにmutationsを足していきます。
第一引数にstateをとりStoreのstateにアクセスできます。
あとはstate.countをnumberの引数分カウントアップしていくように関数を定義しています。
ではこれを受け取っていきます。
this.$store.commit("increment", 2)
こんな感じで受け取ることができます!
mutationsはcommitで受け取ることができます。
第一引数に関数名を指定し、あとは引数があれば入れていきます。
今回はnumberで指定しているので、2を入れていくと2ずつカウントアップしていくようになります。
ではもう一つdecrementを追加していきます。
import Vue from "vue"
import Vuex from "vuex"
Vue.use(Vuex);
export default new Vuex.Store({
state: {
count: 2
},
getters: {
doubleCount: state => state.count * 2,
tripleCount: state => state.count * 3
},
mutations: {
increment(state, number) {
state.count += number;
},
decrement(state, number) {
state.count -= number;
}
}
})
複数のmutationsを受け取るにはmapMutationsヘルパーというものがあります。
<script>
import { mapMutations } from 'vuex';
export default {
methods: {
...mapMutations(["increment", "decrement"])
}
}
</script>
こんな感じでmethodsの部分に記述することができます。
引数はtemplateの部分で記述します。
例えばクリックしたと同時に発火する場合は
<div @click="increment(2)"></div>
こんな感じで引数を取ればおっけいです!
ただしmutationは同期的な処理しか基本的にかけません。
非同期的に処理する場合はactionを使っていきます!
actionとdispatchとは
非同期の処理を書きたい場合はactionsを使用していきます。
actions: {
increment(context, number) {
context.commit("increment", number);
}
}
こんな感じにmutationsの下に追加していきます。
actionsは関数の第一引数にcontextをとることができます。
これで関数ないで非同期処理が使えるようになります。
これを受け取る場合は
this.$store.dispach("increment", 2)
こんなかんじでactionsのcontextはdispatchを使用することによって受け取ることができます!!
もうおなじみですがactionsにもmapActionsがあります!
import { mapActions} from 'vuex';
export default {
methods: {
...mapActions(["increment", "decrement"])
}
}
またこんな感じで省略して受け取ることができます。
この際引数はまた
お疲れ様でした!!