vue3 + elementPlus 封装hook,检测form表单数据修改变更;示例 script setup 语法

  • 原文:https://mp.weixin.qq.com/s/gCuqKskp-KBxdClxcpwFqw
  • 原文:https://mp.weixin.qq.com/s/gCuqKskp-KBxdClxcpwFqw
  • 原文:https://mp.weixin.qq.com/s/gCuqKskp-KBxdClxcpwFqw

原文:https://mp.weixin.qq.com/s/gCuqKskp-KBxdClxcpwFqw

运行系统:windows 10

运行终端:Goodle Chrome(谷歌) 浏览器

开发框架:vue3 + elementPlus

开发环境:nodeJS v20.17.0

nvm 版本:1.1.12

前言:

目前要实现这样一个功能,修改了form表单数据后,检测form表单数据修改前,修改后的变化,记录下来,传递给后端,后端偷懒让前端来做,花了一天时间,缝缝补补优化后,没有什么问题,记录一下
封装hooks组件,组件路径 hooks/formChangeTracker.ts


// 引入 Vue 的响应式 API
import { ref, reactive, watch } from "vue";
/*** 表单修改追踪 Hook(支持动态模块)* @param {Object} initialFormData - 初始表单数据结构,示例: { module1: { field1: value1 }, module2: { field2: value2 } }* @param {Object} [options={}] - 配置选项* @param {Boolean} [options.autoDetect=false] - 是否自动检测变化,设置为true时会自动监听表单变化* @param {Object} [options.fieldLabels={}] - 字段标签映射,结构: {模块名: {字段名: 显示标签}}* @param {Object} [options.moduleLabels={}] - 模块标签映射,结构: {模块名: 显示标签}* @returns {Object} 包含表单数据和操作方法的对象*/
export function useFormChangeTracker(initialFormData, options = {}) {// 解构配置选项,设置默认值const { autoDetect = false, fieldLabels = {}, moduleLabels = {} } = options;// 存储后端原始数据(使用 ref 保持响应式,深拷贝初始数据避免引用问题)// 这里使用ref而不是reactive是因为我们可能需要完全替换整个后端数据const backendData = ref(JSON.parse(JSON.stringify(initialFormData)));// 响应式表单数据(使用 reactive 创建响应式对象,用于绑定表单)// 使用reactive是因为表单数据通常是嵌套对象,reactive对嵌套响应式更友好const formContent = reactive(JSON.parse(JSON.stringify(initialFormData)) // 深拷贝初始数据);// 变化记录(使用 ref 保持响应式)// 使用ref是因为我们可能会完全替换整个changes对象const changes = ref({oldValue: {}, // 模块级别的旧值 {模块名: {字段名: 值}}newValue: {}, // 模块级别的新值 {模块名: {字段名: 值}}changedFields: [], // 变化的字段列表,每个元素包含字段详情和单独的新旧值changeType: {} // 记录哪些模块发生了变化 {模块名: boolean}});// 是否有变化的标记(使用 ref 保持响应式)const hasChanges = ref(false);/*** 从后端加载数据并重置表单* @param {Object} data - 后端返回的数据,结构应与initialFormData一致* @example * loadBackendData({*   userInfo: { name: 'John', age: 30 },*   contactInfo: { email: 'john@example.com' }* })*/const loadBackendData = (data) => {// 更新后端原始数据(深拷贝避免引用问题)backendData.value = JSON.parse(JSON.stringify(data));// 重置表单数据(将后端数据同步到表单)Object.keys(data).forEach(module => {if (formContent[module]) {// 只更新已存在的模块// 使用Object.assign而不是直接赋值,保留表单的响应性Object.assign(formContent[module], data[module]);}});// 重置变化记录resetForm();};/*** 检查模块是否有效(关键字段一致)* @param {String} module - 要检查的模块名* @returns {Boolean} 是否有效模块* @description * 有效的模块必须同时存在于:* 1. 后端数据(backendData)* 2. 字段标签配置(fieldLabels)* 3. 模块标签配置(moduleLabels)*/const isValidModule = (module) => {return (backendData.value.hasOwnProperty(module) && // 有后端数据Object.keys(fieldLabels).includes(module) && // 有字段标签配置Object.keys(moduleLabels).includes(module) // 有模块标签配置);};/*** 检测表单变化并更新 changes 数据* @returns {Object} 包含所有变化的字段信息,结构:* {*   oldValue: {模块: {字段: 旧值}},*   newValue: {模块: {字段: 新值}},*   changedFields: [{*     module: 模块名,*     field: 字段名,*     label: 字段显示标签,*     moduleLabel: 模块显示标签,*     oldValue: 旧值,*     newValue: 新值*   }],*   changeType: {模块名: boolean}* }*/const checkChanges = () => {const changedFields = []; // 存储所有变化的字段详情const oldValue = {}; // 存储模块级别的旧值const newValue = {}; // 存储模块级别的新值const changeType = {}; // 记录哪些模块发生了变化// 遍历表单中的所有模块Object.keys(formContent).forEach(module => {// 跳过无效模块(配置不完整的模块)if (!isValidModule(module)) {console.warn(`模块 ${module} 缺少必要的配置,跳过检测`);return; // 继续下一个模块}let moduleChanged = false; // 标记当前模块是否有变化const moduleOldValues = {}; // 存储当前模块的旧值const moduleNewValues = {}; // 存储当前模块的新值// 遍历模块中的所有字段Object.keys(formContent[module]).forEach(field => {// 使用严格不等于比较当前表单值和后端原始值if (formContent[module][field] !== backendData.value[module][field]) {moduleChanged = true; // 标记模块有变化// 记录字段级别的旧值和新值moduleOldValues[field] = backendData.value[module][field];moduleNewValues[field] = formContent[module][field];// 记录变化的字段详情(包含字段级新旧值)changedFields.push({module, // 模块名field, // 字段名label: fieldLabels[module]?.[field] || field, // 显示标签(优先使用配置的标签)moduleLabel: moduleLabels[module] || module, // 模块显示标签oldValue: backendData.value[module][field], // 字段旧值newValue: formContent[module][field] // 字段新值});}});// 如果当前模块有变化,记录模块级别的变化if (moduleChanged) {oldValue[module] = moduleOldValues;newValue[module] = moduleNewValues;changeType[module] = true;}});// 更新响应式数据changes.value = {oldValue,newValue,changedFields,changeType};// 更新是否有变化的标记(根据变化字段数量判断)hasChanges.value = changedFields.length > 0;return changes.value;};/*** 重置表单到初始状态(后端数据状态)* @description* 1. 将表单数据恢复为后端原始数据* 2. 清空所有变化记录* 3. 重置hasChanges标志*/const resetForm = () => {// 遍历所有后端数据模块Object.keys(backendData.value).forEach(module => {// 只重置表单中存在的模块if (formContent[module]) {// 将表单数据重置为后端原始数据// 使用Object.assign保留响应性Object.assign(formContent[module], backendData.value[module]);}});// 清空变化记录changes.value = {oldValue: {},newValue: {},changedFields: [],changeType: {}};// 重置变化标记hasChanges.value = false;};// 如果启用自动检测,设置深度监听if (autoDetect) {watch(// 监听表单数据(使用深拷贝确保能检测到嵌套变化)() => JSON.parse(JSON.stringify(formContent)),// 变化时执行检测() => checkChanges(),// 深度监听选项{ deep: true });}// 返回供组件使用的方法和数据return {formContent, // 响应式表单数据(用于表单绑定)changes, // 变化记录(包含新旧值)hasChanges, // 是否有变化的标记checkChanges, // 手动检测变化的方法resetForm, // 重置表单的方法loadBackendData, // 加载后端数据的方法isValidModule // 检查模块是否有效的方法};
}

功能说明
这个 useFormChangeTracker Hook 主要提供以下功能:

表单数据管理:维护表单的当前状态和原始状态

变化追踪:检测表单字段的修改并记录新旧值

模块化支持:支持按模块组织表单数据

自动/手动检测:可配置自动检测变化或手动触发检测

重置功能:可以将表单重置为原始状态

数据加载:可以从后端加载新数据

核心实现
使用 Vue 的 ref 和 reactive 创建响应式数据

通过深拷贝确保数据独立性(避免引用问题)

提供 checkChanges 方法比较当前表单值与原始值的差异

支持自动监听表单变化(通过 watch 实现)

记录详细的变更信息,包括字段级和模块级的变化

使用示例 :script setup 语法


<template><!-- 表单容器 --><div class="form-container"><!-- 用户信息模块 --><div class="form-section"><h3>用户信息</h3><!-- 姓名字段 --><div class="form-field"><label>姓名:</label><!-- 双向绑定到 formContent.userInfo.name --><input v-model="formContent.userInfo.name" /><!-- 如果姓名有修改,显示修改指示器 --><span v-if="changes.changeType.userInfo?.name" class="change-indicator">(已修改)</span></div><!-- 年龄字段 --><div class="form-field"><label>年龄:</label><!-- 使用.number修饰符确保绑定为数字类型 --><input v-model.number="formContent.userInfo.age" type="number" /><span v-if="changes.changeType.userInfo?.age" class="change-indicator">(已修改)</span></div></div><!-- 联系信息模块 --><div class="form-section"><h3>联系信息</h3><!-- 邮箱字段 --><div class="form-field"><label>电子邮箱:</label><input v-model="formContent.contactInfo.email" /><span v-if="changes.changeType.contactInfo?.email" class="change-indicator">(已修改)</span></div><!-- 电话字段 --><div class="form-field"><label>联系电话:</label><input v-model="formContent.contactInfo.phone" /><span v-if="changes.changeType.contactInfo?.phone" class="change-indicator">(已修改)</span></div></div><!-- 操作按钮区域 --><div class="action-buttons"><!-- 加载数据按钮 --><button @click="loadDataFromBackend" class="btn btn-load">加载数据</button><!-- 检查变更按钮(autoDetect为true时通常不需要手动检查) --><button @click="checkChanges" :disabled="!hasChanges" class="btn btn-check">检查变更</button><!-- 提交变更按钮 --><button @click="submitChanges" :disabled="!hasChanges" class="btn btn-submit">提交变更</button><!-- 重置表单按钮 --><button @click="resetForm" :disabled="!hasChanges" class="btn btn-reset">重置表单</button></div><!-- 变更信息展示区域(只有有变更时才显示) --><div v-if="hasChanges" class="changes-panel"><h3>变更记录</h3><ul class="changes-list"><!-- 遍历所有变更的字段 --><li v-for="(change, index) in changes.changedFields" :key="index" class="change-item"><!-- 显示模块标签 - 字段标签 --><strong>{{ change.moduleLabel }} - {{ change.label }}:</strong><!-- 显示旧值(带删除线) -->"<span class="old-value">{{ change.oldValue }}</span>" <!-- 显示新值(加粗) -->修改为 "<span class="new-value">{{ change.newValue }}</span>"</li></ul><!-- 变更统计 --><div class="changes-summary">{{ changes.changedFields.length }} 处变更</div></div></div>
</template><script setup>
// 引入需要的Vue API和自定义Hook
import { useFormChangeTracker } from '@/hooks/useFormChangeTracker';/*** 初始表单数据结构* 采用模块化设计,每个模块包含多个字段*/
const initialFormData = {// 用户信息模块userInfo: {name: '', // 姓名字段,初始为空字符串age: 0    // 年龄字段,初始为0},// 联系信息模块contactInfo: {email: '', // 邮箱字段,初始为空phone: ''  // 电话字段,初始为空}
};/*** Hook配置选项* 控制表单追踪行为和显示标签*/
const options = {// 自动检测变化(设为true时表单值变化会自动更新changes)autoDetect: true,// 字段标签映射(将字段名映射为更友好的显示名称)fieldLabels: {userInfo: {name: '姓名', // userInfo模块的name字段显示为"姓名"age: '年龄'   // age字段显示为"年龄"},contactInfo: {email: '电子邮箱', // email字段显示为"电子邮箱"phone: '联系电话'  // phone字段显示为"联系电话"}},// 模块标签映射(将模块名映射为更友好的显示名称)moduleLabels: {userInfo: '用户信息',   // userInfo模块显示为"用户信息"contactInfo: '联系信息' // contactInfo模块显示为"联系信息"}
};/*** 使用表单追踪Hook* 获取表单状态和管理方法*/
const {// 响应式表单数据(用于v-model绑定)formContent,// 变化记录对象,包含:// - oldValue: 旧值// - newValue: 新值// - changedFields: 变化的字段列表// - changeType: 各模块变化状态changes,// 是否有未提交的更改(布尔值)hasChanges,// 手动检查变化的函数checkChanges,// 重置表单的函数resetForm,// 加载后端数据的函数loadBackendData
} = useFormChangeTracker(initialFormData, options);/*** 模拟从后端加载数据* 在实际应用中,这里应该是API调用*/
const loadDataFromBackend = () => {// 模拟API返回的数据const backendData = {userInfo: {name: '张三',  // 模拟的用户名age: 25       // 模拟的年龄},contactInfo: {email: 'zhangsan@example.com',  // 模拟的邮箱phone: '13800138000'            // 模拟的电话}};// 调用Hook提供的方法加载数据// 这会更新backendData和formContent,并重置changesloadBackendData(backendData);console.log('数据已从后端加载并填充到表单');
};/*** 提交变更* 在实际应用中,这里应该调用API提交changes.value*/
const submitChanges = () => {// 首先检查当前变化(确保changes是最新的)const currentChanges = checkChanges();console.log('准备提交的变更:', currentChanges);// 这里可以添加实际提交到后端的逻辑// 例如:// 1. 调用API提交变更// 2. 提交成功后调用loadBackendData更新本地数据// 示例:显示提交成功的提示alert(`成功提交 ${currentChanges.changedFields.length} 处变更`);// 实际项目中可能需要:// try {//   await api.submitChanges(currentChanges);//   loadBackendData(await api.getLatestData());// } catch (error) {//   console.error('提交失败:', error);// }
};
</script><style scoped>
/* 表单容器样式 */
.form-container {max-width: 800px;  /* 限制最大宽度 */margin: 0 auto;    /* 居中显示 */padding: 20px;     /* 内边距 */
}/* 表单模块样式 */
.form-section {margin-bottom: 30px;  /* 模块间距 */padding: 15px;        /* 内边距 */border: 1px solid #eee; /* 边框 */border-radius: 5px;   /* 圆角 */
}/* 表单字段样式 */
.form-field {margin: 10px 0;      /* 字段间距 */display: flex;       /* 弹性布局 */align-items: center; /* 垂直居中 */
}/* 字段标签样式 */
.form-field label {width: 100px;        /* 固定宽度 */font-weight: bold;   /* 加粗 */
}/* 修改指示器样式 */
.change-indicator {color: #f56c6c;      /* 红色 */margin-left: 10px;   /* 左边距 */
}/* 操作按钮容器 */
.action-buttons {margin: 20px 0;      /* 上下边距 */display: flex;       /* 弹性布局 */gap: 10px;           /* 按钮间距 */
}/* 基础按钮样式 */
.btn {padding: 8px 15px;   /* 内边距 */border: none;        /* 无边框 */border-radius: 4px;  /* 圆角 */cursor: pointer;     /* 手型指针 */
}/* 禁用按钮样式 */
.btn:disabled {opacity: 0.6;        /* 半透明 */cursor: not-allowed; /* 禁用指针 */
}/* 加载按钮样式 */
.btn-load {background-color: #409eff; /* 蓝色 */color: white;              /* 白色文字 */
}/* 检查按钮样式 */
.btn-check {background-color: #909399; /* 灰色 */color: white;
}/* 提交按钮样式 */
.btn-submit {background-color: #67c23a; /* 绿色 */color: white;
}/* 重置按钮样式 */
.btn-reset {background-color: #f56c6c; /* 红色 */color: white;
}/* 变更面板样式 */
.changes-panel {margin-top: 30px;    /* 上边距 */padding: 15px;       /* 内边距 */background-color: #f8f8f8; /* 浅灰背景 */border-radius: 5px;  /* 圆角 */
}/* 变更列表样式 */
.changes-list {list-style-type: none; /* 无列表标记 */padding: 0;           /* 无内边距 */
}/* 单个变更项样式 */
.change-item {padding: 8px 0;       /* 内边距 */border-bottom: 1px dashed #ddd; /* 虚线边框 */
}/* 旧值样式 */
.old-value {color: #f56c6c;       /* 红色 */text-decoration: line-through; /* 删除线 */
}/* 新值样式 */
.new-value {color: #67c23a;       /* 绿色 */font-weight: bold;    /* 加粗 */
}/* 变更统计样式 */
.changes-summary {margin-top: 10px;     /* 上边距 */font-weight: bold;    /* 加粗 */text-align: right;    /* 右对齐 */
}
</style>

原文:https://mp.weixin.qq.com/s/gCuqKskp-KBxdClxcpwFqw

注意:

  1. JS数据与template内的form绑定数据,要采用hooks 封装的 formContent,否则无法检测到form数据的变化
    在这里插入图片描述

  2. initialFormData ,fieldLabels, moduleLabels 三个对象里面的字段名称key必须都是 userInfo,contactInfo, 字段名称key必须保持统一, 否则无法检测到form数据的变化

在这里插入图片描述

原文:https://mp.weixin.qq.com/s/gCuqKskp-KBxdClxcpwFqw

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java-泛型类

一、泛型类的基本概念 1. 什么是泛型类 泛型类是指使用类型参数定义的类&#xff0c;可以在类定义时不指定具体类型&#xff0c;而在实例化时指定。 2. 泛型类的作用 类型安全&#xff1a;编译时检查类型匹配 消除强制转换&#xff1a;减少运行时ClassCastException风险 代…

信任边界的人生智慧

我曾经是个喜欢试探的人 总想知道朋友会不会在我困难时伸手&#xff0c;合作伙伴会不会在利益面前变脸&#xff0c;爱人会不会在诱惑下坚守 结果发现&#xff0c;每一次试探都像是在关系上撒盐 不是因为对方经不起考验&#xff0c;而是「考验」这个行为本身就充满了不信任的…

SQL Server 中 GO 的作用

CREATE DATABASE MyDatabase; USE MyDatabase; GO --定义局部变量 DECLARE s_no varchar(8), s_avgrade numeric(4,1); --对局部变量赋值 SET s_no 20170208; SET s_avgrade 95.0; --使用局部变量 UPDATE student SET s_avgrade s_avgrade WHERE s_no s_no;&#x1f31f; G…

指标中台+大模型:解密衡石Agentic BI的NL2DSL架构实现

——Text2Metrics引擎如何攻克语义鸿沟&#xff0c;碾压传统NL2SQL方案 一、传统NL2SQL的“架构原罪”&#xff1a;业务语义的失控黑洞 当某银行尝试用NL2SQL分析“高净值客户流失率”时&#xff0c;系统生成如下危险SQL&#xff1a; 这正是NL2SQL的三大架构缺陷&#xff1a;…

设计模式 - 抽象工厂

抽象工厂是对工厂的抽象化&#xff0c;而不只是制造方法。 为了满足不同用户对产品的多样化需求&#xff0c;工厂不会只局限于生产一类产品&#xff0c;但是系统如果按工厂方法那样为每种产品都增加一个工厂又会造成工厂泛滥。所以&#xff0c;为了调和这种矛盾&#xff0c;抽…

面向对象Plus(2/2)

目录 面向对象Plus(qianwen) 一.面向对象三大特性 封装 继承 多态 二.多态 1.了解多态 2.体验多态 三.类属性和实例属性 1.类属性 a.设置和访问类属性 类属性的优点 b.修改类属性 四.类方法和静态方法 1.类方法 a.类方法特点 b.类方法应用场景 2.静态方法 a…

MocapApi 中文文档 和github下载地址 NeuronDataReader(以下简称 NDR)的下一代编程接口

以下是 MocapApi 技术文档 github https://github.com/pnmocap/MocapApi?tabreadme-ov-file 国内可以查找getcode 英文文档 https://mocap-api.noitom.com/mocap_api_en.html 概述 MocapApi 是 NeuronDataReader&#xff08;以下简称 NDR&#xff09;的下一代编程接口&…

STM32历史、命名、Flash、工作频率

目录 命名: Flash: 工作频率&#xff1a; 复位&#xff1a; 低功耗模式&#xff1a; IO端口&#xff1a; JATG: 看门狗定时器&#xff1a; STM是一家半导体公式&#xff0c;专门做芯片的&#xff0c;STM32是指32位的微处理器&#xff0c;其中芯片的架构是ARM结构的&#…

了解公共部门中的数据网格:支柱、架构和示例

作者&#xff1a;来自 Elastic Elastic Platform Team 想想那些像公共健康记录、城市规划模型等项目背后的所有数据。政府机构一直在产生大量数据。当数据分散在云平台、本地系统或像卫星和应急响应中心这样的专业环境中时&#xff0c;情况变得更加复杂。找到信息变得困难&…

阿里云ACP-检索分析服务

当数据量爆炸增长&#xff0c;并且需要提供全文检索功能&#xff0c;需要有效的数据检索能力 用什么数据库怎么保证安全性如何解决统计分析问题如何解决单点故障如何解决检索难题 应对方案&#xff1a; 关系型数据库&#xff1a;主从备份解决数据安全性问题&#xff0c;数据…

【DBeaver】跨平台数据库连接工具DBeaver Community 23.2.5安装配置使用

DBeaver是一款免费开源的通用数据库管理工具和SQL客户端&#xff0c;支持多种数据库系统。它基于Java开发&#xff0c;具备跨平台能力&#xff0c;可以在Windows、macOS和Linux系统上运行。 目录 安装DBeaver 连接MySQL数据库 安装DBeaver 进入DBeaver官网 DBeaver Communit…

【钱包】WEB3钱包APP框架的设计

【钱包】WEB3钱包APP框架的设计 一、前言 前段时间&#xff0c;自己做了一款WEB3钱包APP&#xff0c;从产品设计到框架搭建都是我一个人搞的&#xff0c;更多的参考了其他公司的钱包APP。 在此&#xff0c;想把自己的钱包经验分享出来&#xff0c;帮助没有做过钱包APP的同学开…

openGL学习(基本窗口)

学习路线 学习 OpenGL 需要掌握一系列基础知识和技能&#xff0c;这些内容涵盖了计算机图形学的基本概念、编程语言、数学知识以及 OpenGL 的具体 API 使用。以下是学习 OpenGL 所需的主要知识点&#xff1a; 1. 计算机图形学基础 图形学概念&#xff1a;了解图形学的基本概…

无人机防护装置技术解析

一、技术要点 1. 侦测防御系统 多频谱复合探测 整合无线电侦测&#xff08;20MHz–6GHz频段扫描&#xff09;、雷达探测、光电跟踪&#xff08;可见光/红外/激光&#xff09;技术&#xff0c;实现360无死角监测。例如神州明达系统可5公里内识别无人机信号&#xff0c;并同步…

2.2.2、CAN总线-测试模式、工作模式

目录 1、测试模式 2、工作模式 &#xff08;1&#xff09; &#xff08;2&#xff09;SLEEP位&#xff1a; &#xff08;3&#xff09;INRQ位&#xff1a;&#xff08;Init Request&#xff09; &#xff08;4&#xff09;ACK&#xff1a;应答 &#xff08;5&#xff09;…

区块链大讲堂 | 分布式隐私计算友好的零知识证明协议

区块链大讲堂 主讲人&#xff1a;上海交通大学计算机学院助理教授胡云聪 报告题目&#xff1a;分布式隐私计算友好的零知识证明协议 参与方式&#xff1a;扫描海报二维码报名参与活动

MyBatis映射文件(XML)中参数传递和SQL特殊字符处理

1. 参数占位符 1.1 #{} 和 ${} 的区别 #{} 占位符 作用&#xff1a;安全传参。MyBatis在执行SQL时&#xff0c;会把#{}替换成?&#xff0c;然后用参数值自动填充。 优点&#xff1a;可以防止SQL注入&#xff0c;推荐使用。 例子&#xff1a; select * from user wher…

C语言 数据结构 --排序 (直接插入排序,选择排序,交换排序......)

引言&#xff1a;本章简洁的讲解一下数据结构中的几个常见的排序 &#xff0c;作复习之用&#xff0c;后面可能会补一些其他的排序 。并给出一些小编学习中遇到的坑&#xff0c;作借鉴。 1.直接插入排序 直接插入排序是一种简单直观的排序算法&#xff0c;其基本思想是将一个数…

华为云发布盘古大模型 5.5 新一代昇腾 AI 云服务上线

2025 年 6 月 20 日&#xff0c;华为开发者大会 2025&#xff08;HDC 2025&#xff09;在东莞召开。华为常务董事、云计算 CEO 张平安宣布基于 CloudMatrix 384 超节点的新一代昇腾 AI 云服务全面上线&#xff0c;并发布盘古大模型 5.5&#xff0c;五大基础模型实现技术突破&am…

Reactor Handle

handle 是 Reactor 中一个非常灵活的操作符&#xff0c;它允许你对每个源元素进行处理&#xff0c;并可以选择性地发出零个或多个元素。它既可以用于映射&#xff08;map&#xff09;也可以用于过滤&#xff08;filter&#xff09;&#xff0c;因此可以看作是 map 和 filter 的…