はじめに
Vuexについて勉強したのでまとめてみます。
Store
Vuexを使う上でアプリケーションの状態(情報)を管理する役割。
Vuexとは
state management。データ(状態)を管理するもの。
Vuexがない環境ではコンポーネント間のデータの受け渡しには、propsや$emitによるイベントを利用して行います。しかし、コンポーネント間でのデータ受け渡しが頻繁に行われたり階層が増えてくるとporpsやemitでのデータ管理が難しくなる。複雑に構成されたコンポーネントでのデータ管理の難しさを解決するための仕組みがVuexです。Vuexという入れ物にデータを入れることでどのコンポーネントからでもVuex内に保持するデータへのアクセスが可能になります。
Vuexのstateはdataプロパティと同じもの。Vuexのstateにプロパティを追加することですべてのコンポーネントからアクセスが可能となる。Vuexは独立したデータ保管場所。
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
},
getters: {
},
mutations: {
},
actions: {
}
})
state→アプリケーションの状態(情報)
getters→stateの一部やstateから返された値を保持する
mutations→stateを更新(変化)させる
action→非同期通信や外部APIとのやりとりを行う
state
stateはdataオプションのような存在で、stateが変更されるとコンポーネントの算出プロパティやテンプレートへと反映されます。なんでもstateに情報を保持させるのではなく、コンポーネント内部でしか使わないようなものはこれまでと同様にdataオプションに、アプリケーション全体で管理するものはstore内で管理すると良いです。
getters
stateから別の値を算出する為に使われる。
gettersは算出プロパティcomputedと同じような働きをしてくれます。
値がキャシュされ、そのgettersが依存しているstateが更新されない限り再評価しません。
違う点は引数にstateと他のgettersを持つことで、それらを使って違う値を返します。
computedと同様に、計算した値を返す以外の処理は行うべきではありません。
computedプロパティだと記述したそのコンポーネント内でしか利用できないので、他のコンポーネントで同じ処理を行いたい場合は同じコードをコンポーネント毎に記述する必要がありまる。でもGettersを利用するとVuexのstoreの中に保存されているので、他のコンポーネントからも同じ方法で利用できます。
getters
getters: {
users : function(state){
return state.users.filter(user => user.age < 30);
}
computedプロパティ
算出プロパティ(computed)はリアクティブな依存関係にもとづきキャッシュされる.
算出プロパティは、リアクティブな依存関係が更新されたときにだけ再評価されます
computed:{
users: function(){
return this.$store.state.users.filter(user => user.age < 30);
}
}
↑2つとも同じ結果になる。
mutations
mutations は state を更新する関数を登録します。
stateの更新を行うためには、mutationsを使う必要があります。
mutations はcommit 関数を使って発火させる。
実際に Vuex のストアの状態を変更できる唯一の方法は、mutationsをコミットすることです。
原則として、mutation以外でstateの更新を行うことを禁止。
commitにはpayloadで値を渡すことができる。
actions
actionsは、状態を変更するのではなく、mutationsをコミットします。
アクションは任意の非同期処理を含むことができます。
mutationsを実行するのはcommitですが、actionsを実行するためにはdispatchメソッドを使用します。
### 例 ```store\index.js import Vue from 'vue'; import Vuex from 'vuex';
Vue.use(Vuex);
export const store = new Vuex.Store({
strict: true,
state: {
products: [
{name: 'Banana', price: 20},
{name: 'Orange', price: 40},
{name: 'Apple', price: 60},
{name: 'Rice', price: 80}
]
},
getters: {
saleProducts: (state) => {
let saleProducts = state.products.map( product => {
return {
name: '' + product.name + '',
price: product.price / 2,
};
});
return saleProducts;
}
},
mutations: {
reducePrice: (state)=> {
state.products.forEach(product => {
product.price -= 1
});
}
},
actions: {
reducePrice: context => {
setTimeout(function(){
//mutationsをコミット
context.commit('reducePrice');
}, 2000);
}
}
});
ビュー
```vue
<template>
<div id="product-list-one">
<h2>Product List One</h2>
<ul>
<li v-for="product in saleProducts">
<span class="name">{{ product.name }}</span>
<span class="price">£{{ product.price }}</span>
</li>
</ul>
<button v-on:click="reducePrice">Reduce Price</button>
</div>
</template>
メソッドでstateを変更するダメなパターン。使ってはダメ。 strictモードにするとError: [vuex] do not mutate vuex store state outside mutation handlers.のエラーが出る。
<script>
export default {
computed: {
saleProducts() {
//gettersのsaleProductsのデータを取得
return this.$store.getters.saleProducts
},
},
methods: {
reducePrice:function(){
this.$store.state.products.forEach(product => {
product.price -= 1
});
}
}
}
</script>
メソッドでmutationsをコミットするパターン。
<script>
export default {
computed: {
saleProducts() {
return this.$store.getters.saleProducts
},
},
methods: {
reducePrice:function(){
this.$store.commit("reducePrice")
}
}
}
</script>
actionsをdispatchするパターン。
<script>
methods: {
this.$store.dispatch("reducePrice")
}
</script>
payloadを使う場合。
mutations: {
reducePrice: (state, payload)=> {
state.products.forEach(product => {
product.price -= payload
});
}
},
<script>
methods: {
reducePrice:function(amount){
this.$store.commit("reducePrice",amount)
}
}
</script>
引数として4を渡す。2ずつ数字が減る。
<button v-on:click="reducePrice(4)">Reduce Price</button>
同じくpayloadを使う場合。今回はactionsをdispatch。
<script>
methods: {
reducePrice:function(amount){
this.$store.dispatch("reducePrice",amount)
}
}
</script>
mutations: {
reducePrice: (state, payload)=> {
state.products.forEach(product => {
product.price -= payload
});
}
},
actions: {
reducePrice: (context) => {
setTimeout(function(){
context.commit('reducePrice', payload);
}, 2000);
}
}
双方向算出プロパティ
入力された文字に色を変更します。red→赤。blue→青。
色を変えたいタグにstyle属性追加
:style="{color:$store.state.colorCode}"
v-modelでcolorCodeを指定
<input v-model='colorCode' type="text">
stateにcolorCode追加
state: {
colorCode: 'blue'
},
mutationsにsetColorCodeメソッド追加
mutations: {
setColorCode(state,payload) {
state.colorCode = payload
}
},
computedプロパティでsetColorCodeにペイロードを渡してsetColorCodeメソッドをcommit
<script>
computed: {
colorCode: {
get(){
return this.$store.state.colorCode
},
set(colorValue){
this.$store.commit('setColorCode',colorValue)
}
}
}
<script/>
以上です。