Vue3+Element?Plus動態(tài)表單實現(xiàn)
更新時間:2025年05月15日 08:41:15 作者:滿
本文主要介紹了Vue3+Element?Plus動態(tài)表單實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
完整代碼
<template> <div class="dynamic-form-container"> <el-form ref="dynamicFormRef" :model="formData" :rules="formRules" label-width="auto" label-position="top" v-loading="loading" > <!-- 動態(tài)渲染表單字段 --> <template v-for="field in formConfig" :key="field.name"> <!-- 輸入框 --> <el-form-item v-if="field.type === 'input'" :label="field.label" :prop="field.name" :rules="generateFieldRules(field)" > <el-input v-model="formData[field.name]" :placeholder="field.placeholder || `請輸入${field.label}`" :type="field.inputType || 'text'" :clearable="field.clearable !== false" /> </el-form-item> <!-- 下拉選擇 --> <el-form-item v-else-if="field.type === 'select'" :label="field.label" :prop="field.name" :rules="generateFieldRules(field)" > <el-select v-model="formData[field.name]" :placeholder="field.placeholder || `請選擇${field.label}`" :clearable="field.clearable !== false" style="width: 100%" > <el-option v-for="option in field.options" :key="option.value" :label="option.label" :value="option.value" /> </el-select> </el-form-item> <!-- 單選框 --> <el-form-item v-else-if="field.type === 'radio'" :label="field.label" :prop="field.name" :rules="generateFieldRules(field)" > <el-radio-group v-model="formData[field.name]"> <el-radio v-for="option in field.options" :key="option.value" :label="option.value" > {{ option.label }} </el-radio> </el-radio-group> </el-form-item> <!-- 復(fù)選框 --> <el-form-item v-else-if="field.type === 'checkbox'" :label="field.label" :prop="field.name" :rules="generateFieldRules(field)" > <el-checkbox-group v-model="formData[field.name]"> <el-checkbox v-for="option in field.options" :key="option.value" :label="option.value" > {{ option.label }} </el-checkbox> </el-checkbox-group> </el-form-item> <!-- 日期選擇器 --> <el-form-item v-else-if="field.type === 'date'" :label="field.label" :prop="field.name" :rules="generateFieldRules(field)" > <el-date-picker v-model="formData[field.name]" :type="field.dateType || 'date'" :placeholder="field.placeholder || `請選擇${field.label}`" style="width: 100%" /> </el-form-item> <!-- 開關(guān) --> <el-form-item v-else-if="field.type === 'switch'" :label="field.label" :prop="field.name" > <el-switch v-model="formData[field.name]" /> </el-form-item> <!-- 自定義插槽 --> <el-form-item v-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() // 加載狀態(tài) const loading = ref(false) // 表單數(shù)據(jù) const formData = ref({}) // 表單驗證規(guī)則 const formRules = ref({}) // 表單配置(從后端獲?。? const formConfig = ref([ // 默認(rèn)配置,實際會被后端數(shù)據(jù)覆蓋 { name: 'username', label: '用戶名', type: 'input', required: true, placeholder: '請輸入用戶名' } ]) // 模擬從后端獲取表單配置 const fetchFormConfig = async () => { try { loading.value = true // 這里替換為實際的API調(diào)用 const response = await mockApiGetFormConfig() formConfig.value = response.data.fields // 初始化表單數(shù)據(jù) initFormData() // 生成驗證規(guī)則 generateFormRules() } catch (error) { ElMessage.error('獲取表單配置失敗: ' + error.message) } finally { loading.value = false } } // 初始化表單數(shù)據(jù) const initFormData = () => { const data = {} formConfig.value.forEach(field => { // 根據(jù)字段類型設(shè)置默認(rèn)值 switch (field.type) { case 'checkbox': data[field.name] = field.defaultValue || [] break case 'switch': data[field.name] = field.defaultValue || false break default: data[field.name] = field.defaultValue || '' } }) formData.value = data } // 生成表單驗證規(guī)則 const generateFormRules = () => { const rules = {} formConfig.value.forEach(field => { if (field.required || field.rules) { rules[field.name] = generateFieldRules(field) } }) formRules.value = rules } // 生成單個字段的驗證規(guī)則 const generateFieldRules = (field) => { const rules = [] // 必填規(guī)則 if (field.required) { rules.push({ required: true, message: field.message || `${field.label}不能為空`, trigger: field.trigger || 'blur' }) } // 自定義規(guī)則 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() // 這里替換為實際的提交API const response = await mockApiSubmitForm(formData.value) ElMessage.success('提交成功') console.log('表單數(shù)據(jù):', formData.value) console.log('服務(wù)器響應(yīng):', 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數(shù)據(jù)結(jié)構(gòu)建議
后端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": "只能包含字母、數(shù)字和下劃線" } ] }, { "name": "gender", "label": "性別", "type": "select", "required": true, "options": [ { "label": "男", "value": "male" }, { "label": "女", "value": "female" } ] }, { "name": "subscribe", "label": "訂閱通知", "type": "switch", "defaultValue": true } ] } }
到此這篇關(guān)于Vue3+Element Plus動態(tài)表單實現(xiàn)的文章就介紹到這了,更多相關(guān)Vue3 Element Plus動態(tài)表單內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue.js實現(xiàn)大轉(zhuǎn)盤抽獎總結(jié)及實現(xiàn)思路
這篇文章主要介紹了 Vue.js實現(xiàn)大轉(zhuǎn)盤抽獎總結(jié)及實現(xiàn)思路,本文通過實例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下2019-10-10解決Vue中引入swiper,在數(shù)據(jù)渲染的時候,發(fā)生不滑動的問題
今天小編就為大家分享一篇解決Vue中引入swiper,在數(shù)據(jù)渲染的時候,發(fā)生不滑動的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-09-09