状态管理Vuex 之 Action

  • 原创
  • 作者:程序员三丰
  • 发布时间:2021-08-03 16:10
  • 浏览量:384
action 类似于 mutation ,不同在于 action 可以包含任意异步操作。

状态管理Vuex 之 Action

Action 介绍

  • action 类似于 mutation ,不同在于:

    • action 提交的是 mutation ,通过 mutation 来改变 state,而不是直接更改状态。
    • action 可以包含任意异步操作。

Action 注册

  • action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,但context 对象不是 store 实例本身,因此可以操作类似 store 的操作:

    • 调用 context.commit 提交一个 Mutation。
    • 通过 context.state 获取 state。
    • 通过 context.getters 获取 getters。
  • 代码实例

    /* 文件路径:store/index.js */
    import Vue from 'vue'
    import Vuex from 'vuex'
    
    Vue.use(Vuex)
    
    const store = new Vuex.Store({
        state: {
            count: 1
        },
        mutations: {
            add(state) {
                // 变更状态
                state.count += 1
            }
        },
        actions: {
            addCountAction (context) {
                context.commit('add')
            }
        }
    })
    
    export default store
    

分发 Action

  • 通过 store.dispatch 方法触发

    <!-- 页面路径:pages/index/index.vue -->
    <template>
        <view>
            <view>数量:{{count}}</view>
            <butto @click="add">增加</butto>
        </view>
    </template>
    <script>
        import store from '@/store/index.js'
        export default {
            computed: {
                count() {
                    return this.$store.state.count
                }
            },
            methods: {
                add() {
                    store.dispatch('addCountAction')
                }
            }
        }
    </script>
    
  • 支持以荷载形式分发

    /* 文件路径:store/index.js */
    import Vue from 'vue'
    import Vuex from 'vuex'
    
    Vue.use(Vuex)
    
    const store = new Vuex.Store({
        state: {
            count: 1
        },
        mutations: {
            add(state, payload) {
                state.count += payload.amount
            }
        },
        actions: {
            addCountAction (context, payload) {
                context.commit('add', payload)
            }
        }
    })
    
    export default store
    
    <!-- 页面路径:pages/index/index.vue -->
    <template>
        <view>
            <view>数量:{{count}}</view>
            <button @click="add"> 增加</button>
        </view>
    </template>
    <script>
        import store from '@/store/index.js'
        export default {
            computed: {
                count() {
                    return this.$store.state.count
                }
            },
            methods: {
                add() {
                    // 以荷载的方式分发
                    store.dispatch('addCountAction', {amount: 100})
                }
            }
        }
    </script>
    
  • 支持以对象形式分发。

    // 代码片段
    methods: {
        add() {
            // 以对象形式分发
            store.dispatch({
                type: 'addCountAction',
                amount: 100
            })
        }
    }
    
  • 通过 mapActions 辅助函数分发

    <!-- 页面路径:pages/index/index.vue -->
    <template>
        <view>
            <view>数量:{{count}}</view>
            <button @click="add"> 增加</button>
        </view>
    </template>
    <script>
        import {mapActions} from 'vuex'
        export default {
            computed: {
                count() {
                    return this.$store.state.count
                }
            },
            methods: {
                ...mapActions([
                    'addCountAction'
                ])
            }
        }
    </script>
    
    • mapActions 支持传入参数(荷载)

      // store/index.js 代码片段
      state: {
          count: 0
      }
      mutations: {
          addParam(state, n) {
              state.count += n
          },
      }
      actions: {
          addCountParamAction(context, n) {
              context.commit('addParam', n)
          },
      }
      
      //组件页面代码片段
      <template>
          <view>
              <view>数量:{{count}}</view>
              <button @click="addCountParamAction(11)">增加</button>
          </view>
      </template>
      <script>
         // .....
          methods: {
              ...mapActions([
                  'addCountParamAction'
              ])
          }
         // .....
      </script>
      
    • mapActions 支持传递一个对象

      //代码片段
      methods: {
          ...mapActions({
              addCount: 'addCountParamAction'
          })
      }
      

actions 可以执行任意的同步和异步操作

  • 在 action 内部执行异步操作

    // 代码片段
    actions: {
       // 参数解构
       addCountActionAsync({commit}){
           console.log('addCountActionAsync in ...')
    
           //在执行累加的时候,会等待3秒才执行
           setTimeout(function() {
               commit('add')
           }, 3000)
    
           console.log('addCountActionAsync out ...')
       }
    }
    

组合 Action

  • 问题抛出

    • action 通常是异步的,那么如何知道 action 什么时候结束呢?
    • 如何才能组合多个 action,以处理更加复杂的异步流程呢?
  • 问题分析

    • 首先,要明白 store.dispatch 可以处理被触发的 action 的处理函数返回的 Promise

      //代码片段
      actions: {
          actionA({commit}) {
              return new Promise( (resolve, reject) => {
                  setTimeout( () => {
                      commit('somtMutation')
                      resolve()
                  }, 1000)
              })
          },
          ActionB({dispatch, commit}) {
              return dispatch('actionA').then( () => {
                  commit('someOtherMutation')
              } )
          }
      }
      
  • 并且,store.dispatch 仍旧返回 Promise

    store.dispatch('ActionA').then( () => {
        //  ..
    })
    
  • 利用 async / await 组合 action

    //假设 getData() 和 getOtherData 返回的是 Promise
    actions: {
        async actionA({commit}) {
            commit('getData', await getData())
        },
        async actionB({dispatch, commit}) {
            await dispatch('actionA') //等待 actionA 完成
            commit('getOtherData', await getOtherData())
        }
    }
    

    提示:组合Action还没实践过,以上整理内容,仅供参考。

声明:本文为原创文章,51blog.xyz和作者拥有版权,如需转载,请注明来源于51blog.xyz并保留原文链接:https://www.51blog.xyz/article/21

文章归档

强烈推荐的PHP全栈开发后台管理系统
buildadmin logo
Thinkphp8 Vue3 Element PLus TypeScript Vite Pinia

🔥BuildAdmin是一个永久免费开源,无需授权即可商业使用,且使用了流行技术栈快速创建商业级后台管理系统。

推荐文章

热门标签

PHP ThinkPHP ThinkPHP5.1 Go Mysql Mysql5.7 Redis Linux CentOS7 Git HTML CSS CSS3 Javascript JQuery Vue LayUI VMware Uniapp 微信小程序 docker wiki Confluence7 学习笔记 uView ES6 Ant Design Pro of Vue React ThinkPHP6.0 chrome 扩展 翻译工具 Nuxt SSR 服务端渲染 scrollreveal.js ThinkPHP8.0 Mac webman 跨域CORS vscode GitHub ECharts Canvas vue3 three.js 微信支付 PHP全栈开发 Python AI 人工智能 AI辅助 工作经验 实战笔记