react后台项目,大多都是表单处理,比如下列4种常见1*n布局 (如果手工编码,大量的Row,Col, Form.Item的嵌套,排列,如果加上联动处理,代码将十分臃肿,不易维护)

  1. 一行一列

  2. 一行两列

  3. 一行三列

  4. 一行四列

对于这列表单开发, 完全可以基于配置生成, 我们可以定义一个数组,数组的每一项都是一个表单项, 对于一行一列的排列, 我们可以自上而下一行一个组件进行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 / yarn 安装:

$ 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 配置生成表单并自动排列的更多相关文章

  1. 基于React和Node.JS的表单录入系统的设计与实现

    一.写在前面 这是一个真实的项目,项目已经过去好久了,虽然很简单,但还是有很多思考点,跟随着笔者的脚步,一起来看看吧.本文纯属虚构,涉及到的相关信息均已做虚构处理, 二.背景 人活着一定要有信仰,没有 ...

  2. 基于PHP和mysql的自动生成表单

    开发背景:公司要求管理系统能够由管理员在前台页面管理系统表单,能够对表单进行增删改查基本操作,表单的各个字段都可以被修改.删除,可以添加新的字段,并且不影响系统正常运行,前台表单展示要由系统自动处理, ...

  3. Swift3.0服务端开发(二) 静态文件添加、路由配置以及表单提交

    今天博客中就来聊一下Perfect框架的静态文件的添加与访问,路由的配置以及表单的提交.虽然官网上有聊静态文件的访问的部分,但是在使用Perfect框架来访问静态文件时还是有些点需要注意的,这些关键点 ...

  4. vue自定义表单生成器,可根据json参数动态生成表单

    介绍 form-create 是一个可以通过 JSON 生成具有动态渲染.数据收集.验证和提交功能的表单生成器.并且支持生成任何 Vue 组件.结合内置17种常用表单组件和自定义组件,再复杂的表单都可 ...

  5. yii2自动生成表单

    视图中: 1.要use的两个文件类 use yii\helpers\Html;   use yii\widgets\ActiveForm; 2.生成表单,以添加商品为例说明.注意红线区域:上传文件需要 ...

  6. 表单组件 form fastadmin(生成表单元素)

    Form组件 定义文件位置: /extend/fast/Formphp 通用参数 $name 通常为我们组件的名称(name属性值),我们在后台接收时可以通过这个名称来获取到它所对应的值 $value ...

  7. 基于jQuery会员中心安全修改表单代码

    基于jQuery会员中心安全修改表单代码.这是一款登录密码,交易密码,手机号码,实名认证,电子邮箱,安全设置表单,会员表单等设置代码.效果图如下: 在线预览   源码下载 实现的代码. html代码: ...

  8. 一款基于jquery ui的动画提交表单

    今天要给大家分享一款基于jquery ui的动画提交表单.这款提交表单的的效果是以动画的形式依次列表所需填写的信息.效果非常不错,效果图如下: 在线预览   源码下载 实现的代码. html代码: & ...

  9. java自动生成表单简单实例

    数据库表设置 tb_form(form表单) 字段 类型 约束 说明 Id Int 主键 主键 Formid Varchar2(20) 唯一 Form表单id的值 Action Varchar2(20 ...

随机推荐

  1. Nebula Storage 2.0 存储格式

    随着 2.0 各版本的陆续发布,Nebula Graph 迎来了一系列的改动,在存储方面,影响最大的改动就是底层编码格式进行了修改.Nebula Graph 的底层存储是基于 KV 保存在 Rocks ...

  2. 说说SpringMVC从http流到Controller接口参数的转换过程

    一,前言 谈起springMVC框架接口请求过程大部分人可能会这样回答:负责将请求分发给对应的handler,然后handler会去调用实际的接口.核心功能是这样的,但是这样的回答未免有些草率.面试过 ...

  3. 关于Python编写时候的一些数据格式调用问题

    utf-8 可变长度字符串,互联网通用,目的是减少内存占用Unicode 万国码, 对于英文多占用一个字节ASCII码 美国编码1个字节Gb2313 中国编码 编码 encode解码 decodepy ...

  4. Java视频教程免费分享(网盘直接取)

    Java基础 Java马士兵:链接:https://pan.baidu.com/s/1jJRvxGi密码:v3xb Java刘意:链接:https://pan.baidu.com/s/1kVZQCqr ...

  5. Flutter学习简记

    StatefulWidget和StatelessWidget StatefulWidget : 具有可变状态的窗口部件,也就是你在使用应用的时候就可以随时变化,比如我们常见的进度条,随着进度不断变化. ...

  6. IDA F5 提示反编译失败,函数太大

    修改IDA安装目录\cfg\hexrays.cfg文件 文本方式打开,修改MAX_FUNCSIZE 的值(可修改为1024)

  7. Go 中的 gRPC 入门详解

    目录 Go GRPC 入门 1,安装包 2,gRPC 服务端 3,gRPC 客户端 4,编译运行 5,其它 GRPC Protobuf buffer 字段类型 字段规则 Protobuf gRPC 四 ...

  8. go每日一库 [home-dir] 获取用户主目录

    关于我 我的博客|文章首发 顾名思义,go-homedir用来获取用户的主目录.实际上,通过使用标准库os/user我们也可以得到内容,使用以下方式 标准库使用 package main import ...

  9. Recoil 中默认值的正确处理

    继续使用 Recoil 默认值及数据级联的使用 的地域可用区级联的例子. 地域变更后可用区随之联动,两个下拉框皆默认选中第一个可选项. 从 URL 获取默认值 考虑这种情况,当 URL 中带了 que ...

  10. Dynamics CRM邮箱配置

    Dynamics CRM对邮箱有很好的支持,开通邮箱后方便用户通过邮件进行Dynamics CRM的业务处理,同时也可以作为一直消息流提醒的手段应用于审批.通知等场景,可以做一些更深入的功能拓展. 本 ...