基于react hooks,antd4 配置生成表单并自动排列
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个表单项 https://ant.design/components/grid-cn/)
基于24 栅格系统,可以我们计算出每个组件占用的栅格数24/n , 基于此,我们可以动态创建Grid,自上而下一行一组进行render实现一行多列布局 ,伪代码如下
const len = group.length;
const span = 24 / len;
return (
<Row key={idx}>
{arr.map((item, subIndex) => itemRender(item, subIndex, span))}
</Row>
);
上述 itemRender 用于render表单组件, antd4表单项通常这么写 ,一个Form.Item 包裹一个表单控件,参考如下
<Form.Item
label="Username"
name="username"
rules={[{ required: true, message: 'Please input your username!' }]}
>
<Input />
</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<string, unknown>; // 组件的props配置 , 比如type为Input, elProps则会配置到Input
itemProps?: Record<string, unknown>; // 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 (
<Col span={span} key={key}>
<Form.Item name={name} label={label} rules={rules} {...itemProps}>
{React.createElement(type, { ...props, ...elProps } as React.Attributes)}
</Form.Item>
</Col>
);
};
为了更方便实现表单联动和支持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<string, unknown>; // 组件的props配置 , 比如type为Input, elProps则会配置到Input
itemProps?: Record<string, unknown>; // Form.Item的props配置,除了上面name,lable,rules三个常用的,其他的可以放在这里配置
rules?: Rule[]; // Form.Item的rules
};
自此, 一个通用的antd form-render 就编写完了, 可以参考https://github.com/leonwgc/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 (
<Form.Item>
<Space>
<Button htmlType="submit" type="primary">
确定
</Button>
<Button htmlType="reset">重置</Button>
</Space>
</Form.Item>
);
},
},
];
return (
<Form
form={form}
onValuesChange={(v) => {
setData((p) => ({ ...p, ...v }));
}}
>
<FormRender layoutData={layout} />
</Form>
);
}
实现 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}`,
});
}
<FormRender layoutData={layout3} cols={cols}></FormRender>;
配置说明
// 组件
export default function FormRenderer({ layoutData, cols }: FormRenderProps): React.ReactNode;
// 组件props
export declare type FormRenderProps = {
layoutData: Array<Item>; // 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<string, unknown>; // 组件的props配置 , 比如type为Input, elProps则会配置到Input
itemProps?: Record<string, unknown>; // Form.Item的props配置,除了上面name,lable,rules三个常用的,其他的可以放在这里配置
rules?: Rule[]; // Form.Item的rules
};
运行示例, yarn start / npm start 查看 demo , 效果如下
基于react hooks,antd4 配置生成表单并自动排列的更多相关文章
- 基于React和Node.JS的表单录入系统的设计与实现
一.写在前面 这是一个真实的项目,项目已经过去好久了,虽然很简单,但还是有很多思考点,跟随着笔者的脚步,一起来看看吧.本文纯属虚构,涉及到的相关信息均已做虚构处理, 二.背景 人活着一定要有信仰,没有 ...
- 基于PHP和mysql的自动生成表单
开发背景:公司要求管理系统能够由管理员在前台页面管理系统表单,能够对表单进行增删改查基本操作,表单的各个字段都可以被修改.删除,可以添加新的字段,并且不影响系统正常运行,前台表单展示要由系统自动处理, ...
- Swift3.0服务端开发(二) 静态文件添加、路由配置以及表单提交
今天博客中就来聊一下Perfect框架的静态文件的添加与访问,路由的配置以及表单的提交.虽然官网上有聊静态文件的访问的部分,但是在使用Perfect框架来访问静态文件时还是有些点需要注意的,这些关键点 ...
- vue自定义表单生成器,可根据json参数动态生成表单
介绍 form-create 是一个可以通过 JSON 生成具有动态渲染.数据收集.验证和提交功能的表单生成器.并且支持生成任何 Vue 组件.结合内置17种常用表单组件和自定义组件,再复杂的表单都可 ...
- yii2自动生成表单
视图中: 1.要use的两个文件类 use yii\helpers\Html; use yii\widgets\ActiveForm; 2.生成表单,以添加商品为例说明.注意红线区域:上传文件需要 ...
- 表单组件 form fastadmin(生成表单元素)
Form组件 定义文件位置: /extend/fast/Formphp 通用参数 $name 通常为我们组件的名称(name属性值),我们在后台接收时可以通过这个名称来获取到它所对应的值 $value ...
- 基于jQuery会员中心安全修改表单代码
基于jQuery会员中心安全修改表单代码.这是一款登录密码,交易密码,手机号码,实名认证,电子邮箱,安全设置表单,会员表单等设置代码.效果图如下: 在线预览 源码下载 实现的代码. html代码: ...
- 一款基于jquery ui的动画提交表单
今天要给大家分享一款基于jquery ui的动画提交表单.这款提交表单的的效果是以动画的形式依次列表所需填写的信息.效果非常不错,效果图如下: 在线预览 源码下载 实现的代码. html代码: & ...
- java自动生成表单简单实例
数据库表设置 tb_form(form表单) 字段 类型 约束 说明 Id Int 主键 主键 Formid Varchar2(20) 唯一 Form表单id的值 Action Varchar2(20 ...
随机推荐
- 解决.NET Core Ajax请求后台传送参数过大请求失败问题
解决.NET Core Ajax请求后台传送参数过大请求失败问题 今天在项目上遇到一个坑, 在.Net Core中通过ajax向mvc的controller传递对象时,控制器(controller)的 ...
- Kotlin/Java Base64编码和解码(图片、文件)
原文: Kotlin/Java Base64编码和解码(图片.文件) | Stars-One的杂货小窝 最近在项目中使用到了Base64编码和解码,便是稍微写篇文章记录一下 PS:本文代码都是使用Ko ...
- vue 弹窗禁止底层滚动
原因:底层视图高度超出百分百,加入弹窗后再苹果浏览器隐藏上下栏的情况下遮罩层没有完全遮住底层. 处理:打开弹窗后禁止底层滚动调用stop事件,关闭则开启底层滚动调用move事件. let mo=fun ...
- python之Click的简单应用
一.介绍 Click是一个Python包,用于以可组合的方式创建漂亮的命令行界面,只需要很少的代码.这是"命令行界面创建工具包".它具有高度可配置性,但具有开箱即用的合理默认值. ...
- 平方十位数(蓝桥杯第八届国赛真题 JAVA-B组)
思路:从大到小枚举,判断其平方是否不重复 答案:9814072356 //水题 标题:平方十位数 由0~9这10个数字不重复.不遗漏,可以组成很多10位数字. 这其中也有很多恰好是平方数(是某个数的平 ...
- java例题_11 求不重复数
1 /*11 [程序 11 求不重复数字] 2 题目:有 1.2.3.4 这四个数字,能组成多少个互不相同且无重复数字的三位数?都是多少? 3 程序分析:可填在百位.十位.个位的数字都是 1.2.3. ...
- 配置IIS虚拟站点(5)
开发完ASP.NET网站后,想要直接浏览,不通过开发环境,那么就需要配置IIS虚拟站点 1.开始菜单->控制面板->所有控制面板->管理工具->双击打开Internet信息服务 ...
- 【Java】8.0 数组及其操作
[概述] 有时候,我们需要某类的变量,它们是用于表达同一类的东西,但每个个体有不一样,比如学生成绩表的各个成绩 我们不可能为每个学生单独建立一个int变量来表示成绩,此时我们可以创建一个数组,再把每个 ...
- [源码解析] 并行分布式任务队列 Celery 之 多进程模型
[源码解析] 并行分布式任务队列 Celery 之 多进程模型 目录 [源码解析] 并行分布式任务队列 Celery 之 多进程模型 0x00 摘要 0x01 Consumer 组件 Pool boo ...
- [Python]import使用的疑难杂症与包管理
概念:模块与包 模块module:一般是以.py为后缀的文件,也包括.pyo..pyc..pyd..so和.dll后缀的文件,模块内定义了函数.类以及变量 包package:包是含有若干个模块的文件夹 ...