ModalForm组件:
const formRef = useRef<any>();<ModalFormkey={51}title='数据仓库'formRef={formRef} // 用于获取表单数据autoFocusFirstInput // 自动对话框打开后,首个表单项自动获得焦点width="33%"modalProps={{ // 扩展ant modal属性destroyOnClose: true, // 关闭时销毁 Modal 里的子元素onCancel: () => setVisible(false), // 取消按钮回调open: visible, // 对话框是否可见afterClose: async () => {const res = await getTreeNodes();if (res.status === 'success') {if (JSON.stringify(res?.data) != '{}') { // 判断数据源是否为空对象setVisible(false);} else {setVisible(true);message.error('请先添加数据源');}}},// 关闭后的回调maskClosable: false, // 点击蒙层是否允许关闭}}onFinish={async (values) => {const res = await getDataSource(dataSourceId);if (res.code === 200) {setVisible(false);// 更新树getTreeData();message.success('切换成功');}}}// 开启grid布局layout="horizontal"grid={true}><ProFormGroup><ProFormSelectkey={52}label="数据源类型"name="originType"placeholder="请选择"rules={[{ required: true }]}labelCol={{ span: 4 }}options={dataType2}initialValue={dataList?.dsType}fieldProps={{onChange: (value, option:any) => {// 通过formRef.current?.setFieldsValue来清除某个表单项的值formRef.current?.setFieldsValue({origin: undefined,});setDatatype3([]);GainDataSource(value);},}}/></ProFormGroup><ProFormGroup><ProFormSelectkey={53}label="数据源"name="origin"placeholder="请选择"rules={[{ required: true }]}labelCol={{ span: 4 }}options={dataType3}initialValue={dataList?.dsName}fieldProps={{onChange: (value, option:any) => {setDataSourceId(value);},}}/></ProFormGroup></ModalForm>
通过 Input 组件实现: 可新增,编辑,删除的tag组件:
// 这里是封装的Tags.tsx组件import {forwardRef, useImperativeHandle, useState} from 'react';
import {Button, Input, message} from "antd";
import { MinusCircleOutlined } from '@ant-design/icons';
import style from './index.less';
import {updateTableTag} from "@/pages/dataDev/metaMgr/service";const Tags = forwardRef((props, ref) => {const [tags, setTags] = useState<any>([]);const [parentTags, setParentTags] = useState<any>();const [tagName, setTagName] = useState<string>(''); // 输入框的值const [show, setShow] = useState<boolean>(true);const [show2, setShow2] = useState<boolean>(true);const [show3, setShow3] = useState<boolean>(false);const [show4, setShow4] = useState<boolean>(false);useImperativeHandle(ref, () => ({showModal: (record: any) => {setParentTags(record);if (record?.tags != null && record?.tags != '') {setTags(record?.tags.split('|'));} else {setTags([]);}}}));/*请求方法*/const Request = async (type:string,id:any,tags:any) => {const res = await updateTableTag({id:id, tags:tags});if (res.code == 200) {if (type == 'add') {message.success('保存成功');} else {message.success('删除成功');}props?.getList(); // 触发父组件的getList方法} else {if (type == 'add') {message.error('保存失败');} else {message.error('删除失败');}}}/*新增*/const addTag = () => {setShow2(false);setShow(false);setShow4(true);/*const newTags: any = {id: new Date().getTime() + 1 + '',name: tagName};*/const newTags: any = tagName;setTags([...tags, newTags]);setTagName('');}/*保存*/const saveTag = async () => {setShow(true);setShow2(true);setShow3(false);setShow4(false);const newTags = tags.filter((item:any) => item !== '');setTags(newTags);Request('add',parentTags?.id,newTags.join('|'));}/*删除*/const deleteTag = (value:any) => {const newTags = tags.filter((item:any) => item !== value);setTags(newTags);Request('delete',parentTags?.id,newTags.join('|'));}/*赋值*/const changeTag = (e:any, value:any) => {const newTags = tags.map((item:any) => {if (item == value) {item = e.target.value;}return item;})setTags(newTags);}/*取消*/const onCancel = () => {setShow(true);setShow2(true);setShow3(false);setShow4(false);const newTags = tags.filter((item:any) => item !== '');setTags(newTags);setTags(parentTags?.tags.split('|')); // 点击取消时, 将父组件的tags值还原}return (<div key={1} style={{margin: '2% 0'}}><div key={2} className={style.box}><span key={3} className={style.tagText}>标签: </span><div key={4} className={style.tagBox}>{tags?.map((item:any,index:any) => {return (<div key={index} style={{position: 'relative', margin: '0 6px'}}><Input key={6} size="small" value={item} disabled={show} style={{width: '100px'}} onChange={(e) => changeTag(e,item) } />{show2 == true ?<MinusCircleOutlined key={7} className={style.mco} onClick={() => {deleteTag(item);}} />: null}</div>)})}<Button key="add" size='small' type="ghost" disabled={show3} onClick={addTag}>+</Button><Button key="submit" size='small' type="dashed" disabled={show4} style={{margin: '0 8px'}} onClick={() => {setShow3(true);setShow(false);}}>编辑</Button><Button key="cancel" size='small' style={{marginRight: '8px'}} onClick={onCancel}>取消</Button><Button key="back" size='small' type="primary" onClick={saveTag}>保存</Button></div></div></div>);
});export default Tags;
核心代码:
// 因为react跟vue不一样,vue的数据可以双向绑定,但是react不可行,所以这里的input回显之后,再输入的话需要我们再处理一下/*Input赋值*/const changeTag = (e:any, value:any) => { // e.target.value是输入框的值const newTags = tags.map((item:any) => { // item是数组中的每一项if (item == value) { // 如果数组中的某一项等于输入框的值, 就将该项的值改为输入框的值item = e.target.value; // 将输入框的值赋值给数组中的某一项}return item; // 返回数组中的每一项})setTags(newTags); // 将新的数组赋值给tags}
// 父组件中使用 Tags.tsx组件import Tags from './Tags'; // 引入 Tags.tsxconst cRef = useRef<any>(null); // 用于获取子组件实例/*子组件触发*/
const getTags = () => {getTableInfo(tableId);
}// 在需要的地方进行调用
setTimeout(() => { // 这里的定时器是为了解决调用Tags组件时,Tags组件还没有创建,而引发的问题cRef.current?.showModal(res?.data); // 通过ref调用showModal方法,给标签组件传值
}, 50);// getList是父组件传递给子组件的方法 getTags是子组件传递给父组件的方法
<Tags key={50} ref={cRef} getList={getTags} />