本篇介绍表单组件的简单封装
将表单改写成通过数组形式渲染
将表单改写成通过数组形式渲染,直接上代码
`<template>
<el-form ref="form" :model="props.form" label-width="auto" style="max-width: 1000px">
<el-row>
<!--不循环row,直接循环col,放不下会自动往下换行。-->
<el-col
v-for="(item,index) in props.formList"
:span="item.span || 6"
:key="index"
>
<el-form-item :rules="item.rules" :label="item.label" :key="index" :prop="item.prop">
<el-cascader v-if="item.renderType === 'ElCascader'" v-model="localForm[item.prop]" :options="item.options" />
<component v-else :is="handleComponent(item.renderType)" v-model="localForm[item.prop]" v-bind="item">
<template v-if="item.renderType === 'ElSelect'">
<el-option v-for="option in item.options" :key="option.value" :label="option.label" :value="option.value"></el-option>
</template>
<template v-if="item.renderType === 'ElRadioGroup'">
<el-radio v-for="option in item.options" :key="option.value" :label="option.label" :value="option.value"></el-radio>
</template>
<template v-if="item.renderType === 'ElCheckboxGroup'">
<el-checkbox v-for="option in item.options" :key="option.value" :label="option.label" :value="option.value"></el-checkbox>
</template>
</component>
</el-form-item>
</el-col>
</el-row>
</el-form>
</template>
<script lang="ts" setup>
import { computed } from 'vue';
const emit = defineEmits(['update:form']);
import { ElInputNumber, ElInput, ElSelect, ElDatePicker, ElRadioGroup, ElSwitch, ElCheckboxGroup, ElCascader } from 'element-plus';
import {type FormList, FormInter} from "@/types/types"
let props = withDefaults(defineProps<{formList?:FormList, form?:FormInter}>(),{
formList:()=>[],
form: ()=>({})
})
// 使用 computed 属性来创建本地响应式数据
const localForm = computed({
get: () => props.form,
set: (value) => {
// 使用 $emit 向父组件发送事件来更新 form
emit('update:form', value);
}
});
const handleComponent = (renderType:string) => {
switch (renderType) {
case 'ElInput':
return ElInput
case 'ElInputNumber':
return ElInputNumber
case 'ElSelect':
return ElSelect
case 'ElDatePicker':
return ElDatePicker
case 'ElRadioGroup':
return ElRadioGroup
case 'ElSwitch':
return ElSwitch
case 'ElCheckboxGroup':
return ElCheckboxGroup
case 'ElCascader':
return ElCascader
default:
return renderType
}
}
</script>`
<template>
<div>
表单组件封装
<div>数据:{{ form }}</div>
<lee-form :form="form" :formList="formList" @update:form="updateForm" />
</div>
</template>
<script setup lang="ts">
import { reactive,computed } from 'vue'
import { type FormList, FormInter } from '@/types/types'
import LeeForm from '@/components/form/leeForm.vue'
const formList = computed<FormList[]>(()=>[
{
renderType: 'ElInput',
label: '姓名',
prop: 'name',
rules: [
{ required: true, message: '请输入姓名', trigger: 'blur' }
]
},
{
renderType: 'ElInputNumber',
label: '年龄',
prop: 'age',
rules: [ // 动态校验
{ required:form.name, message: '请输入姓名', trigger: 'blur' }
]
},
{
renderType: 'ElSelect',
label: '性别',
prop: 'sex',
options: [
{ label: '男', value: '男' },
{ label: '女', value: '女' }
]
},
{
renderType: 'ElDatePicker',
label: '生日',
prop: 'birthday'
},
{
renderType: 'ElRadioGroup',
label: '婚姻状况',
prop: 'marriage',
options: [
{ label: '未婚', value: '未婚' },
{ label: '已婚', value: '已婚' }
]
},
{
renderType: 'ElSwitch',
label: '开关',
prop: 'switch'
},
{
renderType: 'ElCheckboxGroup',
label: '多选框',
prop: 'checkboxGroup',
options: [
{ label: '1', value: '1' },
{ label: '2', value: '2' }
]
},
{
renderType: 'ElCascader',
label: '级联选择器',
prop: 'elCascader',
options: [
{
value: 'guide',
label: 'Guide',
children: [
{
value: 'disciplines',
label: 'Disciplines',
children: [
{
value: 'consistency',
label: 'Consistency'
}
]
}
]
}
]
},
{
renderType: 'ElInput',
label: '备注',
prop: 'note',
rows: 2,
type: 'textarea'
},
])
const form = reactive<FormInter>({
name: '',
elCascader:[]
})
/**
* 更新表单数据
* @param {Record<string, any>} val - 需要更新的表单数据对象
* @description 通过 Object.assign 方法将传入的数据对象合并到现有表单对象中
*/
const updateForm = (val: Record<string, any>) => {
console.log(val)
Object.assign(form, val)
}
</script>
<style scoped></style>
githuab地址为:'https://github.com/leezhenwang/vue3-TypeScript-demo.git/
小恐龙
专注于WEB和移动前端开发