vue3 + elementPlus 封裝hook,檢測form表單數據修改變更;示例用 script setup 語法使用

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 的…