Vue3 + Element Plus 動態表單實現

?完整代碼

<template><div class="dynamic-form-container"><el-formref="dynamicFormRef":model="formData":rules="formRules"label-width="auto"label-position="top"v-loading="loading"><!-- 動態渲染表單字段 --><template v-for="field in formConfig" :key="field.name"><!-- 輸入框 --><el-form-itemv-if="field.type === 'input'":label="field.label":prop="field.name":rules="generateFieldRules(field)"><el-inputv-model="formData[field.name]":placeholder="field.placeholder || `請輸入${field.label}`":type="field.inputType || 'text'":clearable="field.clearable !== false"/></el-form-item><!-- 下拉選擇 --><el-form-itemv-else-if="field.type === 'select'":label="field.label":prop="field.name":rules="generateFieldRules(field)"><el-selectv-model="formData[field.name]":placeholder="field.placeholder || `請選擇${field.label}`":clearable="field.clearable !== false"style="width: 100%"><el-optionv-for="option in field.options":key="option.value":label="option.label":value="option.value"/></el-select></el-form-item><!-- 單選框 --><el-form-itemv-else-if="field.type === 'radio'":label="field.label":prop="field.name":rules="generateFieldRules(field)"><el-radio-group v-model="formData[field.name]"><el-radiov-for="option in field.options":key="option.value":label="option.value">{{ option.label }}</el-radio></el-radio-group></el-form-item><!-- 復選框 --><el-form-itemv-else-if="field.type === 'checkbox'":label="field.label":prop="field.name":rules="generateFieldRules(field)"><el-checkbox-group v-model="formData[field.name]"><el-checkboxv-for="option in field.options":key="option.value":label="option.value">{{ option.label }}</el-checkbox></el-checkbox-group></el-form-item><!-- 日期選擇器 --><el-form-itemv-else-if="field.type === 'date'":label="field.label":prop="field.name":rules="generateFieldRules(field)"><el-date-pickerv-model="formData[field.name]":type="field.dateType || 'date'":placeholder="field.placeholder || `請選擇${field.label}`"style="width: 100%"/></el-form-item><!-- 開關 --><el-form-itemv-else-if="field.type === 'switch'":label="field.label":prop="field.name"><el-switch v-model="formData[field.name]" /></el-form-item><!-- 自定義插槽 --><el-form-itemv-else-if="field.type === 'slot'":label="field.label":prop="field.name":rules="generateFieldRules(field)"><slot :name="field.slotName" :field="field" :model="formData" /></el-form-item></template><el-form-item><el-button type="primary" @click="submitForm">提交</el-button><el-button @click="resetForm">重置</el-button></el-form-item></el-form></div>
</template><script setup>
import { ref, onMounted } from 'vue'
import { ElMessage } from 'element-plus'// 表單引用
const dynamicFormRef = ref()// 加載狀態
const loading = ref(false)// 表單數據
const formData = ref({})// 表單驗證規則
const formRules = ref({})// 表單配置(從后端獲取)
const formConfig = ref([// 默認配置,實際會被后端數據覆蓋{name: 'username',label: '用戶名',type: 'input',required: true,placeholder: '請輸入用戶名'}
])// 模擬從后端獲取表單配置
const fetchFormConfig = async () => {try {loading.value = true// 這里替換為實際的API調用const response = await mockApiGetFormConfig()formConfig.value = response.data.fields// 初始化表單數據initFormData()// 生成驗證規則generateFormRules()} catch (error) {ElMessage.error('獲取表單配置失敗: ' + error.message)} finally {loading.value = false}
}// 初始化表單數據
const initFormData = () => {const data = {}formConfig.value.forEach(field => {// 根據字段類型設置默認值switch (field.type) {case 'checkbox':data[field.name] = field.defaultValue || []breakcase 'switch':data[field.name] = field.defaultValue || falsebreakdefault:data[field.name] = field.defaultValue || ''}})formData.value = data
}// 生成表單驗證規則
const generateFormRules = () => {const rules = {}formConfig.value.forEach(field => {if (field.required || field.rules) {rules[field.name] = generateFieldRules(field)}})formRules.value = rules
}// 生成單個字段的驗證規則
const generateFieldRules = (field) => {const rules = []// 必填規則if (field.required) {rules.push({required: true,message: field.message || `${field.label}不能為空`,trigger: field.trigger || 'blur'})}// 自定義規則if (field.rules && Array.isArray(field.rules)) {rules.push(...field.rules)}// 類型校驗if (field.type === 'input' && field.inputType === 'email') {rules.push({type: 'email',message: '請輸入正確的郵箱格式',trigger: ['blur', 'change']})}return rules
}// 提交表單
const submitForm = async () => {try {// 表單驗證await dynamicFormRef.value.validate()// 這里替換為實際的提交APIconst response = await mockApiSubmitForm(formData.value)ElMessage.success('提交成功')console.log('表單數據:', formData.value)console.log('服務器響應:', response)// 可以在這里處理提交成功后的邏輯} catch (error) {if (error instanceof Error) {ElMessage.error('表單驗證失敗: ' + error.message)}}
}// 重置表單
const resetForm = () => {dynamicFormRef.value.resetFields()
}// 模擬API獲取表單配置
const mockApiGetFormConfig = () => {return new Promise((resolve) => {setTimeout(() => {resolve({data: {fields: [{name: 'username',label: '用戶名',type: 'input',required: true,placeholder: '請輸入用戶名',maxlength: 20},{name: 'password',label: '密碼',type: 'input',inputType: 'password',required: true,placeholder: '請輸入密碼',rules: [{ min: 6, max: 18, message: '密碼長度在6到18個字符', trigger: 'blur' }]},{name: 'gender',label: '性別',type: 'select',required: true,options: [{ label: '男', value: 'male' },{ label: '女', value: 'female' },{ label: '其他', value: 'other' }]},{name: 'hobbies',label: '興趣愛好',type: 'checkbox',options: [{ label: '游泳', value: 'swimming' },{ label: '跑步', value: 'running' },{ label: '閱讀', value: 'reading' }]},{name: 'subscribe',label: '訂閱通知',type: 'switch',defaultValue: true},{name: 'birthday',label: '出生日期',type: 'date',dateType: 'date',required: true}]}})}, 800)})
}// 模擬API提交表單
const mockApiSubmitForm = (data) => {return new Promise((resolve) => {setTimeout(() => {resolve({ code: 200, message: 'success', data })}, 500)})
}// 組件掛載時獲取表單配置
onMounted(() => {fetchFormConfig()
})
</script><style scoped>
.dynamic-form-container {max-width: 800px;margin: 0 auto;padding: 20px;
}
</style>

后端API數據結構建議

后端API返回的表單配置建議采用如下JSON格式:

{"code": 200,"message": "success","data": {"fields": [{"name": "username","label": "用戶名","type": "input","required": true,"placeholder": "請輸入用戶名","inputType": "text","maxlength": 20,"rules": [{"pattern": "^[a-zA-Z0-9_]+$","message": "只能包含字母、數字和下劃線"}]},{"name": "gender","label": "性別","type": "select","required": true,"options": [{"label": "男","value": "male"},{"label": "女","value": "female"}]},{"name": "subscribe","label": "訂閱通知","type": "switch","defaultValue": true}]}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/83263.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/83263.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/83263.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Mac修改hosts文件方法

Mac修改hosts文件方法 在 macOS 上修改 hosts 文件需要管理員權限 步驟 1&#xff1a;打開終端 通過 Spotlight 搜索&#xff08;Command 空格&#xff09;輸入 Terminal&#xff0c;回車打開。或進入 應用程序 > 實用工具 > 終端。 步驟 2&#xff1a;備份 hosts 文件…

深度學習—BP神經網絡

文章目錄 [TOC](文章目錄) 一、基本概念二、 網絡結構三、BP神經網絡的原理總結特點&#xff1a;應用場景優缺點 一、基本概念 BP 神經網絡&#xff08;Backpropagation Neural Network&#xff09;是一種基于誤差反向傳播算法的多層前饋神經網絡&#xff0c;由輸入層、隱藏層…

Spring AI(6)——向量存儲

向量數據庫是一種特殊類型的數據庫&#xff0c;在 AI 應用中發揮著至關重要的作用。 在向量數據庫中&#xff0c;查詢與傳統關系型數據庫不同。它們執行的是相似性搜索&#xff0c;而非精確匹配。當給定一個向量作為查詢時&#xff0c;向量數據庫會返回與該查詢向量“相似”的…

Qt功能區:簡介與安裝

Qt功能區 1. 功能區簡介2. SARibbon2.1 簡介2.2 編譯與安裝采用CMake-gui進行編譯采用VS進行編譯安裝與使用 Qt 官方不支持 Ribbon 風格&#xff08;Ribbon UI 風格是微軟開創的&#xff0c;具有專利許可協議&#xff0c;許可協議對從構建 UI 的指令到每個按鈕間的空格數都做了…

iOS safari和android chrome開啟網頁調試與檢查器的方法

手機開啟遠程調試教程&#xff08;適用于 Chrome / Safari&#xff09; 前端移動端調試指南&#xff5c;適用 iPhone 和 Android&#xff5c;WebDebugX 出品 本教程將詳細介紹如何在 iPhone 和 Android 手機上開啟網頁檢查器&#xff0c;配合 WebDebugX 實現遠程調試。教程包含…

Golang企業級商城高并發微服務實戰

Golang企業級商城高并發微服務實戰包含內容介紹&#xff1a; 從零開始講了百萬級單體高并發架構、千萬級微服務架構&#xff0c;其中包含Rpc實現微服務、微服務的跨語言調用jsonrpc和protobuf、protobuf的安裝、protobuf高級語法、protobuf結合Grpc實現微服務實戰、微服務服務…

實現可靠的 WebSocket 連接:心跳與自動重連的最佳實踐

概覽 本文將手把手教你如何從零編寫一個可用于直播或在線聊天的 WSocket 類&#xff0c;依次實現連接建立、心跳檢測、斷線重連、消息收發以及資源清理等功能。我們將結合 WebSocket API 的標準用法、心跳保持 和 重連策略&#xff0c;并充分運用現代 JavaScript 語法&#xf…

UEFI Spec 學習筆記---33 - Human Interface Infrastructure Overview(1)

33 - Human Interface Infrastructure Overview 本章節主要用于介紹Human Interface Infrastructure&#xff08;HII&#xff09;架構介紹&#xff0c;描述如何通過 HII 來管理用戶的輸入&#xff0c;以及描述在 UEFI spec 中涉及 HII 相關的 Protocol、function 和類型定義。…

ip命令詳解

控制網卡的硬件狀態 ip link set ens36 down ip link set ens36 up 修改網卡名稱&#xff08;臨時&#xff09; ip link set ens36 down ip link set ens36 name xxx 修改網卡的mac地址 ip link set ens36 down ip link set xxx name ens36 查看ip的addr ip addr show ip ad…

hadoop中了解yarm

Hadoop中的YARN&#xff08;Yet Another Resource Negotiator&#xff09;是一種新的Hadoop資源管理器&#xff0c;是一個通用資源管理系統&#xff0c;可為上層應用提供統一的資源管理和調度。以下是其相關介紹&#xff1a; 核心思想 將JobTracker的資源管理和作業調度/監控功…

做好的QT軟件,換一個筆記本打開后發現字體很小,部分字體還被控件遮擋

出現這種情況的原因主要是屏幕的DPI&#xff08;每英寸點數&#xff09;不同。Qt中控件的大小單位為像素&#xff0c;在高DPI下&#xff0c;控件會變小&#xff0c;低DPI下控件會變大。而Qt中字體的單位默認為磅&#xff0c;無論在什么顯示器上顯示同一磅值的字體&#xff0c;其…

linux - 權限的概念

目錄 用戶權限 超級用戶與普通用戶的區別 超級用戶&#xff08;root&#xff09;&#xff1a; 普通用戶&#xff1a; 切換用戶身份 使用sudo執行高權限命令 用戶管理 用戶組管理 文件權限 文件訪問者類別 基本權限 權限表示方法 權限修改 chmod chown chgrp u…

Python函數返回值的藝術:為何True/False是更優實踐及例外情況分析

在Python編程實踐中&#xff0c;子程序的返回值設計往往是一個容易被忽視但卻至關重要的設計決策。本文將深入探討為什么返回True/False往往是更好的選擇&#xff0c;何時應該避免這種做法&#xff0c;以及如何處理與None值相關的問題。 為什么返回True/False是更好的實踐&…

STM32單片機內存分配詳細講解

單片機的內存無非就兩種&#xff0c;內部FLASH和SRAM&#xff0c;最多再加上一個外部的FLASH拓展。在這里我以STM32F103C8T6為例子講解FLASH和SRAM。 STM32F103C8T6具有64KB的閃存和20KB的SRAM。 一. Flash 1.1 定義 非易失性存儲器&#xff0c;即使在斷電后&#xff0c;其所…

【Tools】Visual Studio使用經驗介紹(包括基本功能、遠程調試、引入第三方庫等等)

這里寫目錄標題 1. VS基本使用1.1. 快捷鍵1.2. 查看變量地址1.3. 查看代碼匯編1.4. visual studio 熱重載功能的使用1.5. vs遠程服務器調試1.6. 引入第三方庫VLD1.7. release debug模式 1. VS基本使用 1.1. 快捷鍵 ctrl c :復制光標所在行 注意&#xff1a;只需要光標在這…

網絡爬蟲學習之httpx的使用

開篇 本文整理自《Python3 網絡爬蟲實戰》&#xff0c;主要是httpx的使用。 筆記整理 使用urllib庫requests庫的使用&#xff0c;已經可以爬取絕大多數網站的數據&#xff0c;但對于某些網站依然無能為力。 這是因為這些網站強制使用HTTP/2.0協議訪問&#xff0c;這時urllib和r…

Python內存管理:賦值、淺拷貝與深拷貝解析

賦值與共享資源 在Python中&#xff0c;直接賦值操作&#xff08;如 list2 list1&#xff09;會導致兩個變量共享同一個內存地址。這意味著對 list1 的修改會直接影響到 list2&#xff0c;因為它們指向同一個對象。 注意: 賦值等于完全共享資源 如果我們不希望這樣完全共享&…

CentOS7原有磁盤擴容實戰記錄(LVM非LVM)【針對GPT分區】

一、環境 二、命令及含義 fdisk ????fdisk?是一個較老的分區表創建和管理工具&#xff0c;主要支持MBR&#xff08;Master Boot Record&#xff09;格式的分區表。MBR分區表支持的硬盤單個分區最大容量為2TB&#xff0c;最多可以有4個主分區。fdisk通過命令行界面進行操…

獲取相機圖像(ROS2)

文章目錄 前言一、獲取筆記本自帶相機圖像1.打開終端2.安裝usb-cam功能包3.啟動相機節點4.再打開一個終端5.啟動rqt查看圖像(1)方法一&#xff1a;點擊窗口選項&#xff0c;打開圖像話題(2)方法二&#xff1a;使用命令行&#xff0c;直接打開圖像話題 二、獲取USB相機圖像總結 …

Go 語言中接口類型轉換為具體類型

類型轉換方法 在 Go 語言中&#xff0c;將接口類型轉換為具體類型主要有以下幾種方法&#xff1a; 1. 類型斷言&#xff08;Type Assertion&#xff09; var i interface{} "hello"// 基本形式 s : i.(string) // 將接口i轉換為string類型 fmt.Println(s) // 輸…