效果图

Form.vue
<template>
<div>
<el-form ref="ruleFormRef" :model="formData" :rules="rules" label-width="120px" status-icon>
<template v-for="(item, index) in formDesc" :key="index">
<el-form-item :label="item.label" v-if="item.type === 'select'" prop="region">
<el-select v-model="formData.region" placeholder="please select your zone">
<el-option
v-for="(optionItem, optionIndex) in item.option"
:key="optionIndex"
:label="optionItem.label"
:value="optionItem.value"
/>
</el-select>
</el-form-item>
<el-form-item :label="item.label" v-else-if="item.type === 'date'" prop="time">
<el-date-picker v-model="formData.time" type="date" placeholder="Pick a date" style="width: 100%" />
</el-form-item>
<el-form-item :label="item.label" v-else-if="item.type === 'switch'">
<el-switch v-model="formData.delivery" />
</el-form-item>
<el-form-item :label="item.label" v-else-if="item.type === 'checkbox'" prop="type">
<el-checkbox-group v-model="formData.type">
<el-checkbox
v-for="(checkboxItem, checkboxIndex) in item.checkboxList"
:key="checkboxIndex"
:label="checkboxItem.label"
:name="checkboxItem.name"
/>
</el-checkbox-group>
</el-form-item>
<el-form-item :label="item.label" v-else-if="item.type === 'radio'" prop="resource">
<el-radio-group v-model="formData.resource">
<el-radio v-for="(radioItem, radioIndex) in item.radioList" :key="radioIndex" :label="radioItem.label" />
</el-radio-group>
</el-form-item>
<el-form-item :label="item.label" v-else prop="name">
<el-input v-model="formData.name" />
</el-form-item>
</template>
<el-form-item>
<el-button type="primary" @click="submitForm(ruleFormRef)">Create</el-button>
<el-button @click="resetForm(ruleFormRef)">Reset</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script setup lang="ts">
import { rules } from './FormData'
import type { FormInstance } from 'element-plus'
interface Props {
formDesc: any
formData: Record<string, any>
}
const props = defineProps<Props>()
console.log(props)
const ruleFormRef = ref<FormInstance>()
interface EmitEvent {
(e: 'submit', params: any): void
}
const emit = defineEmits<EmitEvent>()
const submitForm = async (formEl: FormInstance | undefined) => {
if (!formEl) return
await formEl.validate((valid, fields) => {
if (valid) {
console.log('submit!')
console.log(props.formData)
emit('submit', props.formData)
} else {
console.log('error submit!', fields)
}
})
}
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()
}
</script>
<style></style>
FormData.ts (表单项及校验规则)
import type { FormRules } from 'element-plus'
export const formDesc = ref([
// 表单项
{
label: '标题',
prop: 'name',
type: 'input'
},
{
label: '区域',
prop: 'region',
type: 'select',
option: [
{
label: '上海',
value: 'shanghai'
},
{
label: '北京',
value: 'beijing'
}
]
},
{
label: '选择时间',
prop: 'time',
type: 'date'
},
{
label: '激活',
prop: 'delivery',
type: 'switch'
},
{
label: '多选',
prop: 'type',
type: 'checkbox',
checkboxList: [
{
label: '唱',
name: 'APEX'
},
{
label: '跳',
name: 'APEX'
},
{
label: 'RAR',
name: 'APEX'
},
{
label: '篮球',
name: 'APEX'
}
]
},
{
label: '单选',
prop: 'resource',
type: 'radio',
radioList: [
{
label: '蔡徐坤'
},
{
label: '周杰伦'
}
]
}
])
export const rules = reactive<FormRules>({
// 校验规则
name: [
{ required: true, message: 'Please input Activity name', trigger: 'blur' },
{ min: 3, max: 5, message: 'Length should be 3 to 5', trigger: 'blur' }
],
region: [
{
required: true,
message: 'Please select Activity zone',
trigger: 'change'
}
],
time: [
{
type: 'date',
required: true,
message: 'Please pick a date',
trigger: 'change'
}
],
type: [
{
type: 'array',
required: true,
message: 'Please select at least one activity type',
trigger: 'change'
}
],
resource: [
{
required: true,
message: 'Please select activity resource',
trigger: 'change'
}
]
})
父组件调用Form组件
<template>
<el-dialog v-model="dialogVisible" title="Tips" width="50%" :before-close="cancel">
<div>
<Form :formData="formData" :formDesc="formDesc" @submit="handleBaseSubmit" />
</div>
</el-dialog>
</template>
<script lang="ts" setup>
import Form from '../commonForm/Form.vue'
import { formDesc } from '../commonForm/FormData'
const formData = reactive<Record<string, any>>({
name: '',
region: '',
time: '',
delivery: false,
type: [],
resource: '',
desc: ''
})
const handleBaseSubmit = (model: Record<string, any>) => {
console.log(model) // 获取表单数据
}
</script>
<style scoped>
</style>