需求如图:

与后端协商好的表单数据为:

组件代码:

/* 阶梯分成组件 */
import React, { useState, useEffect } from 'react';
import { message, InputNumber, Button } from 'antd';
import { PlusOutlined, DeleteOutlined } from '@ant-design/icons';
import styles from './Condition.less'; let rowKey = 0; type ConfigProps = {
unit?: string;
afterText?: string;
precision?: number;
key?: string;
}; const Condition: React.FC<any> = (props) => {
const { value, maxLength, config, onChange } = props;
const [dataList, setDataList] = useState<any[]>([{ rowKey }]); // 新增
const handleAdd = () => {
if (dataList && dataList.length <= maxLength) {
if (!rowKey) rowKey = dataList.length || 0;
rowKey += 1;
const keyObj = {};
config.map((item: ConfigProps) => {
if (item.key) keyObj[item.key] = undefined;
});
const newObj = { ...keyObj, rowKey };
setDataList([...dataList, newObj]);
if (onChange) {
onChange([...dataList, newObj]);
}
} else {
message.error('已达添加上限');
}
}; // 删除
const handleDelete = (_key: any) => {
setDataList(dataList.filter((it: any) => it.rowKey !== _key));
if (onChange) {
onChange(dataList.filter((it: any) => it.rowKey !== _key));
}
}; // 要求整数
// const limitDecimals = (values?: string | number | undefined) => {
// if (values) return String(values).replace(/^(0+)|[^\d]+/g, '');
// return '';
// }; // 改变值
const handleNumber = (_value: number | string | null, data: any, key: string) => {
const newList = dataList.map((it) => {
if (it.rowKey === data.rowKey) {
return { ...it, [key]: _value };
}
return it;
});
setDataList(newList);
if (onChange) {
onChange(newList);
}
}; // 监听默认值更新
useEffect(() => {
if (value && value.length > 0) {
setDataList(value);
}
}, []); return (
<div
className={styles['m-condition']}
style={{
maxHeight: dataList.length > 10 ? '432px' : 'auto',
overflowY: dataList.length > 10 ? 'scroll' : 'auto',
}}
>
{dataList &&
dataList.map((item: any, index: number) => (
<div key={`${item.rowKey}${item.tips}`} style={{ marginBottom: '8px' }}>
<div
style={{
width: '100%',
display: 'flex',
justifyContent: 'flex-start',
alignItems: 'center',
}}
>
{config?.map((itemConfig: any, indexConfig: number) => {
return (
<span
key={itemConfig.afterText}
style={{ display: 'inline-flex', alignItems: 'center' }}
>
<InputNumber
max={
indexConfig === 0 ? item[config[1].key] || itemConfig.max : itemConfig.max
}
min={
indexConfig === 1 ? item[config[0].key] || itemConfig.min : itemConfig.min
}
style={{
width: '140px',
marginLeft: indexConfig === 0 ? 0 : '8px',
marginRight: '8px',
}}
precision={itemConfig.precision}
placeholder={'请输入'}
value={itemConfig.num}
onChange={(values) => handleNumber(values, item, itemConfig.key)}
key="NumberMin"
addonAfter={itemConfig.unit}
/>
<span>{itemConfig.afterText}</span>
</span>
);
})}
<DeleteOutlined
onClick={() => handleDelete(item.rowKey)}
style={{ marginLeft: '8px', visibility: index === 0 ? 'hidden' : 'visible' }}
/>
</div>
</div>
))}
<Button
type="dashed"
onClick={handleAdd}
style={{ width: '100%' }}
icon={<PlusOutlined />}
disabled={maxLength && dataList && dataList.length && dataList.length >= maxLength}
>
新增阶梯
</Button>
</div>
);
}; export default Condition;

  

.m-condition {
&::-webkit-scrollbar {
width: 4px;
} &::-webkit-scrollbar-thumb {
background: #e3e8ee;
border-radius: 10px;
} &::-webkit-scrollbar-track-piece {
background: transparent;
}
}

  

引用:

在存储表单组件的dataSource数组时,遍历render:
if (el.id === 'xxx') {
return {
...el,
renderFormItem: () => <Condition />,
};
}

 

传递的数据格式为:

react+antd 开发一个可动态增减的复合组件的更多相关文章

  1. 【React】开发一个城市选择控件

    想到做这个,是因为无意中在github上看到了这一个仓库https://github.com/lunlunshiwo/ChooseCity,做的就是一个城市选择控件,是用vue写的,说的是阿里的一道题 ...

  2. React + Antd开发模式下的Excel导入功能

    具体js如下,配合的是antd里面的upload组件,使用的是xlsx插件 npm :  npm install xlsx 插件链接: https://github.com/SheetJS/sheet ...

  3. React Native 开发豆瓣评分(七)首页组件开发

    首页内容拆分 看效果图,首页由热门影院.豆瓣热门.热门影视等列表组成,每个列表又由头加横向滑动的 电影海报列表构成. 所以可以先把页面的电影海报.评分.列表头做成组件,然后在使用 ScrollView ...

  4. 放弃antd table,基于React手写一个虚拟滚动的表格

    缘起 标题有点夸张,并不是完全放弃antd-table,毕竟在react的生态圈里,对国人来说,比较好用的PC端组件库,也就antd了.即便经历了2018年圣诞彩蛋事件,antd的使用者也不仅不减,反 ...

  5. react+antd 使用脚手架动态修改主题色

    最近做了一个需求,后台管理系统添加一个可以动态修改ant-design主题色.查询了大多数的文章,发现基本都是抄来抄去,而且文章记录的也一点也不详细.刚刚把这个功能做完了,顺便记录一下如何去修改主题色 ...

  6. 从0到1用react+antd+redux搭建一个开箱即用的企业级管理后台系列(基础篇)

    背景 ​ 最近因为要做一个新的管理后台项目,新公司大部分是用vue写的,技术栈这块也是想切到react上面来,所以,这次从0到1重新搭建一个react项目架子,需要考虑的东西的很多,包括目录结构.代码 ...

  7. DECO 一个REACT NAtive 开发IDE工具

    DECO 一个REACT NAtive 开发IDE工具. 目前只支持 OS,NO WINDOWS https://www.decosoftware.com/ 一个方便的快速 ERXPRESS 教程:h ...

  8. 使用React、Node.js、MongoDB、Socket.IO开发一个角色投票应用的学习过程(三)

    这几篇都是我原来首发在 segmentfault 上的地址:https://segmentfault.com/a/1190000005040834 突然想起来我这个博客冷落了好多年了,也该更新一下,呵 ...

  9. (24/24) webpack小案例--自己动手用webpack构建一个React的开发环境

    通过前面的学习,对webpack有了更深的认识,故此节我们就利用前面相关知识自己动手用webpack构建一个React的开发环境,就算是一个小案例吧. 注:此处使用的开发工具是Webstorm. 1. ...

  10. react + react-router + less +antd 开发环境

    react + react-router + less +antd 开发环境搭建 1.基于create-reacte-app,需要先安装这个脚手架,然后初始化项目. 2.进入项目目录,首先 npm r ...

随机推荐

  1. Mac连接交换机

    接上免驱动的绿联,可以看到有一个usb串口设备: ls /dev/tty.* /dev/tty.Bluetooth-Incoming-Port /dev/tty.usbserial-AB0LU5PY ...

  2. Charles抓包工具详解

    学习Charles能做什么: 能够用charles分析前后端问题 能够使用charles模拟弱网测试环境 能够使用charles断点构建异常的测试环境 Charles 简介 1.Charles是什么? ...

  3. Raize

    Raize.v5和Raize.v6 本人在windows10下装有delphi7和delphi2010,安装好Raize.v6后,两个版本delphi的控件页都找不到Raize控件,即使想编译相应的D ...

  4. Chart控件-常用设置

    visual studio中原生控件chart控件使用时的一些常用设置 鼠标缩放功能 缩放后恢复曲线

  5. [转]idea 试用30天“无限续费”idea破解

    首先打开idea设置 左上角点击file-->setting-->Plugins   https://plugins.zhile.io 然后点击 确定 ("OK") 点 ...

  6. 操作系统实战45讲笔记- 07 Cache与内存:程序放在哪儿?

    程序局部性原理: CPU 大多数时间在执行相同的指令或者与此相邻的指令 时间局部性VS空间局部性: a. 时间局部性:当前访问的指令或数据,也可能在之后访问: b. 空间局部性:当程序访问内存地址x时 ...

  7. Java Swing 防止键入手Key 的实现方法

    实现思路,启动一个线程每隔0.1秒去比较文本里字符长度变化,如果文本变长了,这个情况间隔时间超过2秒,则认为是人工键入. 对于字符串较多,且包含数字和字母的情况,比较适用. class KeyCode ...

  8. HOLIscapes使用条款与免责协议

    HOLIscapes(以下简称"我们")在此特别提醒您务必认真阅读.充分理解本<使用条款与免责协议>(以下简称"本协议")中各条款并选择是否接受本协 ...

  9. sudo apt update 没有 Release 文件

    注: 不同环境出错原因可能不同,本文仅供参考. 今天在Ubuntu 19.04 系统运行指令 sudo apt update 时,忽然提示错误,报错如下: 404 Not Found [IP: 101 ...

  10. Verilog仿真遇到的问题

    1.Vivado 15.4仿真时编译没有报错,但是仿真不成功,逻辑很简单,full为高电平时,rd_en要拉高,但全程没有拉高! 检查语法发现语句" else if( empty == 'b ...