Vuex学习总结 - Actions(6)
4.Vuex核心概念
4.4 Actions
Actions不直接改变Vuex实例中的状态,而是提交mutation
。
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count: 0,
},
mutations: {
increment(state) {
state.count++
},
},
actions: {
increment(context) {
context.commit('increment')
},
},
})
<template>
<div>
<button @click="increment">加一</button> {{count}}
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
name: "Counter2",
computed: {
...mapState(['count']),
},
methods: {
increment() {
this.$store.dispatch('increment')
},
}
}
</script>
Action处理程序会收到一个上下文对象,该对象与Vuex实例有相同的方法和属性。
因此,您可以调用context.commit
、context.state
、context.getters
、context.dispatch
。
使用解构来简化代码。
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count: 0,
},
mutations: {
increment(state) {
state.count++
},
},
actions: {
increment({commit}) {
commit('increment')
},
},
})
注意到这里在组件中使用this.$store.dispatch('increment')
来触发Action,在Action中提交mutation
。
为什么不在组件中直接提交mutation
?在组件中可以直接提交mutation
,但mutation
必须是同步的,如果要执行异步操作,就要在Action里面执行。
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count: 0,
},
mutations: {
increment(state) {
state.count++
},
},
actions: {
increment({commit}) {
commit('increment')
},
incrementAsync({ commit }) {
setTimeout(() => {
commit('increment')
}, 1000)
},
},
})
<template>
<div>
<button @click="increment">加一</button> {{count}}
<button @click="incrementAsync">异步加一</button> {{count}}
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
name: "Counter2",
computed: {
...mapState(['count']),
},
methods: {
increment() {
this.$store.dispatch('increment')
},
incrementAsync() {
this.$store.dispatch('incrementAsync')
},
}
}
</script>
在组件中调用dispatch
时还可以这样写:
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count: 0,
},
mutations: {
incrementBy(state, payload) {
state.count += payload.amount
},
},
actions: {
incrementAsync({ commit }, payload) {
setTimeout(() => {
commit('incrementBy', payload)
}, 1000)
},
})
<template>
<div>
<button @click="incrementAsync">异步加十</button> {{count}}
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
name: "Counter2",
computed: {
...mapState(['count']),
},
methods: {
incrementAsync() {
this.$store.dispatch('incrementAsync', {amount: 10})
// this.$store.dispatch({type: 'incrementAsync', amount: 10})
},
}
}
</script>
使用mapActions
。
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count: 0,
},
mutations: {
increment(state) {
state.count++
},
},
actions: {
increment({commit}) {
commit('increment')
},
},
})
<template>
<div>
<button @click="increment">加一</button> {{count}}
<button @click="add">加一</button> {{count}}
</div>
</template>
<script>
import {mapState, mapActions} from 'vuex'
export default {
name: "Counter2",
computed: {
...mapState(['count']),
},
methods: {
...mapActions(['increment']),
...mapActions({
add: 'increment'
})
}
}
</script>
处理异步流。
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count: 0,
},
mutations: {
increment(state) {
state.count++
},
},
actions: {
actionA ({commit}) {
return new Promise((resolve) => {
setTimeout(() => {
commit('increment')
resolve()
}, 1000)
})
},
},
})
<template>
<div>
<button @click="increment">加一</button> {{count}}
</div>
</template>
<script>
import {
mapState,
} from 'vuex'
export default {
name: "Counter2",
computed: {
...mapState(['count']),
},
methods: {
increment() {
this.$store.dispatch('actionA').then(() => {
console.log('执行成功!')
})
},
}
}
</script>
在一个Action中触发另一个Action。
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count: 0,
},
mutations: {
increment(state) {
state.count++
},
incrementBy(state, payload) {
state.count += payload.amount
},
},
actions: {
actionA ({commit}) {
return new Promise((resolve) => {
setTimeout(() => {
commit('increment')
resolve()
}, 1000)
})
},
actionB({dispatch, commit}) {
return dispatch('actionA').then(() => {
commit('incrementBy', {amount: 10})
})
},
},
})
<template>
<div>
<button @click="increment">加一</button> {{count}}
</div>
</template>
<script>
import {
mapState,
} from 'vuex'
export default {
name: "Counter2",
computed: {
...mapState(['count']),
},
methods: {
increment() {
this.$store.dispatch('actionB').then(() => {
console.log('执行成功!')
})
},
}
}
</script>
在Action中使用async
和await
。
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
career: {
id: '',
name: '',
},
certificateType: {
id: '',
name: '',
},
},
mutations: {
getCareerById(state, payload) {
state.career = payload
},
getCertificateType(state, payload) {
state.certificateType = payload
},
},
actions: {
async actionC({commit}, payload) {
let career = await axios.get(`http://192.168.3.117:8001/insurance/career/getCareerById/${payload.id}`);
commit('getCareerById', career.data.data.career)
},
async actionD({dispatch, commit}, payload) {
await dispatch('actionC', {id: 1})
let certificateType = await axios.get(`http://192.168.3.117:8001/insurance/certificate-type/getCertificateTypeById/${payload.id}`);
commit('getCertificateType', certificateType.data.data.certificateType)
},
},
})
<template>
<div>
<button @click="getData">加载数据</button>
<br/>
职业:{{career.name}}
<br/>
证件类型:{{certificateType.name}}
<!--<br/>-->
<!--职业:{{this.$store.state.career.name}}-->
<!--<br/>-->
<!--证件类型:{{this.$store.state.certificateType.name}}-->
</div>
</template>
<script>
import {
mapState,
} from 'vuex'
export default {
name: "Asynchronous",
computed: {
...mapState(['career', 'certificateType']),
},
methods: {
getData() {
this.$store.dispatch('actionD', {id: 1}).then(() => {
console.log('加载成功!')
})
},
},
}
</script>
参考: