vue-19(Vuex异步操作和变更)

news2025/6/6 16:49:05

异步操作和变更

异步操作和变异对于 Vuex 中的状态管理至关重要,尤其是在处理数据获取、API 调用或任何需要时间完成的操作时。正确处理异步操作可以确保应用程序的状态保持一致和可预测。本章将深入探讨异步操作的复杂性、它们与变异的关系以及有效管理它们的最佳实践。

理解异步操作

Vuex 中的操作是提交mutations的函数。它们是 Vuex 存储中更改状态的唯一方式。操作可以包含任意的异步操作。这是操作和变异之间的一个关键区别:mutations必须是同步的。

为什么需要异步操作?

考虑一个需要先从 API 获取数据再更新状态的场景。这个过程本质上就是异步的。你不会希望在等待 API 响应时阻塞主线程。动作允许你在不冻结 UI 的情况下执行这些异步操作。

示例: 从 API 获取用户数据。

// store.js
import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios' // Assuming you're using axios for API calls

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    user: null,
    loading: false,
    error: null
  },
  mutations: {
    SET_USER (state, user) {
      state.user = user
    },
    SET_LOADING (state, loading) {
      state.loading = loading
    },
    SET_ERROR (state, error) {
      state.error = error
    }
  },
  actions: {
    async fetchUser ({ commit }, userId) {
      commit('SET_LOADING', true)
      commit('SET_ERROR', null) // Clear any previous errors
      try {
        const response = await axios.get(`https://api.example.com/users/${userId}`)
        commit('SET_USER', response.data)
      } catch (error) {
        commit('SET_ERROR', error.message)
      } finally {
        commit('SET_LOADING', false)
      }
    }
  },
  getters: {
    isLoading: state => state.loading,
    hasError: state => state.error,
    getUser: state => state.user
  }
})

在这个例子中:

  • fetchUser 是一个异步操作,它接受 context(解构为 { commit })和 userId 作为参数。
  • commit 用于触发变异。
  • SET_LOADINGSET_USERSET_ERROR 是更新状态的mutations。
  • axios.get 用于发起 API 调用。关键字 await 确保操作在继续之前等待 API 调用完成。
  • 一个 try...catch...finally 块用于处理潜在的错误,并确保加载状态始终被重置。

Mutations的作用

Mutations负责 同步 更新状态。Actions 提交Mutations。这种关注点分离对于保持可预测的状态至关重要。你绝不应该在mutations中直接执行异步操作。

为什么Mutations必须是同步的:

Vue Devtools 跟踪应用于状态的所有变更。如果变更具有异步性,将无法准确追踪状态随时间的变化,导致调试变得极其困难。

示例: 上一个示例中的Mutations。

 mutations: {
    SET_USER (state, user) {
      state.user = user
    },
    SET_LOADING (state, loading) {
      state.loading = loading
    },
    SET_ERROR (state, error) {
      state.error = error
    }
  },

这些Mutations是简单且同步的。它们直接更新相应的状态属性。

异步操作和变异的最佳实践

1. 清晰的关注点分离

保持actions负责异步逻辑,而mutations负责同步状态更新。这使您的代码更易于维护和调试。

2. 使用 async/await 以提高清晰度

使用 async/await 比直接使用 .then().catch() 处理 Promise 更容易阅读和理解。

3. 优雅地处理错误

始终在您的操作中包含错误处理,以捕获来自 API 调用或其他异步操作的潜在错误。更新状态以反映错误,允许您的组件向用户显示适当的消息。

4. 管理加载状态

在你的 store 中使用加载状态来指示异步操作正在进行中。这允许你的组件在等待操作完成时显示加载指示器或禁用某些操作。

5. 行动中避免直接修改状态

永远不要在动作中直接修改状态。始终提交一个变异来更新状态。这确保了所有状态变化都能被 Vue Devtools 跟踪。

6. 考虑使用专用 API 服务

对于大型应用,可以考虑创建一个专门的 API 服务来处理所有 API 调用。这可以使你的操作保持清晰,专注于状态管理。

示例: 使用专门的 API 服务。

// api/userService.js
import axios from 'axios';

const API_BASE_URL = 'https://api.example.com';

export default {
  async getUser(userId) {
    try {
      const response = await axios.get(`${API_BASE_URL}/users/${userId}`);
      return response.data;
    } catch (error) {
      throw new Error(error.message);
    }
  }
};

// store.js
import Vue from 'vue'
import Vuex from 'vuex'
import userService from './api/userService'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    user: null,
    loading: false,
    error: null
  },
  mutations: {
    SET_USER (state, user) {
      state.user = user
    },
    SET_LOADING (state, loading) {
      state.loading = loading
    },
    SET_ERROR (state, error) {
      state.error = error
    }
  },
  actions: {
    async fetchUser ({ commit }, userId) {
      commit('SET_LOADING', true)
      commit('SET_ERROR', null)
      try {
        const user = await userService.getUser(userId);
        commit('SET_USER', user)
      } catch (error) {
        commit('SET_ERROR', error.message)
      } finally {
        commit('SET_LOADING', false)
      }
    }
  },
  getters: {
    isLoading: state => state.loading,
    hasError: state => state.error,
    getUser: state => state.user
  }
})

这种方法使 fetchUser 操作更加清晰,更专注于状态管理,而 userService 则处理 API 调用逻辑。

实际案例与演示

示例 1:异步提交表单

考虑一个需要将数据发送到 API 并根据响应更新状态的表单提交场景。

// MyForm.vue
<template>
  <div>
    <form @submit.prevent="handleSubmit">
      <input type="text" v-model="formData.name" placeholder="Name">
      <input type="email" v-model="formData.email" placeholder="Email">
      <button type="submit" :disabled="isLoading">
        {{ isLoading ? 'Submitting...' : 'Submit' }}
      </button>
      <p v-if="error" style="color: red;">{{ error }}</p>
      <p v-if="successMessage" style="color: green;">{{ successMessage }}</p>
    </form>
  </div>
</template>

<script>
import { mapState, mapActions } from 'vuex';

export default {
  data() {
    return {
      formData: {
        name: '',
        email: ''
      }
    };
  },
  computed: {
    ...mapState(['isLoading', 'error', 'successMessage'])
  },
  methods: {
    ...mapActions(['submitForm']),
    async handleSubmit() {
      await this.submitForm(this.formData);
    }
  }
};
</script>
// store.js
import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    isLoading: false,
    error: null,
    successMessage: null
  },
  mutations: {
    SET_LOADING (state, loading) {
      state.isLoading = loading
    },
    SET_ERROR (state, error) {
      state.error = error
    },
    SET_SUCCESS_MESSAGE (state, message) {
      state.successMessage = message
    }
  },
  actions: {
    async submitForm ({ commit }, formData) {
      commit('SET_LOADING', true)
      commit('SET_ERROR', null)
      commit('SET_SUCCESS_MESSAGE', null)
      try {
        const response = await axios.post('https://api.example.com/submit', formData)
        commit('SET_SUCCESS_MESSAGE', 'Form submitted successfully!')
      } catch (error) {
        commit('SET_ERROR', error.message)
      } finally {
        commit('SET_LOADING', false)
      }
    }
  },
  getters: {
    isLoading: state => state.isLoading,
    hasError: state => state.error,
    successMessage: state => state.successMessage
  }
})

在这个例子中:

  • MyForm.vue 组件在表单提交时派发 submitForm 动作。
  • submitForm 动作使用 axios.post 进行 API 调用。
  • SET_LOADINGSET_ERRORSET_SUCCESS_MESSAGE 变更根据 API 响应更新状态。
  • 该组件在表单提交时显示加载指示器,并根据状态显示错误或成功消息。

示例2:异步操作的防抖处理

有时,你可能希望限制异步操作派发的速率。例如,当用户输入时搜索数据。防抖可以帮助防止过多的 API 调用。

// store.js
import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'
import debounce from 'lodash.debounce' // Install lodash: npm install lodash

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    searchResults: [],
    loading: false,
    error: null
  },
  mutations: {
    SET_SEARCH_RESULTS (state, results) {
      state.searchResults = results
    },
    SET_LOADING (state, loading) {
      state.loading = loading
    },
    SET_ERROR (state, error) {
      state.error = error
    }
  },
  actions: {
    async search ({ commit }, query) {
      commit('SET_LOADING', true)
      commit('SET_ERROR', null)
      try {
        const response = await axios.get(`https://api.example.com/search?q=${query}`)
        commit('SET_SEARCH_RESULTS', response.data)
      } catch (error) {
        commit('SET_ERROR', error.message)
      } finally {
        commit('SET_LOADING', false)
      }
    },
    debouncedSearch: debounce(function ({ dispatch }, query) {
      dispatch('search', query)
    }, 500) // Debounce for 500ms
  },
  getters: {
    searchResults: state => state.searchResults,
    isLoading: state => state.loading,
    hasError: state => state.error
  }
})
// SearchComponent.vue
<template>
  <div>
    <input type="text" v-model="searchQuery" @input="handleInput" placeholder="Search...">
    <div v-if="isLoading">Loading...</div>
    <div v-if="error" style="color: red;">{{ error }}</div>
    <ul>
      <li v-for="result in searchResults" :key="result.id">{{ result.name }}</li>
    </ul>
  </div>
</template>

<script>
import { mapState, mapActions } from 'vuex';

export default {
  data() {
    return {
      searchQuery: ''
    };
  },
  computed: {
    ...mapState(['searchResults', 'loading', 'error'])
  },
  methods: {
    ...mapActions(['debouncedSearch']),
    handleInput() {
      this.debouncedSearch(this.searchQuery);
    }
  }
};
</script>

在这个例子中:

  • debouncedSearch 动作使用 lodash.debounce 来限制 search 动作派发的频率。
  • SearchComponent.vue 组件在输入值变化时都会调用 debouncedSearch
  • 这可以防止 search 操作过于频繁地被派发,从而减少 API 调用的次数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2401889.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

专业级PDF转CAD解决方案

PDF 文件因其出色的便携性和稳定性&#xff0c;已成为许多用户的首选格式。但在涉及图像编辑或精细调整时&#xff0c;CAD 文件显然更具优势。 这款 CAD 图纸转换工具&#xff0c;界面清爽、操作直观&#xff0c;是处理图纸文件的理想助手。 它不仅支持不同版本 CAD 文件之间…

STM32 智能小车项目 两路红外循迹模块原理与实战应用详解

在嵌入式系统、机器人、智能设备等场景中&#xff0c;红外反射型光电传感器 被广泛应用于黑白识别、障碍检测、物体计数、位置判断等任务。其中&#xff0c;RPR220 是一款性能稳定、体积小巧的红外光电收发管&#xff0c;本文将详细介绍其工作原理、引脚参数、接线说明以及典型…

SSL安全证书怎么安装?

SSI并非一个标准的、广为人知的安全证书类型&#xff0c;通常网站安装的是SSL/TLS证书&#xff0c;用于加密网站和用户浏览器之间的通信&#xff0c;保障数据传输安全。以下以安装SSL/TLS证书为例&#xff0c;介绍网站安装证书的步骤&#xff1a; 一、证书申请与获取 选择证书…

电子电器架构 --- OTA测试用例分析(上)

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 钝感力的“钝”,不是木讷、迟钝,而是直面困境的韧劲和耐力,是面对外界噪音的通透淡然。 生活中有两种人,一种人格外在意别人的眼光;另一种人无论…

抑郁症患者数据分析

导入数据 import pandas as pd from pyecharts.charts import * from pyecharts import options as optsdfpd.read_csv(YiYuZheng.csv) df.head(1)Patient_nameLabelDateTitleCommunicationsDoctorHospitalFaculty0患者&#xff1a;女 43岁压抑05.28压抑 个人情况&#xff1a;…

Rust 学习笔记:关于智能指针的练习题

Rust 学习笔记&#xff1a;关于智能指针的练习题 Rust 学习笔记&#xff1a;关于智能指针的练习题问题一问题二问题三问题四问题五问题六问题七问题八问题九问题十 Rust 学习笔记&#xff1a;关于智能指针的练习题 参考视频&#xff1a; https://www.bilibili.com/video/BV1S…

6.RV1126-OPENCV 形态学基础膨胀及腐蚀

一.膨胀 1.膨胀原理 膨胀的本质就是通过微积分的转换&#xff0c;将图像A和图形B进行卷积操作合并成一个AB图像。核就是指任意的形状或者大小的图形B。例如下图&#xff0c;将核(也就是图形B)通过微积分卷积&#xff0c;和图像A合并成一个图像AB。 2.特点 图像就会更加明亮 …

筑牢企业网管域安全防线,守护数字核心——联软网管域安全建设解决方案

在当今数字化浪潮中&#xff0c;企业网管域作为数据中心的核心&#xff0c;其安全防护至关重要。一旦网管域遭受攻击&#xff0c;整个网络系统可能陷入瘫痪&#xff0c;给企业带来巨大损失。联软科技凭借其创新的网管域安全建设解决方案&#xff0c;为企业提供了全方位的安全保…

【目标检测】backbone究竟有何关键作用?

backbone的核心在于能为检测提供若干种感受野大小和中心步长的组合&#xff0c;以满足对不同尺度和类别的目标检测。

一个小小的 flask app, 几个小工具,拼凑一下

1. 起因&#xff0c; 目的: 自己的工具&#xff0c;为自己服务。给大家做参考。项目地址&#xff1a; https://github.com/buxuele/flask_utils 2. 先看效果 3. 过程: 一个有趣的 Flask 工具集&#xff1a;从无到有的开发历程 缘起&#xff1a;为什么要做这个项目&#xff…

对抗性提示:大型语言模型的安全性测试

随着大语言模型&#xff08;LLM&#xff09;在虚拟助手、企业平台等现实场景中的深度应用&#xff0c;其智能化与响应速度不断提升。然而能力增长的同时&#xff0c;风险也在加剧。对抗性提示已成为AI安全领域的核心挑战&#xff0c;它揭示了即使最先进的模型也可能被操纵生成有…

好得睐:以品质守味、以科技筑基,传递便捷与品质

据相关数据显示&#xff0c;超市半成品菜是冻品区增长最快品类&#xff0c;再加上商超渠道作为消费者日常高频接触场景&#xff0c;是促进半成品菜成为冻品生鲜消费领域的关键一环。好得睐作为半成品菜领军品牌&#xff0c;其商超渠道布局是连接消费者与品质生活的重要桥梁。商…

docker-部署Nginx以及Tomcat

一、docker 部署Nginx 1、搜索镜像&#xff08;nginx&#xff09; [rootlocalhost /]# docker search nginx Error response from daemon: Get "https://index.docker.io/v1/search?qnginx&n25": dial tcp 192.133.77.133:443: connect: connection refused 简…

蒙特卡罗模拟: 高级应用的思路和实例

蒙特卡罗模拟不仅仅是一种理论练习&#xff0c;它还是一种强大的工具&#xff0c;在金融、医疗保健、物流等领域都有实际应用。本篇文章将探讨高级和复杂的现实生活场景&#xff0c;深入探讨它们的细微差别&#xff0c;并通过详细的解释在 Python 中实现它们。 什么是蒙特卡罗…

数据分析Agent构建

数据分析agent构建 代码资料来源于 Streamline-Analyst&#xff0c;旨在通过该仓库上的代码了解如何使用大语言模型构建数据分析工具&#xff1b; 个人仓库&#xff1a;Data-Analysis-Agent-Tutorial 不同的在于 Data-Analysis-Agent-Tutorial 是在 Streamline-Analyst 基础…

vscode配置lua

官网下载lua得到如下 打开vscode的扩展下载如下三个 打开vscode的此处设置 搜索 executorMap&#xff0c;并添加如下内容

【笔记】MSYS2 的 MINGW64 环境 全面工具链

#工作记录 MSYS2 的 MINGW64 环境&#xff08;mingw64.exe&#xff09;&#xff0c;下面是为该环境准备的最全工具链安装命令&#xff08;包括 C/C、Python、pip/wheel、GTK3/GTK4、PyGObject、Cairo、SDL2 等&#xff09;。 这一环境适用于构建原生 64 位 Windows 应用程序。…

国内头部的UWB企业介绍之品铂科技

一、核心优势与技术实力‌ ‌厘米级定位精度‌ 自主研发的ABELL无线实时定位系统&#xff0c;在复杂工业环境中实现静态与动态场景下‌10-30厘米‌高精度定位&#xff0c;尤其擅长金属设备密集的化工、电力等场景&#xff0c;抗干扰能力行业领先。‌多技术融合能力‌ 支持卫星…

Prj10--8088单板机C语言8259中断测试(2)

1.测试结果 2.全部代码 #include "tiny_stdarg.h" // 使用自定义可变参数实现#define ADR_273 0x0200 #define ADR_244 0x0400 #define LED_PORT 0x800 #define PC16550_THR 0x1f0 #define PC16550_LSR 0x1f5 / //基本的IO操作函数 / char str[]"Hel…

35.x64汇编写法(二)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 本次游戏没法给 内容参考于&#xff1a;微尘网络安全 上一个内容&#xff1a;34.x64汇编写法&#xff08;一&#xff09; 上一个内容写了&#xff0c;汇编调…