上代码:仅供参考哦~
import React, { useState, useEffect } from 'react'
import { Tree, Input, } from 'antd'
import {
PlusOutlined,
EditOutlined,
MinusOutlined,
CheckOutlined,
DeleteOutlined,
} from '@ant-design/icons'
import _ from 'lodash'
const { TreeNode } = Tree
export default props => {
const [expandedKeys, setExpandedKeys] = useState([])
const [treeData, setTreeData] = useState(props.data) // 业务需求传过来的数组
const [dataList, setDataList] = useState([]) // 存放扁平数据的数组
const [autoExpandParent, setAutoExpandParent] = useState(true)
// 调用扁平数组的方法
useEffect(() => {
generateList(treeData)
}, [expandedKeys])
// 展开时触发
const onExpand = (expandedKeys) => {
setExpandedKeys(expandedKeys)
setAutoExpandParent(false)
setDataList([])
}
// 添加子元素
const addNode = (key, data) =>
data.map((item) => {
if (item.key === key) {
if (item.children) {
item.children.push({
value: 'default',
defaultValue: 'default',
key: `${key}-${Math.random(100)}`,
parentKey: key,
isEditable: false,
})
} else {
item.children = []
item.children.push({
value: 'default',
defaultValue: 'default',
key: `${key}-${Math.random(100)}`,
parentKey: key,
isEditable: false,
})
}
return
}
if (item.children) {
addNode(key, item.children)
}
})
// 点击添加
const onAdd = (e) => {
const copyData = _.cloneDeep(treeData)
const copyExpandedKeys = _.cloneDeep(expandedKeys)
if (copyExpandedKeys.indexOf(e) === -1) {
copyExpandedKeys.push(e)
}
addNode(e, copyData)
setExpandedKeys(copyExpandedKeys)
setTreeData(copyData)
}
// 删除结点,递归
const deleteNode = (key, data) =>
data.map((item, index) => {
if (item.key === key) {
data.splice(index, 1)
return
} else {
if (item.children) {
deleteNode(key, item.children)
}
}
})
// 点击删除
const onDelete = (key) => {
const copyData = _.cloneDeep(treeData)
deleteNode(key, copyData)
setTreeData(copyData)
}
// 编辑结点,递归
const editNode = (key, data) =>
data.map((item) => {
if (item.key === key) {
item.isEditable = true
} else {
item.isEditable = false
}
// 当某节点处于编辑状态,并改变数据,点击编辑其他节点时,此节点变成不可编辑状态,value 需要回退到 defaultvalue
item.value = item.defaultValue
if (item.children) {
editNode(key, item.children)
}
})
// 点击编辑
const onEdit = (key) => {
const copyData = _.cloneDeep(treeData)
editNode(key, copyData)
setTreeData(copyData)
setDataList([])
}
// 取消编辑递归
const closeNode = (key, defaultValue, data) =>
data.map((item) => {
item.isEditable = false
if (item.key === key) {
item.value = defaultValue
}
if (item.children) {
closeNode(key, defaultValue, item.children)
}
})
// 编辑状态下点击取消编辑
const onClose = (key, defaultValue) => {
const copyData = _.cloneDeep(treeData)
closeNode(key, defaultValue, copyData)
setTreeData(copyData)
}
// 保存编辑递归
const saveNode = (key, data) =>
data.map((item) => {
if (item.key === key) {
item.defaultValue = item.value
}
if (item.children) {
saveNode(key, item.children)
}
item.isEditable = false
})
// 编辑状态下保存值
const onSave = (key) => {
const copyData = _.cloneDeep(treeData)
saveNode(key, copyData)
setTreeData(copyData)
generateList(copyData)
}
// 编辑状态下实时写入输入的值递归
const changeNode = (key, value, data) =>
data.map((item) => {
if (item.key === key) {
item.value = value
}
if (item.children) {
changeNode(key, value, item.children)
}
})
const onChange = (e, key) => {
const copyData = _.cloneDeep(treeData)
changeNode(key, e.target.value, copyData)
setTreeData(copyData)
}
const renderTreeNodes = (data) =>
data.map((item) => {
if (item.isEditable) {
item.title = (
<div>
<input
value={item.value}
onChange={(e) => onChange(e, item.key)}
/>
<MinusOutlined
type="close"
style={{ marginLeft: 20 }}
onClick={() => onClose(item.key, item.defaultValue)}
/>
<CheckOutlined
type="check"
style={{ marginLeft: 10 }}
onClick={() => onSave(item.key)}
/>
</div>
)
} else {
item.title = (
<div>
<span>{item.value}</span>
<span>
<EditOutlined
style={{ marginLeft: 20 }}
type="edit"
onClick={() => onEdit(item.key)}
/>
<PlusOutlined style={{ marginLeft: 10 }} type="add" onClick={() => onAdd(item.key)} />
<DeleteOutlined
style={{ marginLeft: 10 }}
type="edit"
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 {...item} />
})
const checkEdit = (data) => {
let bool
data.map(item => {
if (item.isEditable) {
bool = true
return
}
if (item.children) {
checkEdit(item.children)
}
})
return bool
}
const generateList = (data) => {
for (let i = 0; i < data.length; i++) {
const { key } = data[i]
dataList.push({ key, value: data[i].value })
if (data[i].children) {
generateList(data[i].children)
}
}
}
const getParentKey = (key, tree) => {
let parentKey
for (let i = 0; i < tree.length; i++) {
const node = tree[i]
if (node.children) {
if (node.children.some(item => item.key === key)) {
parentKey = node.key
} else if (getParentKey(key, node.children)) {
parentKey = getParentKey(key, node.children)
}
}
}
return parentKey
}
return (
<div>
<Tree
showLine={true}
expandedKeys={expandedKeys}
autoExpandParent={autoExpandParent}
onExpand={onExpand}
draggable
selectable={false}
>
{renderTreeNodes(treeData)}
</Tree>
</div>
)
}