Vue 之 Vuex(5)actions 的使用

Action 类似于 mutation,不同在于:

  • Action 提交的是 mutation,而不是直接变更状态。
  • Action 可以包含任意异步操作。
  • mutation 是同步事务

Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.statecontext.getters 来获取 state 和 getters。当我们在之后介绍到 Modules 时,你就知道 context 对象为什么不是 store 实例本身了。

<!DOCTYPE html>
<html lang="en" xmlns="">
<head>
    <meta charset="UTF-8">
    <title>Vuex:actions 的使用</title>
</head>
<body>
<div id="app">
    <button-counter></button-counter>
</div>

<script src="vuex.js"></script>
<script src="vue.js"></script>
<script>
  Vue.component('ButtonCounter', {
    computed: {
      ...Vuex.mapState([
        'count'
      ])
    },
    methods: {
      increment() {
        // 使用 dispatch 触发 actions 下的方法
        this.$store.dispatch('increment')
      },
      ...Vuex.mapActions([
        // 将 `this.incrementAsync(timeout)` 映射为 `this.$store.dispatch('incrementAsync', timeout)`
        'incrementAsync'
      ]),
      ...Vuex.mapActions({
        // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
        add: 'increment'
      })
    },
    template: `
      <div>
      <button @click="increment">increment:You clicked me {{ count }} times.</button><hr>
      <button @click="incrementAsync(1000)">incrementAsync:You clicked me {{ count }} times.</button>
      </div>
    `
  })

  // 创建Vuex容器
  const store = new Vuex.Store({
    state: {
      count: 0
    },
    mutations: {
      increment(state) {
        state.count++
      }
    },
    // 异步操作
    actions: {
      // increment(context) {
      //   context.commit('increment')
      // },
      // ES6 简化写法,以上面作用相同
      increment({commit}) {
        commit('increment')
      },
      // 带有载荷 timeout,载荷可以是 对象,使用方法与 mutations 相同
      incrementAsync({commit}, timeout) {
        setTimeout(() => {
          commit('increment')
        }, timeout)
      }
    }
  })

  new Vue({
    el: '#app',
    store
  });

</script>
</body>
</html>

复杂一点的例子:

store.js:单独配置 Vuex 容器

import Vue from 'vue'
import Vuex from 'vuex'
import {types} from './mutation-types'
import shop from './shop'

Vue.use(Vuex)

// 创建Vuex容器
export default new Vuex.Store({
  state: {
    cart: {
      added: [] // 购物车添加的物品列表
    }
  },
  mutations: {
    [types.CHECKOUT_REQUEST](state) {
      console.log('清空购物车 ' + state)
    },
    [types.CHECKOUT_SUCCESS](state) {
      console.log('购物成功时调用 ' + state)
    },
    [types.CHECKOUT_FAILURE](state, savedCartItems) {
      console.log('购物失败时调用 ' + state)
      console.log(savedCartItems)
    },
  },
  // 异步操作
  actions: {
    checkout({commit, state}, products) {
      // 把当前购物车的物品备份起来
      const savedCartItems = [...state.cart.added]
      // 发出结账请求,然后乐观地清空购物车
      commit(types.CHECKOUT_REQUEST)
      // 购物 API 接受一个成功回调和一个失败回调
      setTimeout(() => {
        shop.buyProducts(
          products, // 购买的产品
          // 成功操作
          () => commit(types.CHECKOUT_SUCCESS),
          // 失败操作
          () => commit(types.CHECKOUT_FAILURE, savedCartItems)
        )
      }, 2000)
    }
  }
})

mutation-types.js:mutations 方法名称统一管理,有助于项目团队对 state 所包含的 mutations 一目了然

export const types = {
  CHECKOUT_REQUEST: 'checkoutRequest',
  CHECKOUT_SUCCESS: 'checkoutSuccess',
  CHECKOUT_FAILURE: 'checkoutFailure',
}

shop:购物类的定义文件

export default function shop() {
  // 购买商品 API
  this.buyProducts = function (products, success, failure) {
    console.log(products) // 购买的产品
    console.log(success) // 操作成功时调用
    console.log(failure) // 操作失败时调用
  };
}

调用其他异步方法:

actions: {
  actionA ({ commit }) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        commit('someMutation')
        resolve()
      }, 1000)
    })
  },
  actionB ({ dispatch, commit }) {
    return dispatch('actionA').then(() => {
      commit('someOtherMutation')
    })
  },
}

配合 async/await 使用:

// 假设 getData() 和 getOtherData() 返回的是 Promise

actions: {
  async actionC ({ commit }) {
    commit('gotData', await getData())
  },
  async actionD ({ dispatch, commit }) {
    await dispatch('actionC') // 等待 actionA 完成
    commit('gotOtherData', await getOtherData())
  }
}
### 如何在 Vue使用 Vuex 进行状态管理 #### 安装与配置 为了在 Vue 应用程序中集成 Vuex,首先需要安装 Vuex。对于 Vue 2.x 版本的应用来说,可以在 `src/store/index.js` 文件中完成基本的设置[^3]。 ```javascript import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) const store = new Vuex.Store({ state: { // 存储全局的状态数据 }, mutations: { // 修改state的方法 }, actions: { // 处理异步操作并提交mutations }, getters: { // 计算属性,基于state返回新状态 } }) export default store ``` 接着,在项目的入口文件(通常是 main.js 或 app.js)引入创建好的 store 实例,并将其挂载至 Vue 实例: ```javascript import Vue from 'vue' import App from './App.vue' import store from './store' new Vue({ render: h => h(App), store, }).$mount('#app') ``` #### 核心概念解析 - **State**: 表示应用程序的整体状态树,即所有组件共享的数据源。 - **Mutations**: 提交更改请求给 Store 的唯一方式;必须是同步事务。 - **Actions**: 类似于 mutation,不同之处在于 action 不直接改变状态而是可以包含任意异步操作最后通过 commit 方法调用 mutation 更新状态。 - **Getters**: 可以认为是从 store 的 state 中派生出来的状态,类似于 Vue 组件中的 computed 属性[^1]。 #### 使用组合式API简化代码结构 随着 Vue 3 发布以及 Composition API 的推出,官方建议采用更为灵活的方式编写逻辑——setup 函数配合组合式 API (Composition API),比如利用 `useStore()` 钩子替代传统的 mapXxx 辅助函数来获取或更新状态[^2]。 ```typescript // 在 setup 函数内部 import { defineComponent } from 'vue'; import { useStore } from 'vuex'; export default defineComponent({ name: 'MyComponent', setup() { const store = useStore(); function incrementCounter() { store.commit('increment'); } return { count: computed(() => store.getters.count), // 获取 getter incrementCounter // 返回方法供模板调用 }; } }); ``` #### 模块化设计提升可维护性 考虑到大型应用可能面临的复杂度增加问题,Vuex 支持将 store 切分为多个模块(Module)[^5]。每个模块都可以独立地定义自身的 state、mutation、action 和 getter,甚至支持嵌套子模块,从而有效降低整体耦合程度,提高系统的扩展性和清晰度。 ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值