Vue3 表单逻辑抽象与复用方案设计
1. 背景与问题
在开发中经常遇到复杂的表单页面,这些表单通常具有以下特点:
- 字段较多且类型复杂
- 存在多个依赖关系(如审核人依赖组织)
- 包含特殊功能(如地图选择)
- 需要处理编辑和新增两种场景
- 数据提交和回显需要转换
这些特点导致以下问题:
- 代码组织混乱
- 逻辑复用困难
- 维护成本高
- 代码重复率高
2. 解决方案
2.1 整体思路
将表单逻辑分为三层:
- 基础功能层 - 处理常规表单字段
- 定制功能层 - 处理特定业务逻辑
- 特殊功能层 - 处理复杂交互功能
同时抽象出通用的工具层:
- 通用表单数据处理 hook
- 通用表单配置 hook
- 工具函数库
2.2 核心抽象
2.2.1 通用表单数据处理 Hook
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| export function useFormData<T extends object, S = T>( initialData: T, options: { transform?: (data: T) => S; reverseTransform?: (data: S) => T; validate?: (data: T) => Promise<boolean>; } ) { const formData = reactive<T>(initialData);
const transformSubmitData = () => { return options.transform ? options.transform(formData) : formData; };
const handleEditData = (data: S) => { const transformed = options.reverseTransform ? options.reverseTransform(data) : data; Object.assign(formData, transformed); }; return { formData, transformSubmitData, handleEditData }; }
|
2.2.2 通用表单配置 Hook
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| typescript
export function useFormConfig( getConfig: () => FormItemConfig[], dependencies?: { watch: string[]; handler: (...args: any[]) => void; }[] ) { const formConfig = computed(() => ({ formItemsConfig: getConfig() })); if (dependencies) { dependencies.forEach(dep => { watch(dep.watch, dep.handler); }); } return { formConfig }; }
|
2.3 实现层级
2.3.1 基础功能层
处理基本表单字段,如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| typescript
export function useBaseForm() { const { formData, transformSubmitData, handleEditData } = useFormData<BaseFormData>( { name: '', description: '', activityTime: [] }, { transform: (data) => ({ name: data.name, startTime: formatTimestamp(data.activityTime[0]) }) } ); return { baseForm: formData, transformBaseData: transformSubmitData, handleBaseEdit: handleEditData }; }
|
2.3.2 定制功能层
处理特定业务逻辑,如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| typescript
export function useCustomForm() { const { formData, transformSubmitData } = useFormData<CustomFormData>( { cid: '', auditor: [] }, { transform: (data) => ({ cid: data.cid, auditor: arrayToString(data.auditor) }) } ); return { customForm: formData, transformCustomData: transformSubmitData }; }
|
2.3.3 特殊功能层
处理复杂交互功能,如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| typescript
export function useSpecialForm() { const { formData, transformSubmitData } = useFormData<SpecialFormData>( { signType: 1, signPlace: '', attachments: [] } );
const openMapSelect = () => {
}; return { specialForm: formData, transformSpecialData: transformSubmitData, openMapSelect }; }
|
2.4 组合使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| typescript
export function useActivityForm(isEdit = false) { const base = useBaseForm(); const custom = useCustomForm(); const special = useSpecialForm();
const formConfig = computed(() => ({ formItemsConfig: [ ...base.formConfig.value.formItemsConfig, ...custom.formConfig.value.formItemsConfig, ...special.formConfig.value.formItemsConfig ] }));
const handleSubmit = async () => { const submitData = { ...base.transformBaseData(), ...custom.transformCustomData(), ...special.transformSpecialData() }; return submitData; }; return { formConfig, handleSubmit }; }
|
3. 使用示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| vue <script setup> import { useActivityForm } from './hooks/useActivityForm'; const { formConfig, handleSubmit } = useActivityForm(isEdit);
const onSubmit = async () => { const data = await handleSubmit(); await submitAPI(data); }; </script> <template> <tForm :config="formConfig" @submit="onSubmit" /> </template>
|
4. 方案优势
高复用性
类型安全
- TypeScript 支持
- 完整类型定义
- 类型推导
可维护性
开发效率
5. 注意事项
- 合理划分功能层级
- 保持接口一致性
- 注意性能优化
- 完善错误处理
- 做好类型定义
6. 后续优化
- 添加更多预设配置
- 扩展验证规则
- 优化性能
- 添加单元测试
- 完善文档
7. 总结
通过合理的抽象和模块化设计,我们可以大大提高表单开发的效率和代码质量。这个方案不仅解决了当前的问题,也为后续的开发提供了良好的基础。