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. 关于redis缓存数据库的一些思考

    今晚无聊,躺在床上,在刷技术文章时,看见了一篇关于redis缓存的文章 写的蛮好,这也就引起了我对于redis思考! 不如往深了说 引起了我对于追求探索技术本质的一些思考 平时在网上刷到很多关于red ...

  2. Codeforces Round #574 (Div. 2) D1. Submarine in the Rybinsk Sea (easy edition) 【计算贡献】

    一.题目 D1. Submarine in the Rybinsk Sea (easy edition) 二.分析 简单版本的话,因为给定的a的长度都是定的,那么我们就无需去考虑其他的,只用计算ai的 ...

  3. golang 并发运算时主线程先运行完,子线程运行没结束的问题记录

    代码如下: blocks,err:= mgo.FindBlocks(batch) //获得当前批次下的矿体信息 cubes:= BlockCutting(blocks[0],x,y,z,nest) f ...

  4. 10、字典dict

    字典(dict) 字典是有序,键不重复,元素只能是键值对的可变的容器 dict = {'k1':'v1','k2':'v2'} 容器 元素必须键值对 键不重复,重复则会被覆盖 data = {'k1' ...

  5. 十分钟学会Scratch图形化编程

    一.概要 Scratch是麻省理工学院开发的供儿童或者初学者学习编程的开发平台.其通过点击并拖拽的方式,完成编程,可以使儿童或者成人编程初学者学习编程基础概念等.Scratch是一款积木式图形编程软件 ...

  6. io流(File类)

    File类 创建一个file类(没有无参构造)的对象,并与文件进行关联 用File类来操作文件,代码如下: package com.bjsxt.test01; import java.io.File; ...

  7. The League of Sequence Designers Gym - 102460E

    题目链接:https://vjudge.net/problem/Gym-102460E 思路:求: 题目当中给了一段伪代码算法,仔细一看发现它是不会记录负数情况,所以与正确答案会有误差,现在题目给定K ...

  8. ch1_6_7求解数字排序问题

    import java.util.Arrays; import java.util.Comparator; import java.util.HashMap; import java.util.Sca ...

  9. P1085_不高兴的津津(JAVA语言)

    package 顺序与分支; /* * 题目描述 津津上初中了.妈妈认为津津应该更加用功学习,所以津津除了上学之外, 还要参加妈妈为她报名的各科复习班.另外每周妈妈还会送她去学习朗诵.舞蹈和钢琴. 但 ...

  10. 想了解FlinkX-Oracle Logminer?那就不要错过这篇文章

    FlinkX-Oracle Logminer模块是FlinkX基于Logminer对Oracle重做日志进行实时采集分析,可对Oracle进行实时同步也可以通过指定SCN或者时间戳从某个节点进行同步, ...