ai写作网站南宁百度seo推广
目录
- 背景
- 方案设计
- 方案一:通过 `type` 字段判断渲染组件类型
- 思路
- 示例结构
- 优点
- 缺点
- 方案二:通过 itemRender 自定义组件渲染
- 思路
- 示例结构
- 优点
- 缺点
- 两者对比总结
- 综合建议
背景
我们已经有了 Select、Input、Radio 等基本表单组件。现在我们对于不同模块,如事件列表、属性列表、用户列表,它们都有一个通用筛选模块。这个筛选模块需要支持配置不同字段(包含 label、type、placeholder 等),对于事件列表,支持事件名称、事件类型、是否上线,对于属性列表,支持属性名称、属性类型…
方案设计
方案一:通过 type
字段判断渲染组件类型
思路
你定义一个统一的渲染组件,如 DynamicFormItem
,它根据配置项中传入的 type
(如 'input'
, 'select'
, 'radio'
等)自动渲染对应的 antd 组件。
示例结构
interface FieldConfig {label: string;name: string;type: 'input' | 'select' | 'radio';options?: { label: string; value: string }[];placeholder?: string;rules?: Rule[];
}const DynamicFormItem: React.FC<{ field: FieldConfig }> = ({ field }) => {const { type, label, name, options = [], ...rest } = field;const renderFormItem = () => {switch (type) {case 'input':return <Input placeholder={rest.placeholder} />;case 'select':return (<Select placeholder={rest.placeholder}>{options.map(opt => (<Select.Option key={opt.value} value={opt.value}>{opt.label}</Select.Option>))}</Select>);case 'radio':return (<Radio.Group>{options.map(opt => (<Radio key={opt.value} value={opt.value}>{opt.label}</Radio>))}</Radio.Group>);default:return null;}};return (<Form.Item label={label} name={name} rules={rest.rules}>{renderFormItem()}</Form.Item>);
};
优点
- 结构清晰,易于配置,适合低代码或表单配置系统。
- 增加新类型只需扩展
switch
或配置 map。 - 适用于统一风格、标准化表单。
缺点
- 灵活性较差,组件渲染逻辑由内部掌控,外部不可定制 UI。
- 处理复杂交互逻辑(如依赖联动、动态插槽)较为困难。
方案二:通过 itemRender 自定义组件渲染
思路
每个配置项支持传入一个 itemRender
方法,用于返回自定义的表单项组件,这种方式允许你完全控制每一项的渲染逻辑。
示例结构
interface FieldConfig {label: string;name: string;rules?: Rule[];itemRender?: () => React.ReactNode;
}const DynamicFormItem: React.FC<{ field: FieldConfig }> = ({ field }) => {const { label, name, rules, itemRender } = field;return (<Form.Item label={label} name={name} rules={rules}>{itemRender ? itemRender() : null}</Form.Item>);
};
优点
- 灵活性极高,支持所有 antd 控件、组合控件甚至第三方控件。
- 更适合高级场景(如复杂的嵌套表单、富文本、自定义行为等)。
- 渲染逻辑由使用者控制,组件更解耦、可组合性强。
缺点
- 配置方式更偏向开发者,门槛略高。
- 所有类型都需要手动写
itemRender
,可能重复。
两者对比总结
对比项 | 方案一:基于 type | 方案二:基于 itemRender |
---|---|---|
配置复杂度 | ✅ 低(适合配置表单) | ❌ 高(需要写渲染逻辑) |
灵活性 | ❌ 低 | ✅ 高 |
适用场景 | 表单类型有限、低代码平台 | 个性化表单、交互复杂 |
可维护性 | ✅ 可统一管理控件逻辑 | ❌ 分散在配置项中 |
扩展性 | 一定程度可扩展 | 完全可扩展 |
综合建议
你可以考虑 两者混用的折中方案:
interface FieldConfig {label: string;name: string;type?: 'input' | 'select' | 'radio';options?: any[];itemRender?: () => React.ReactNode;
}
优先用 itemRender
,如果没有就按 type
渲染,这样同时具备标准性和灵活性,适合中大型业务系统。