跳到主要内容
版本:Next

表单与选择组件

目录

  1. 简介
  2. 项目结构概览
  3. DyForm动态表单引擎
  4. Select组件系统
  5. 日期时间选择器
  6. 性能优化策略
  7. 最佳实践指南
  8. 故障排除
  9. 总结

简介

本文档详细阐述了LMEs Web Base项目中的表单与选择类组件架构设计。该系统包含三个核心组件:DyForm动态表单引擎、Select组件系统以及DateTimePickRange日期时间选择器。这些组件共同构成了一个完整的表单解决方案,支持JSON Schema驱动的UI渲染、实时校验规则、懒加载选项、远程搜索等功能。

项目结构概览

图表来源

DyForm动态表单引擎

架构设计

DyForm是一个基于JSON Schema的动态表单引擎,采用Vue 3 Composition API和TypeScript构建。它通过预定义的组件映射表实现不同表单控件的动态渲染。

图表来源

JSON Schema驱动的UI渲染

DyForm通过formItemElementMap实现组件映射,支持多种表单控件类型:

const formItemElementMap: Record<string, any> = markRaw({
input: DyInput,
inputNumber: ElInputNumber,
select: Select,
selectInput: SelectInput,
flow: RelationFlowDialog,
variable: Variable,
textareaFlow: TextareaFlow,
switch: (props: PropType<any>, { attrs }: SetupContext) => {
return <el-switch {...attrs} />
},
})

实时校验规则

DyForm集成了Element Plus的表单验证系统,支持复杂的校验规则链:

const validate = () => {
if (!formRef.value) return false
return new Promise((resolve, reject) => {
formRef.value?.validate((valid: boolean) => {
if (valid) {
resolve(true)
} else {
reject(false)
}
})
})
}

章节来源

图表来源

Element Plus封装ElSelect

ElSelect是对Element Plus Select组件的封装,主要用于特定配置场景:

return (
<el-config-provider namespace={namespace} z-index={500}>
<el-select
empty-values={[null, undefined]}
value-on-clear={undefined}
{...attrs}
disabled={disabled}
class="cs-setting-select_custom_style"
popper-class="settings-cs-select_check"
>
{options
? options.map((item: any) => {
return <Option {...item} />
})
: slots.default?.()}
</el-select>
</el-config-provider>
)

下拉选项懒加载与远程搜索

虽然当前实现主要依赖静态选项,但框架已为懒加载和远程搜索预留了扩展点:

// 选项数据源处理
const options = computed(() => {
return (
props.optionData?.value ||
(props.optionData as Array<any>) ||
props.options
)
})

多选标签溢出处理

Radio组件实现了多选标签的智能处理:

// 多tag情况处理
if (Array.isArray(props.data)) {
return props.data.map((item: DataType, index: any) => {
return (
<div class={styles.tag} key={index}>
{item.name || item.label || item.description || item.type}
{props.showClose ? (
<Icon
class={styles.tagClose}
icon="tag_close"
onClick={(evt) => onClose(item, evt)}
/>
) : null}
</div>
)
})
}

章节来源

日期时间选择器

Vue 3响应式系统深度集成

DateTimePickRange组件展示了Vue 3响应式系统的最佳实践:

图表来源

时间范围联动机制

const onChangeFrom = (val: Date) => {
if (times.To && dayjs(val).isAfter(times.To)) {
ElMessage.warning(_t('开始时间必须比结束时间小'))
return
}
emit('change', times)
}

const onChangeTo = (val: Date) => {
if (times.To && dayjs(val).isBefore(times.From)) {
ElMessage.warning(_t('开始时间必须比结束时间小'))
return
}
emit('change', times)
}

国际化日期格式适配

组件支持多语言环境下的日期格式化:

const isZh = ref(true)

const checkZh = (lang: string) => {
const languageStr = lang.toLowerCase()
if (languageStr.includes('zh')) return true
if (languageStr.includes('original')) return true
return false
}

onMounted(() => {
isZh.value = checkZh(getCurrentLang())
onLanguageChange()
})

章节来源

性能优化策略

节流输入处理

虽然当前组件未显式实现节流,但可以通过以下方式优化:

// 推荐的节流实现
import debounce from 'lodash/debounce'

const handleInputChange = debounce((value: string) => {
// 处理输入变化
}, 300)

虚拟滚动选项列表

对于大量选项的场景,可以考虑实现虚拟滚动:

// 虚拟滚动示例结构
const VirtualSelect = defineComponent({
setup() {
const visibleOptions = ref([])
const scrollTop = ref(0)

const calculateVisibleOptions = () => {
// 计算可见选项逻辑
}

return () => (
<div
class="virtual-list"
onScroll={calculateVisibleOptions}
>
{visibleOptions.value.map(option => (
<Option {...option} />
))}
</div>
)
}
})

组件缓存策略

DyForm使用markRaw避免不必要的响应式代理:

const formItemElementMap: Record<string, any> = markRaw({
input: DyInput,
inputNumber: ElInputNumber,
// ... 其他组件
})

最佳实践指南

表单重置模式

// DyForm重置方法
const resetForm = () => {
if (!formRef.value) return false
formRef.value.resetFields()
}

// 手动重置示例
const manualReset = () => {
formItemProps.value.forEach((item: FormItemPropType) => {
form.value[item.prop] = item.defaultValue
})
}

默认值填充策略

// 初始化表单数据
const initFormData = () => {
formItemProps.value.forEach((item: FormItemPropType) => {
form.value[item.prop] = form.value[item.prop] || item.defaultValue
})
active.value = formItemProps.value[0].name
}

错误处理模式

// 验证错误处理
const validateWithErrorHandling = async () => {
try {
await validate()
return true
} catch (error) {
ElMessage.error('表单验证失败,请检查输入')
return false
}
}

故障排除

常见问题与解决方案

1. 动态表单组件未正确渲染

问题: JSON Schema中的el字段不匹配任何已注册组件

解决方案:

// 确保组件已正确注册到formItemElementMap
const customWidgetMap = {
myCustomComponent: MyCustomComponent
}

// 在DyForm中使用
<DyForm
customWidgetMap={customWidgetMap}
formItemProps={schema}
/>

2. 选择器选项不显示

问题: optionData或options属性为空

解决方案:

// 确保选项数据正确传递
<Select
optionData={computedOptions}
v-model={selectedValue}
/>

3. 日期范围验证失效

问题: 时间范围验证逻辑未正确执行

解决方案:

// 添加自定义验证规则
const customRules = [
{
validator: (rule, value, callback) => {
if (value.From && value.To && dayjs(value.From).isAfter(value.To)) {
callback(new Error('开始时间不能晚于结束时间'))
} else {
callback()
}
},
trigger: 'change'
}
]

章节来源

总结

LMEs Web Base的表单与选择组件系统展现了现代前端开发的最佳实践。通过DyForm动态表单引擎的JSON Schema驱动架构、Select组件系统的双重实现策略、以及DateTimePickRange的响应式集成,该系统提供了完整的表单解决方案。

关键特性包括:

  • 灵活的动态表单渲染:支持多种表单控件类型的JSON Schema驱动渲染
  • 强大的选择器系统:提供自研增强型和Element Plus封装两种选择
  • 深度响应式集成:充分利用Vue 3的响应式系统特性
  • 国际化支持:完整的多语言环境适配
  • 性能优化:合理的组件缓存和渲染策略

这套组件系统不仅满足了当前业务需求,还为未来的功能扩展和性能优化奠定了坚实的基础。