Vuex コアコンセプト アクション編
今回のお題は、こちらです。
https://vuex.vuejs.org/ja/actions.html
アクション
- store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
count: 51
},
getters: {
},
mutations: {
increment: (state) => {
state.count ++
},
decrement: state => state.count--,
},
actions: {
increment ({ commit, state, getters }) {
commit('increment')
}
// increment (context) {
// context.commit('increment')
// }
}
})
export default store
store.dispatch('increment')
console.log(store.state.count)
- context は、state, getters, commit の大元とのこと。
- actions -> mutations 数珠つなぎになっていますね。
-
{ commit, state, getters }
は, contextを分割代入しています。- 分割代入で書いたほうがいいですね。
- 引数の順番は、ありません。
- stateも引っ張ってこれますが、ここでの使用はread onlyです。
アクションのディスパッチ
- store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
count: 51
},
getters: {
},
mutations: {
increment: (state) => {
state.count ++
},
decrement: state => state.count--,
},
actions: {
increment ({ commit, state, getters }) {
setTimeout( () => {
commit('increment')
}, 1000)
}
}
})
export default store
store.dispatch('increment')
console.log(store.state.count)
- 非同期処理をしたい場合は、mutationsでやらずに、actionsでしなさいとのこと。
- actionsをつかうなら、mutationsは、actionsで加工をしたデータの書き込み処理専用みたいな感じでしょうか。
オブジェクト形式とペイロード形式
- store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
count: 51
},
getters: {
},
mutations: {
increment: (state, n) => {
state.count = state.count + n
},
decrement: state => state.count--,
},
actions: {
increment ({ commit }, { amount }) {
commit('increment', amount)
// increment ({ commit }, payload) {
// commit('increment', payload.amount)
}
// increment (context, payload) {
// context.commit('increment', payload.amount)
// }
}
})
export default store
store.dispatch('increment', {
amount: 10
})
console.log('store.state.count + 10 :',store.state.count)
store.dispatch({
type: 'increment',
amount: 20
})
console.log('store.state.count + 20 :',store.state.count)
- payloadも分割代入できますね。
- dispatchも、オブジェクト形式を推奨とのこと。
- type: を使うかはお好みです。
より実践的な例
- 読み物です。
コンポーネント内でのアクションのディスパッチ
- store.js
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
count: 51
},
getters: {
},
mutations: {
increment: (state, n) => {
state.count = state.count + n
},
decrement: state => state.count--,
},
actions: {
increment: ({ commit } ) => {
commit('increment', 10)
}
}
})
export default store
// store.dispatch('increment', {
// amount: 10
// })
// console.log('store.state.count + 10 :',store.state.count)
// store.dispatch({
// type: 'increment',
// amount: 20
// })
// console.log('store.state.count + 20 :',store.state.count)
- App.vue
<template lang="pug">
#app
Counter
</template>
<script>
import Vue from 'vue'
import store from './store.js'
import { mapState } from 'vuex'
import { mapGetters } from 'vuex'
import { mapActions } from 'vuex'
const Counter = {
template: `<div>
<p> {{ count }}</p>
<button @click="incrementMethods()">+10 buttton</button>
<button @click="increment()">+10 buttton</button>
<button @click="clickAction">+20 buttton</button>
<button @click="add()">+10 buttton</button>
</div>`,
data: () => ({
localCount: 999,
}),
methods: {
incrementMethods() {
return this.$store.dispatch('increment')
},
clickAction () {
this.incrementBy({
amount: 20
})
/* this.$store.dispatch('incrementBy', {
amount: 20
}) */
},
...mapActions([
'increment',
'incrementBy',
]),
...mapActions({
add: 'increment'
})
},
computed: {
storecount () {
},
...mapGetters([
]),
...mapState({
count: 'count',
})
}
}
export default {
name: 'app',
store,
components: {
Counter
},
data: () => ({
}),
}
</script>
- コンポーネント内での、actionsのdispatchの使い方ですね。
- いろんなやり方がありますが、mapActions をうまく使いたいですね。
アクションを構成する
- store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
count: 51
},
getters: {
},
mutations: {
someMutation: (state) => {
state.count +=1
},
increment: (state, n) => {
state.count = state.count + n
},
decrement: state => state.count--,
},
actions: {
actionA ({ commit }) {
return new Promise((resolve, reject) => {
setTimeout(() => {
commit('someMutation')
resolve('success')
reject('fail!')
}, 1000)
})
},
increment: ({ commit } ) => {
commit('increment', 10)
},
incrementBy: ({ commit }, { amount } ) => {
commit('increment', amount)
}
}
})
export default store
store.dispatch('actionA')
.then((result) => { console.log(result)})
.catch(result => console.log(result))
非同期処理が終わったときの通知の仕方ですね。
store.js
const store = new Vuex.Store({
state: {
count: 51
},
getters: {
},
mutations: {
someMutation: (state) => {
state.count +=1
},
someOtherMutation: (state) => {
state.count +=2
},
increment: (state, n) => {
state.count = state.count + n
},
decrement: state => state.count--,
},
actions: {
actionB ({ dispatch, commit }) {
return dispatch('actionA').then(() => {
commit('someOtherMutation')
})
},
actionA ({ commit }) {
return new Promise((resolve, reject) => {
setTimeout(() => {
commit('someMutation')
resolve('success')
reject('fail!')
}, 1000)
})
},
increment: ({ commit } ) => {
commit('increment', 10)
},
incrementBy: ({ commit }, { amount } ) => {
commit('increment', amount)
}
}
})
export default store
store.dispatch('actionB')
.then((result) => { console.log(result)})
.catch(result => console.log(result))
actionBは、actionAが成功したら、someOtherMutation が実行されます。
async は、勉強不足でうまく動かずです。
また、更新がんばります。
今回は、これで終了です。