前提
我们公司正在开发一个内部工作管理系统,其中有一个功能是让员工填写日常工作任务。
不同部门和岗位的工作任务不同,所以他们填写的内容也不一样。比如,项目经理需要填写项目进度和预计完成时间,行政人员需要填写处理的事项和耗时。
为了满足这些差异化需求,我们开发了一个可配置的表单组件。使用这个组件,我们只需要在系统中定义好不同岗位需要填写的表单项,就能自动生成相应的表单。
当员工填写表单时,组件会自动保存数据到一个对象中。我们可以监控这个对象,执行后续的业务逻辑。
组件还能根据我们设置的校验规则,自动检查员工的输入是否合法,并显示错误提示。
最后,当员工提交表单时,我们就可以调用组件提供的提交方法,进一步处理数据后提交给后端系统。
通过使用这个可配置的表单组件,我们可以在不同场景中灵活应用,既提高了开发效率,也方便了系统的后续维护。
说干就干,下面是我写组件的逻辑:
组件逻辑
在组件的 <script>
部分,我们定义了以下关键功能:
- 表单数据管理:
- 使用 reactive 函数创建表单数据对象 formData,并与表单项的 v-model 绑定。
- 通过 watch 函数监听 props.formData 的变化,及时更新 formData。
- 表单项类型判断:
- 定义 getInputComponent 函数,根据表单项的 type 属性返回对应的 Vue 组件。
- 表单初始化:
- 遍历 formItems 数组,将 defaultValue 属性设置为表单项的初始值。
- 表单输入验证:
- 定义 handleInput 函数,用于在用户输入时进行正则表达式验证。
表单数据获取:
通过 defineExpose 暴露 getFormData 方法,供父组件调用获取表单数据。
<template>
<el-form label-position="top" label-width="auto" :rules="rules" :model="formData" :inline="true" class="oneForm">
<el-form-item v-for="item in formItems" :key="item.prop" :label="item.label">
<component
:is="getInputComponent(item.type)"
v-model="formData[item.prop]"
:type="item.inputType"
:placeholder="`请填写 ${item.label}`"
:maxlength="item.maxlength"
:show-password="item.showPassword"
:value-format="item['value-format']"
:disabled-date="disabledDate"
:shortcuts="shortcuts"
:size="size"
:rows="item.rows"
:autosize="item.autosize"
@input="(value) => handleInput(item.prop, item.pattern)"
:style="{ width: item.type === 'textarea' ? '100%' : 'auto' }"
>
<template v-if="item.type === 'select'">
<el-option
v-for="option in item.options"
:key="option.value"
:label="option.label"
:value="option.value"
></el-option>
</template>
</component>
</el-form-item>
</el-form>
</template>
<script setup>
i