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.commitcontext.statecontext.getterscontext.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中使用asyncawait

// 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>

参考:

posted @ 2021-02-03 11:20  gzhjj  阅读(127)  评论(0编辑  收藏  举报