个人的使用React开发的组件库x-react-design已开源
npm地址:https://www.npmjs.com/package/x-react-design?activeTab=readme
Tree组件,也就是树组件,数据结构当中的树也与此类似。开发树组件的难点是什么:是如何构建子树,其实很容易想到用递归构建子树。
这里Tree组件分了两种:节点名称前面带复选框的和不带复选框的。
1、不带复选框:
2、带复选框的:
树组件代码:
import { useState, useMemo, Fragment } from 'react'
import DownTriangle from '../Icons/DownTriangleIcon'
import RightTriangle from '../Icons/RightTriangleIcon'
import './index.css'
const Tree = (props) => {
const [treeData, setTreeData] = useState(props.treeData || [])
const handleInitTreeData = (data, field, type, node) => {
let arr = []
function loop(data) {
return data.map(item => {
if(type === 'init') {
item[field] = false
} else if(type === 'update' && node.val === item.val) {
item[field] = !item[field]
}
if(item.children && Array.isArray(item.children)) {
item.children = loop(item.children)
}
return item
})
}
arr = loop([...data])
return arr
}
const tempData = useMemo(() => {
return handleInitTreeData([...props.treeData], 'isSelected', 'init')
}, [props.treeData])
const clickTreeNode = (node) => {
let arr = []
arr = handleInitTreeData([...treeData], 'isSelected', 'update', node)
setTreeData(arr)
props.onChange && props.onChange(node.val, node.label, node.isSelected)
}
const renderTree = (treeDataArr) => {
let arr = []
function loop(data, level) {
return data.map(item => {
let newLevel = level + 1
return <Fragment key={JSON.stringify(item)}>
<span
className="tree-node-label"
onClick={() => {clickTreeNode(item)}}
>
{
(item.children && item.children.length > 0) ?
(item.isSelected ? <DownTriangle /> : <RightTriangle />)
:
<span className='tree-node-label-left-empty'></span>
}
{
props.showCheckbox ?
<input
type="checkbox"
checked={item.isSelected}
/>
: null
}
<span>
{
item.label
}
</span>
</span>
{
item.isSelected ?
<div
className="tree-node-item"
style={{paddingLeft: 15 * newLevel}}
>
{
item.children ?
loop(item.children, newLevel)
: null
}
</div>
: null
}
</Fragment>
})
}
arr = loop([...treeDataArr], 0)
return arr
}
return <div
className="tree-container"
>
{
renderTree(tempData)
}
</div>
}
export default Tree
样式文件index.css:
.tree-container {}
.tree-node-label {
display: flex;
cursor: pointer;
}
.tree-node-label:hover {
color: #00d5ff;
}
.tree-node-label-left-empty {
display: inline-block;
width: 16px;
height: 16px;
}
使用Tree组件的代码:
import Tree from '../../components/Tree'
const data = [
{
label: '节点1',
val: 'node-1',
},
{
label: '节点2',
val: 'node-2',
children: [
{
label: '节点2-1',
val: 'node-2-1',
},
{
label: '节点2-2',
val: 'node-2-2',
},
]
},
{
label: '节点3',
val: 'node-3',
children: [
{
label: '节点3-1',
val: 'node-3-1',
children: [
{
label: '节点3-1-1',
val: 'node-3-1-1',
},
{
label: '节点3-1-2',
val: 'node-3-1-2',
},
]
},
]
},
]
const MyTree = () => {
const handleChange = (val, label, isSelected) => {
console.log(val, label, isSelected);
}
return <div>
<Tree treeData={data} showCheckbox={true} onChange={handleChange} />
</div>
}
export default MyTree
有些参数解释一下:treeData代表的就是节点树数据,showCheckbox代表节点名称前面是否显示复选框,onChange代表的是点击节点的事件。其他参数和功能后续完善。
在Tree组件里renderTree函数是重点,renderTree是构建树结构的函数,使用了递归,level参数是标明树在第几层,利用newLevel设置每个节点距离左边的padding距离,以构建出树状。
目前写的功能能够满足基本功能,后续在完善其它功能。、
未完,待续。。。
**附言 :**x-react-design组件库组件: