Vue3+Element Plus动态表单实现
作者:滿
本文主要介绍了Vue3+Element Plus动态表单实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
完整代码
<template> <div class="dynamic-form-container"> <el-form ref="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-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> <!-- 复选框 --> <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> <!-- 开关 --> <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() // 加载状态 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 || [] break case 'switch': data[field.name] = field.defaultValue || false break default: 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() // 这里替换为实际的提交API const 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 } ] } }
到此这篇关于Vue3+Element Plus动态表单实现的文章就介绍到这了,更多相关Vue3 Element Plus动态表单内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!