Skip to content

Instantly share code, notes, and snippets.

@KiligFei
Created June 16, 2021 08:37
Show Gist options
  • Save KiligFei/6d02a5cfc36b5dccdfaa7297fb05e161 to your computer and use it in GitHub Desktop.
Save KiligFei/6d02a5cfc36b5dccdfaa7297fb05e161 to your computer and use it in GitHub Desktop.
[Tree] 文件夹菜单树 #Recat
import React, { useState } from 'react';
import { Tree } from 'antd';
import { EditOutlined, PlusOutlined, MinusOutlined, CloseOutlined, CheckOutlined } from '@ant-design/icons';
import { nanoid } from 'nanoid';
const { TreeNode } = Tree;
const treeData = [
{
value: '0',
defaultValue: '0',
key: '0',
isEditable: false,
children: [
{
value: '0-1',
key: '0-1',
defaultValue: '0-1',
isEditable: false,
},
{
value: '0-2',
key: '0-2',
defaultValue: '0-2',
isEditable: false,
},
],
},
];
const expandedKeyArr = ['0'];
export default function FileTree () {
const [data, setData] = useState(treeData);
const [expandedKeys, setExpandedKeys] = useState(expandedKeyArr);
const onExpand = (expandedKeys) => {
// 记录折叠的key值
setExpandedKeys(expandedKeys);
};
const renderTreeNodes = (data) => {
let nodeArr;
nodeArr = data.map((item) => {
item.parentKey = undefined;
if (item.isEditable) {
item.title = (
<div>
<input value={item.value || ''} onChange={(e) => onChange(e, item.key)} />
<CloseOutlined
style={{ marginLeft: 10 }} onClick={() => onClose(item.key, item.defaultValue)}
/>
<CheckOutlined style={{ marginLeft: 10 }} onClick={() => onSave(item.key)} />
</div>
);
} else {
item.title = (
<div>
<span>{item.value}</span>
<span>
<EditOutlined style={{ marginLeft: 10 }} onClick={() => onEdit(item.key)} />
<PlusOutlined style={{ marginLeft: 10 }} onClick={() => onAdd(item.key)} />
{item.parentKey === '0' ? null : <MinusOutlined
style={{ marginLeft: 10 }} onClick={() => onDelete(item.key)}
/>}
</span>
</div>
);
}
if (item.children) {
return (
<TreeNode title={item.title} key={item.key} dataRef={item}>
{renderTreeNodes(item.children)}
</TreeNode>
);
}
return <TreeNode title={item.title} key={item.key} />;
});
return nodeArr;
};
const onAdd = (key) => {
if (expandedKeys.indexOf(key) === -1) {
expandedKeyArr.push(key);
}
setExpandedKeys(expandedKeyArr.slice());
addNode(key, treeData);
// useState里数据务必为immutable (不可赋值的对象),所以必须加上slice()返回一个新的数组对象
setData(treeData.slice());
};
const onEdit = (key) => {
editNode(key, treeData);
setData(treeData.slice());
};
const editNode = (key, data) =>
data.forEach((item) => {
item.isEditable = item.key === key;
item.value = item.defaultValue; // 当某节点处于编辑状态,并改变数据,点击编辑其他节点时,此节点变成不可编辑状态,value 需要回退到 defaulted
if (item.children) {
editNode(key, item.children);
}
});
const addNode = (key, data) =>
data.forEach((item) => {
if (item.key === key) {
if (item.children) {
item.children.push({
value: 'default',
key: nanoid(), // 这个 key 应该是唯一的
});
} else {
item.children = [];
item.children.push({
value: 'default',
key: nanoid(),
});
}
return;
}
if (item.children) {
addNode(key, item.children);
}
});
const onChange = (e, key) => {
changeNode(key, e.target.value, treeData);
setData(treeData.slice());
};
const changeNode = (key, value, data) =>
data.forEach((item) => {
if (item.key === key) {
item.value = value;
}
if (item.children) {
changeNode(key, value, item.children);
}
});
const onSave = (key) => {
saveNode(key, treeData);
setData(treeData.slice());
};
const saveNode = (key, data) =>
data.forEach((item) => {
if (item.key === key) {
item.defaultValue = item.value;
}
if (item.children) {
saveNode(key, item.children);
}
item.isEditable = false;
});
const onClose = (key, defaultValue) => {
closeNode(key, defaultValue, treeData);
setData(treeData);
};
const closeNode = (key, defaultValue, data) =>
data.forEach((item) => {
item.isEditable = false;
if (item.key === key) {
item.value = defaultValue;
}
if (item.children) {
closeNode(key, defaultValue, item.children);
}
});
const onDelete = (key) => {
deleteNode(key, treeData);
setData(treeData.slice());
};
const deleteNode = (key, data) =>
data.forEach((item, index) => {
if (item.key === key) {
data.splice(index, 1);
} else {
if (item.children) {
deleteNode(key, item.children);
}
}
});
return (
<div>
<Tree expandedKeys={expandedKeys} onExpand={onExpand}>
{renderTreeNodes(data)}
</Tree>
</div>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment