1. 功能说明
基于antd Tree,实现了可编辑菜单树,支持以下功能:
- 树节点 新增、删除、修改(input输入)
- 树节点 拖拽调整顺序
2. 效果
3. 完整代码
import React, { useState, useEffect } from 'react';
import { Modal, Button, Form, Input, Select, Checkbox, Divider, Tree, Message } from 'antd';
import { PlusOutlined, CloseOutlined } from '@ant-design/icons';
const { TreeNode } = Tree;
var tempKey = '1000';
const App = (props) => {
const { onHandleCancel = () => {}, onHandleOk = () => {}, data = {} } = props;
var treeDataTemp = [
{
title: '0-0',
key: '0-0',
children: [
{
title: '0-0-0',
key: '0-0-0',
children: [
{
title: '0-0-0-0',
key: '0-0-0-0'
},
{
title: '0-0-0-1',
key: '0-0-0-1'
}
]
},
{
title: '0-0-2',
key: '0-0-2'
}
]
},
{
title: '0-2',
key: '0-2'
}
];
const [treeData, setTreeData] = useState(treeDataTemp);
const onDragEnter = (info) => {
console.log(info);
};
const onDrop = (info) => {
console.log(info);
const dropKey = info.node.key;
const dragKey = info.dragNode.key;
const dropPos = info.node.pos.split('-');
const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1]);
const loop = (data, key, callback) => {
for (let i = 0; i < data.length; i++) {
if (data[i].key === key) {
return callback(data[i], i, data);
}
if (data[i].children) {
loop(data[i].children, key, callback);
}
}
};
const data = [...treeData];
let dragObj;
loop(data, dragKey, (item, index, arr) => {
arr.splice(index, 1);
dragObj = item;
});
if (!info.dropToGap) {
loop(data, dropKey, (item) => {
item.children = item.children || [];
item.children.unshift(dragObj);
});
} else if (
(info.node.props.children || []).length > 0 &&
info.node.props.expanded &&
dropPosition === 1
) {
loop(data, dropKey, (item) => {
item.children = item.children || [];
item.children.unshift(dragObj);
});
} else {
let ar;
let i;
loop(data, dropKey, (item, index, arr) => {
ar = arr;
i = index;
});
if (dropPosition === -1) {
ar.splice(i, 0, dragObj);
} else {
ar.splice(i + 1, 0, dragObj);
}
}
setTreeData([...data]);
console.log('data2', data);
};
const onAdd = (key) => {
console.log('onAdd', key);
var treeDataOld = JSON.parse(JSON.stringify(treeData));
var treeDataNew = addNode(key, treeDataOld);
setTreeData(treeDataNew);
tempKey++;
function addNode(key, data) {
data.forEach((item) => {
if (item.key === key) {
item.children
? item.children.push({
title: `默认值${tempKey}`,
key: `${tempKey}`
})
: (item.children = [
{
title: `默认值${tempKey}`,
key: `${tempKey}`
}
]);
} else {
if (item.children) {
addNode(key, item.children);
}
}
});
return data;
}
};
const onDelete = (key) => {
console.log('onAdd', key);
var treeDataOld = JSON.parse(JSON.stringify(treeData));
var treeDataNew = deleteNode(key, treeDataOld);
setTreeData(treeDataNew);
function deleteNode(key, arr) {
arr.map((item, index) => {
if (item.key == key) {
arr.splice(index, 1);
}
if (item.children) {
deleteNode(key, item.children);
}
});
return arr;
}
};
const onChange = (e, key) => {
console.log('onChange', e, key);
var treeDataOld = JSON.parse(JSON.stringify(treeData));
var treeDataNew = editNode(key, treeDataOld, e.target.value);
setTreeData(treeDataNew);
function editNode(key, data, val) {
data.forEach((item) => {
if (item.key === key) {
item.title = val;
} else {
if (item.children) {
editNode(key, item.children, val);
}
}
});
return data;
}
};
const renderTreeNodes = (data) => {
console.log('renderTreeNodes', data);
return data.map((item) => {
if (item.children) {
return (
<TreeNode title={item.title} key={item.key}>
{renderTreeNodes(item.children)}
</TreeNode>
);
}
return <TreeNode {...item}></TreeNode>;
});
};
const onTitleRender = (item) => {
return (
<div style={{ display: 'flex', alignItems: 'center' }}>
<Input
defaultValue={item.title}
onChange={(e) => onChange(e, item.key)}
/>
<span style={{ display: 'flex' }}>
<PlusOutlined style={{ marginLeft: 10 }} onClick={() => onAdd(item.key)} />
<CloseOutlined style={{ marginLeft: 10 }} onClick={() => onDelete(item.key)} />
</span>
</div>
);
};
return (
<>
<Modal
title={data?.header}
visible={true}
onOk={() => handleOk()}
onCancel={() => onHandleCancel(false)}
okText="确认"
cancelText="取消"
maskClosable={false}
>
<Tree
className="draggable-tree"
defaultExpandAll={true}
draggable
onDragEnter={onDragEnter}
onDrop={onDrop}
titleRender={onTitleRender}
>
{treeData?.length && renderTreeNodes(treeData)}
</Tree>
</Modal>
</>
);
};
export default App;
|