react+antd 开发一个可动态增减的复合组件

2023-03-14,,

需求如图:

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

组件代码:

/* 阶梯分成组件 */
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 开发一个可动态增减复合组件的相关教程结束。

《react+antd 开发一个可动态增减的复合组件.doc》

下载本文的Word格式文档,以方便收藏与打印。