一、Action 基本概念

Action 是 Vuex 中用于处理异步操作的方法,它的核心作用是:

  1. 封装异步逻辑(如调用后端接口、延迟执行等);
  2. 异步操作完成后,通过提交 Mutation 来修改 State(不能直接修改 State);
  3. 支持组件通过 dispatch 触发,并返回结果供组件使用。
与 Mutation 的核心区别:
特性 Mutation Action
操作类型 同步操作 异步操作(也可同步,但没必要)
状态修改 直接修改 State 间接通过 commit 调用 Mutation
触发方式 store.commit() store.dispatch()
返回值 无(同步执行完毕) 自动返回 Promise(便于等待结果)

二、Action 处理异步数据的核心机制

Action 处理异步数据的流程可概括为:“组件触发→异步操作→提交 Mutation→更新 State→组件响应”,核心机制体现在以下三个环节:

1. 异步操作的封装与触发

Action 通过 store.dispatch('actionName', payload) 被组件触发,内部可包含任意异步操作(如 fetchsetTimeout 等)。

  • 示例:定义一个获取用户信息的 Action
    // store/index.js
    const store = createStore({
      state: { userInfo: null },
      mutations: {
        SET_USER(state, data) {
          state.userInfo = data; // 同步修改状态
        }
      },
      actions: {
        // 处理异步:获取用户信息
        fetchUserAction(context, userId) { 
          // 异步操作:调用接口
          return fetch(`/api/user/${userId}`)
            .then(res => res.json())
            .then(data => {
              // 异步完成后,提交 Mutation 更新状态
              context.commit('SET_USER', data); 
              return data; // 将数据返回给组件
            });
        }
      }
    });
    
2. 与 Mutation 的协作:异步→同步的桥梁

Action 不能直接修改 State,必须通过 context.commit('mutationName', data) 调用 Mutation,由 Mutation 同步修改 State

  • 这一机制保证了所有状态变更最终通过同步的 Mutation 完成,确保 Vuex DevTools 能追踪每一次状态变化(若 Action 直接修改 State,异步操作会导致状态变更不可追踪)。
3. 结果返回与组件响应

Action 执行异步操作后,会将结果通过 return 传递给组件(返回值会被包装成 Promise),组件可根据结果处理后续逻辑(如渲染数据、提示错误)。

  • 组件中触发 Action 并获取结果:
    // 组件中
    methods: {
      loadUser() {
        // 触发 Action,等待结果
        this.$store.dispatch('fetchUserAction', 123)
          .then(userData => {
            console.log('获取用户成功', userData);
            // 此时 State 已更新,组件会自动渲染
          })
          .catch(error => {
            console.error('获取用户失败', error);
          });
      }
    }
    

三、async/await 在 Action 中的使用

async/await 是 JavaScript 处理异步操作的语法糖,能让 Action 中的异步逻辑更简洁、易读(避免回调地狱)。在 Vuex 中,它是处理异步数据的“最佳实践”。

1. 基本用法:将 Action 定义为 async 函数

在 Action 前添加 async 关键字,内部用 await 等待异步操作完成,代码会按“同步的形式”执行异步逻辑。

actions: {
  // 用 async 定义 Action(自动返回 Promise)
  async fetchUserAction(context, userId) { 
    try {
      // 用 await 等待接口请求完成
      const response = await fetch(`/api/user/${userId}`); 
      const userData = await response.json(); // 继续等待解析 JSON
      
      // 异步完成后提交 Mutation
      context.commit('SET_USER', userData); 
      
      return userData; // 返回数据给组件(会被包装成 Promise.resolve)
    } catch (error) {
      // 捕获错误并返回(会被包装成 Promise.reject)
      console.error('请求失败', error);
      throw error; // 让组件能通过 catch 捕获
    }
  }
}
2. 组件中用 await 等待 Action 结果

组件中触发 Action 时,用 await 等待其返回的 Promise 完成,使组件逻辑更清晰:

// Vue 3 组合式 API 示例
import { onMounted } from 'vue';
import { useStore } from 'vuex';

const store = useStore();

onMounted(async () => {
  try {
    // 用 await 等待 Action 执行完成
    const userData = await store.dispatch('fetchUserAction', 123); 
    console.log('用户数据:', userData); 
    // 此时 State 已更新,可安全使用 store.state.userInfo
  } catch (error) {
    console.error('加载失败:', error);
  }
});
3. 核心价值:解决“异步时序问题”

async/await 让 Action 和组件的异步逻辑摆脱了嵌套回调,更重要的是严格控制了执行顺序

  • 组件中 await store.dispatch(...) 会暂停后续代码,直到 Action 中的异步操作(接口请求)完成、State 更新后才继续执行。
  • 这完美解决了“组件依赖异步数据渲染”的问题(如你之前遇到的 hadSick 数据未加载就被访问的错误)。
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐