需求如图:

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

组件代码:

/* 阶梯分成组件 */
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. vue3 门户网站搭建1-路由

    从 0 到 1搭建门户网站,记录一下. 因为需求不大,所以比较简单,门户和后台管理直接一个项目出来,路由配置则想的是: 1.门户,用  /portal 标识 2.后台管理,用 /admin 标识 3. ...

  2. etcd 入门

    服务注册与服务发现 三部分的作用: 注册中心:记录服务和服务地址的映射关系 服务提供者:将服务注册到服务中心 服务发现者:对服务中心的服务进行调用 简单易懂的 raft 算法 Raft算法是一个一致性 ...

  3. git学习资料汇总

    学习持续开发和持续继承CI/CD  https://zhuanlan.zhihu.com/p/609519307 git工作流主题 https://github.com/oldratlee/trans ...

  4. Vue 事件监听

    事件监听 v-on 使用v-on进行事件绑定监听,回调函数写在methods中.可以使用@的这种简写形式来代替v-on,当事件源无参数传递时,可省略括号. 语法如下所示: <button @:事 ...

  5. 网络-6 IPV6(上)

    一.iPv4与ipv6对比 1.ipv4与ipv6优缺点 1.1 Ipv4与ipv6对比,ipv4中的切片使用的三个字段:identification   flags   fragment offse ...

  6. ansible笔记第二章(ansible-varable变量)

    (1)变量类型 1.1在playbook文件中的play使用变量 [root@m01 project1]# cat vars_1.yml - hosts: oldboy vars:   - web_p ...

  7. ucocIII野火

    5.1裸机系统 5.1.1 轮询系统 轮询系统即是在裸机编程的时候,先初始化好相关的硬件,然后让主程序在一个死循环里面不断循环,顺序地做各种事情.轮询系统是一种非常简单的软件结构,通常只适用于那些只需 ...

  8. 已知内存BUF单元开始的区域中存放有一组无符号字节数据,要求将这些数据按从小到大的顺序排列,排序后的数据依然放在原来的存储区中。

    设计要求: 已知内存BUF单元开始的区域中存放有一组无符号字节数据,要求将这些数据按从小到大的顺序排列,排序后的数据依然放在原来的存储区中.(10分) #make_BIN# BUF DB 22,21, ...

  9. BUUCTF-[GXYCTF2019]Ping Ping Ping

    一道命令执行题目    一.基础知识  Linux shell特殊字符(参考链接) [;]作为多个命令语句的分隔符(Command separator [semicolon]). 要在一个语句里面执行 ...

  10. java okio 找不到的问题

    问题描述: okio 找不到的问题 解决办法: 下载 jar_files.zip 在idea-File-Project Structure- Project Settings - Libraries ...