
基于react hooks,antd4 配置生成表单并自动排列
{React.createElement(type, { ...props, ...elProps } as React.Attributes)} );}; ); }, }, ]; return ( );}
发布日期:2021-05-09 04:22:27
浏览次数:10
分类:博客文章
本文共 6866 字,大约阅读时间需要 22 分钟。
react后台项目,大多都是表单处理,比如下列4种常见1*n布局 (如果手工编码,大量的Row,Col, Form.Item的嵌套,排列,如果加上联动处理,代码将十分臃肿,不易维护)
一行一列
一行两列
一行三列
一行四列
对于这列表单开发, 完全可以基于配置生成, 我们可以定义一个数组,数组的每一项都是一个表单项, 对于一行一列的排列, 我们可以自上而下一行一个组件进行render , 伪代码如下
return arr.map((item, idx) => itemRender(item, idx, 24))
对于一行n列 (n=2/3/4 , 参考antd grid布局, 一行最多不超过4个表单项 )
基于24 栅格系统,可以我们计算出每个组件占用的栅格数24/n , 基于此,我们可以动态创建Grid,自上而下一行一组进行render实现一行多列布局 ,伪代码如下const len = group.length; const span = 24 / len; return ({arr.map((item, subIndex) => itemRender(item, subIndex, span))}
);
上述 itemRender 用于render表单组件, antd4表单项通常这么写 ,一个Form.Item 包裹一个表单控件,参考如下
基于js我们可以抽离出如下配置项, 1. render什么组件,例如Input/Select/等,另外配置组件props 2. Form.Item 配置 , 我们可以设计如下通用js对象表示这些信息
{ type?: React.ComponentType | string; // 组件类型, 比如Input 等 name?: string; //Form.Item的name label?: string; // Form.Item的label elProps?: Record; // 组件的props配置 , 比如type为Input, elProps则会配置到Input itemProps?: Record ; // Form.Item的props配置,除了上面name,lable,rules三个常用的,其他的可以放在这里配置 rules?: Rule[]; // Form.Item的rules};
根据上面的js对象配置信息,我们可以实现itemRender动态创建组件和布局
const itemRender = (item: Item, key: number | string, span = 24) => { if (typeof item !== 'object' || !item) return null; const { type, name, rules, label, elProps = {}, itemProps = {}, render, ...props } = item; return (
为了更方便实现表单联动和支持render任意组件(不仅仅是表单), 我们可以扩展js加上render和getJSON 方法(当然叫getConfigJs更合适)
{ type?: React.ComponentType | string; // 组件类型, 比如Input 等 name?: string; //Form.Item的name label?: string; // Form.Item的label render?: () => React.ReactNode; //自定义 render getJSON?: () => Item | null; // 动态返回Item配置 elProps?: Record; // 组件的props配置 , 比如type为Input, elProps则会配置到Input itemProps?: Record ; // Form.Item的props配置,除了上面name,lable,rules三个常用的,其他的可以放在这里配置 rules?: Rule[]; // Form.Item的rules};
自此, 一个通用的antd form-render 就编写完了, 可以参考
安装
用 / 安装:
$ npm install --save antd-form-render$ yarn add antd-form-render
功能
- 配置一维数组实现 1 行 n 列 (自动布局,自上向下,自左向右布局,参考汽车自动挡驾驶) n可以是1/2/3/4 ,默认1
- 配置二维数组实现 1行n列 (手动布局,每一行显示几列根据数组长度决定,参考汽车手动挡驾驶)
- 天然支持表单联动 ,参考下面示例1性别选择代码
- 支持自定义render, 当antd组件无法满足需求,可以自定义返回任意react node
- 支持动态返回js对象, 参考下面示例1性别选择代码,性别男下面动态生成输入框,女则为下拉框
- 数据收集,name作为key ,相应表单控件的值为value
实现 1 行 1 列
import React, { useState } from 'react';import FormRender from 'antd-form-render';import { Form, Button, Space, Input, Radio, Select } from 'antd';export default function App() { const [data, setData] = useState({}); // 定义form const [form] = Form.useForm(); // 一维数组定义layout,从上往下一行放一个表单控件 const layout = [ { type: Input, label: '手机号', placeholder: '请输入', name: 'tel', // 对Input的配置 , elProps对type指定的组件配置 elProps: { maxLength: 11, }, // 对Form.Item的配置 itemProps: { rules: [ { required: true, message: '请输入' }, { pattern: /^1\d{10}$/, message: '手机号必须为11位数字' }, ], }, }, { type: Input.Password, label: '密码', placeholder: '请输入', name: 'pwd', itemProps: { rules: [{ required: true, message: '请输入' }], }, }, { type: Input.Password, label: '确认密码', placeholder: '请输入', name: 'confirmPwd', itemProps: { rules: [ { required: true, message: '请输入' }, ({ getFieldValue }) => ({ validator(_, value) { if (!value || getFieldValue('pwd') === value) { return Promise.resolve(); } return Promise.reject(new Error('两次密码不一致')); }, }), ], }, }, { type: Radio.Group, label: '性别', name: 'gender', elProps: { options: [ { label: '男', value: '男' }, { label: '女', value: '女' }, ], }, }, { // 根据条件动态返回object getJSON() { return data.gender === '男' ? { type: Input, label: '兴趣爱好(男)', placeholder: '请输入兴趣爱好', name: 'hobby', itemProps: { rules: [{ required: true, message: '请输入兴趣爱好' }], }, } : data.gender === '女' ? { type: Select, label: '兴趣爱好(女)', placeholder: '请选择兴趣爱好', name: 'hobby', itemProps: { itemProps: { rules: [{ required: true, message: '请选择兴趣爱好' }], }, }, elProps: { options: [ { label: '画画', value: '画画' }, { label: '唱歌', value: '唱歌' }, { label: '跳舞', value: '跳舞' }, ], }, } : null; }, }, { type: Input.TextArea, name: 'desc', label: '简介', elProps: { placeholder: '个人简介', rows: 4, }, itemProps: { rules: [ { required: true, }, ], }, }, { // 自定义render render() { return (
实现 1 行 n 列如下 ,比如一行 2 列(子数组的长度决定列数,长度能被 24 整除)
const layout = [ [ { type: Input, label: '11', placeholder: '请输入', name: '11', }, { type: Input, label: '12', placeholder: '请输入', name: '12', }, ], [ { type: Input, label: '21', placeholder: '请输入', name: '21', }, { type: Input, label: '22', placeholder: '请输入', name: '22', }, ],];
实现 1 行 2/3/4 列如下
// 一维数组,设置了cols 为1/2/3/4 ,实现自动从左至右,从上到下的 1*cols 1行多列自动布局const layout3 = [];for (let i = 0; i < 11; i++) { layout3.push({ type: Input, label: `输入框${i + 1}`, placeholder: '请输入', name: `name${i}`, });};
配置说明
// 组件export default function FormRenderer({ layoutData, cols }: FormRenderProps): React.ReactNode;// 组件propsexport declare type FormRenderProps = { layoutData: Array- ; // 1/2维数组 cols: null | 1 | 2 | 3 | 4; // 自动布局1行显示几列 default 1};// 数组配置项export declare type Item = { type?: React.ComponentType | string; // 组件类型, 比如Input 等 name?: string; //Form.Item的name label?: string; // Form.Item的label render?: () => React.ReactNode; //自定义 render getJSON?: () => Item | null; // 动态返回Item配置 elProps?: Record
; // 组件的props配置 , 比如type为Input, elProps则会配置到Input itemProps?: Record ; // Form.Item的props配置,除了上面name,lable,rules三个常用的,其他的可以放在这里配置 rules?: Rule[]; // Form.Item的rules};
运行示例, yarn start / npm start 查看 demo , 效果如下
发表评论
最新留言
能坚持,总会有不一样的收获!
[***.219.124.196]2025年03月24日 17时22分41秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
Java 读取Excel百分数保留原格式(即不转换为小数)的方法
2021-05-09
深度学习一:深度前馈网络和反向传播
2021-05-09
在wxPython使ListCtrl占据整个窗口
2021-05-09
微软面试题
2021-05-09
Google新玩法(转载)
2021-05-09
C#中Dispose和Close的区别!
2021-05-09
如何让服务在流量暴增的情况下保持稳定输出
2021-05-09
一个20年技术老兵的 2020 年度技术总结
2021-05-09
一例完整的websocket实现群聊demo
2021-05-09
SQLSERVER数据库死锁与优化杂谈
2021-05-09
【Net】ABP框架学习之它并不那么好用
2021-05-09
Git 笔记
2021-05-09
Harbor 批量清理历史镜像
2021-05-09
使用Azure Functions玩转Serverless
2021-05-09
.NET Core 基于Websocket的在线聊天室
2021-05-09
我们真的需要JWT吗?
2021-05-09
使用MySQL Shell创建MGR
2021-05-09
win10新版wsl2使用指南
2021-05-09
spring-boot 使用hibernate validation对参数进行优雅的校验
2021-05-09
关于我
2021-05-09