Tree component
npm install @uiw/react-treeTree 树形控件
===




使用树控件可以完整展现其中的层级关系,并具有展开收起选择等交互功能。
``jsx`
import { Tree } from 'uiw';
// or
import Tree from '@uiw/react-tree';
`jsx mdx:preview&bg=#fff
import React from 'react';
import { Tree, Card, Row, Col, } from 'uiw';
const data = [
{
label: '湖北省',
key: '0-0-0',
children:[
{
label: '武汉市',
key: '0-1-0',
children:[
{ label: '新洲区', key: '0-1-1' },
{ label: '武昌区', key: '0-1-2' },
{
label: '汉南区',
key: '0-1-3',
children:[
{ label: '汉南区1', key: '0-1-3-1' },
{ label: '汉南区2', key: '0-1-3-2' },
{ label: '汉南区3', key: '0-1-3-3' },
]
},
]
},
{ label: '黄冈市', key: '0-2-0' },
{
label: '黄石市',
key: '0-3-0',
children:[
{ label: '青山区', key: '0-3-1' },
{ label: '黄陂区', key: '0-3-2' },
{ label: '青山区', key: '0-3-3' },
]
},
]
},
{
label: '上海市',
key: '1-0-0',
children:[
{ label: '黄浦区', key: '1-0-1' },
{ label: '卢湾区', key: '1-0-2' },
{
label: '徐汇区',
key: '1-0-3',
children:[
{ label: '半淞园路街道', key: '1-1-0' },
{ label: '南京东路街道', key: '1-2-0' },
{ label: '外滩街道', key: '1-3-0' },
]
},
]
},
{
label: '北京市',
key: '2-0-0',
children:[
{ label: '东城区', key: '2-1-0' },
{ label: '西城区', key: '2-2-0' },
{
label: '崇文区',
key: '2-3-0',
children:[
{ label: '东花市街道', key: '2-3-1' },
{ label: '体育馆路街道', key: '2-3-2' },
{ label: '前门街道', key: '2-3-3' },
]
},
]
}
];
const Demo = () => (
$3
`jsx mdx:preview&bg=#fff
import React from 'react';
import { Tree, Card, Row, Col, Icon } from 'uiw';const data = [
{
label: '湖北省',
key: '0-0-0',
children:[
{
label: '武汉市',
key: '0-1-0',
children:[
{ label: '新洲区', key: '0-1-1' },
{ label: '武昌区', key: '0-1-2' },
{
label: '汉南区',
key: '0-1-3',
children:[
{ label: '汉南区1', key: '0-1-3-1' },
{ label: '汉南区2', key: '0-1-3-2' },
{ label: '汉南区3', key: '0-1-3-3' },
]
},
]
},
{ label: '黄冈市', key: '0-2-0' },
{
label: '黄石市',
key: '0-3-0',
children:[
{ label: '青山区', key: '0-3-1' },
{ label: '黄陂区', key: '0-3-2' },
{ label: '青山区', key: '0-3-3' },
]
},
]
},
{
label: '上海市',
key: '1-0-0',
children:[
{ label: '黄浦区', key: '1-0-1' },
{ label: '卢湾区', key: '1-0-2' },
{
label: '徐汇区',
key: '1-0-3',
children:[
{ label: '半淞园路街道', key: '1-1-0' },
{ label: '南京东路街道', key: '1-2-0' },
{ label: '外滩街道', key: '1-3-0' },
]
},
]
},
{
label: '北京市',
key: '2-0-0',
children:[
{ label: '东城区', key: '2-1-0' },
{ label: '西城区', key: '2-2-0' },
{
label: '崇文区',
key: '2-3-0',
children:[
{ label: '东花市街道', key: '2-3-1' },
{ label: '体育馆路街道', key: '2-3-2' },
{ label: '前门街道', key: '2-3-3' },
]
},
]
}
];
const Demo = () => (
data={data}
renderTitle={(item, { selected, noChild }) => (
<>
{item.label}
>
)}
onExpand={(key, expanded, data, node) => {
console.log(key, expanded, data, node);
}}
onSelected={(key, selected, item, evn) => {
console.log(key, selected, item, evn);
}}
/>
data={data}
icon="right-circle-o"
onExpand={(key, expanded, data, node) => {
console.log(key, expanded, data, node);
}}
onSelected={(key, selected, item, evn) => {
console.log(key, selected, item, evn);
}}
/>
data={data}
iconAnimation={false}
icon={(data, { isOpen, noChild }) => {
if(isOpen && !noChild) {
return 'folder-open';
} else if (!noChild) {
return 'folder';
}
return 'file-text';
}}
onExpand={(key, expanded, data) => {
console.log(key, expanded, data);
}}
onSelected={(key, selected, item, evn) => {
console.log(key, selected, item, evn);
}}
/>
|
)
export default Demo;
`$3
通过设置
checkStrictly 父节点受子节点控制,设置 multiple 为多选,设置 isSelected 取消选中效果,也可以使用 TreeChecked 组件。`jsx mdx:preview&bg=#fff
import React from 'react';
import { Tree, Card, Row, Col, Icon } from 'uiw';const data = [
{
label: '湖北省',
key: '0-0-0',
children:[
{
label: '武汉市',
key: '0-1-0',
children:[
{ label: '新洲区', key: '0-1-1', disabled: true },
{ label: '武昌区', key: '0-1-2' },
{
label: '汉南区',
key: '0-1-3',
children:[
{ label: '汉南区1', key: '0-1-3-1' },
{ label: '汉南区2', key: '0-1-3-2' },
{ label: '汉南区3', key: '0-1-3-3' },
]
},
]
},
{ label: '黄冈市', key: '0-2-0' },
{
label: '黄石市',
key: '0-3-0',
children:[
{ label: '青山区', key: '0-3-1' },
{ label: '黄陂区', key: '0-3-2' },
{ label: '青山区', key: '0-3-3' },
]
},
]
},
{
label: '上海市',
key: '1-0-0',
children:[
{ label: '黄浦区', key: '1-0-1' },
{ label: '卢湾区', key: '1-0-2' },
{
label: '徐汇区',
key: '1-0-3',
children:[
{ label: '半淞园路街道', key: '1-1-0' },
{ label: '南京东路街道', key: '1-2-0' },
{ label: '外滩街道', key: '1-3-0' },
]
},
]
},
{
label: '北京市',
key: '2-0-0',
children:[
{ label: '东城区', key: '2-1-0' },
{ label: '西城区', key: '2-2-0' },
{
label: '崇文区',
key: '2-3-0',
children:[
{ label: '东花市街道', key: '2-3-1' },
{ label: '体育馆路街道', key: '2-3-2' },
{ label: '前门街道', key: '2-3-3' },
]
},
]
},
{ label: '澳门', key: '3' },
];
const Demo = () => (
data={data}
selectedKeys={['0-1-1']}
multiple
isSelected={false}
checkStrictly
renderTitle={(item, { selected, isHalfChecked }) => {
if(isHalfChecked) {
return (
<> {item.label}>
);
}
if (selected) {
return (
<> {item.label}>
);
}
return (
<> {item.label}>
);
}}
onExpand={(key, expanded, data, node) => {
console.log(key, expanded, data, node);
}}
onSelected={(key, selected, item, evn) => {
console.log(key, selected, item, evn);
}}
/>
)
export default Demo;
`$3
`jsx mdx:preview&bg=#fff
import React from 'react';
import { Tree, Card, Row, Col, Icon } from 'uiw';const data = [
{
label: '湖北省',
key: '0-0-0',
children:[
{
label: '武汉市',
disabled: true,
key: '0-1-0',
children:[
{ label: '新洲区', key: '0-1-1' },
{ label: '武昌区', key: '0-1-2' },
{
label: '汉南区',
key: '0-1-3',
children:[
{ label: '汉南区1', key: '0-1-3-1' },
{ label: '汉南区2', key: '0-1-3-2' },
{ label: '汉南区3', key: '0-1-3-3' },
]
},
]
},
{ label: '黄冈市', key: '0-2-0' },
{
label: '黄石市',
key: '0-3-0',
children:[
{ label: '青山区', key: '0-3-1' },
{ label: '黄陂区', key: '0-3-2' },
{ label: '青山区', key: '0-3-3' },
]
},
]
},
{
label: '上海市',
key: '1-0-0',
children:[
{ label: '黄浦区', key: '1-0-1' },
{ label: '卢湾区', key: '1-0-2' },
{
label: '徐汇区',
key: '1-0-3',
children:[
{ label: '半淞园路街道', key: '1-1-0' },
{ label: '南京东路街道', key: '1-2-0' },
{ label: '外滩街道', key: '1-3-0' },
]
},
]
},
{
label: '北京市',
key: '2-0-0',
children:[
{ label: '东城区', key: '2-1-0' },
{ label: '西城区', key: '2-2-0' },
{
label: '崇文区',
key: '2-3-0',
children:[
{ label: '东花市街道', key: '2-3-1' },
{ label: '体育馆路街道', key: '2-3-2' },
{ label: '前门街道', key: '2-3-3' },
]
},
]
}
];
const Demo = () => (
data={data}
renderTitle={(item, { selected, noChild, disabledStyle }) => (
<>
{item.label}
>
)}
/>
data={data}
renderTitle={(item, { selected, isHalfChecked, disabledStyle, disabledClass }) => {
if(isHalfChecked) {
return (
<> {item.label}>
);
}
if (selected) {
return (
<> {item.label}>
);
}
return (
<> {item.label}>
);
}}
/>
|
)
export default Demo;
`$3
带连接线的树,通过设置
showLine。`jsx mdx:preview&bg=#fff
import React from 'react';
import { Tree, Card, Row, Col } from 'uiw';const data = [
{
label: '湖北省',
key: '0-0-0',
children:[
{
label: '武汉市',
key: '0-1-0',
children:[
{ label: '新洲区', key: '0-1-1' },
{ label: '武昌区', key: '0-1-2' },
{
label: '汉南区',
key: '0-1-3',
children:[
{ label: '汉南区1', key: '0-1-3-1' },
{ label: '汉南区2', key: '0-1-3-2' },
{ label: '汉南区3', key: '0-1-3-3' },
]
},
]
},
{ label: '黄冈市', key: '0-2-0' },
{
label: '黄石市',
key: '0-3-0',
children:[
{ label: '青山区', key: '0-3-1' },
{ label: '黄陂区', key: '0-3-2' },
{ label: '青山区', key: '0-3-3' },
]
},
]
},
{
label: '上海市',
key: '1-0-0',
children:[
{ label: '黄浦区', key: '1-0-1' },
{ label: '卢湾区', key: '1-0-2' },
{
label: '徐汇区',
key: '1-0-3',
children:[
{ label: '半淞园路街道', key: '1-1-0' },
{ label: '南京东路街道', key: '1-2-0' },
{ label: '外滩街道', key: '1-3-0' },
]
},
]
},
{
label: '北京市',
key: '2-0-0',
children:[
{ label: '东城区', key: '2-1-0' },
{ label: '西城区', key: '2-2-0' },
{
label: '崇文区',
key: '2-3-0',
children:[
{ label: '东花市街道', key: '2-3-1' },
{ label: '体育馆路街道', key: '2-3-2' },
{ label: '前门街道', key: '2-3-3' },
]
},
]
}
];
const Demo = () => (
data={data}
showLine
iconAnimation={false}
icon={(data, {isOpen, noChild}) => {
if(isOpen && !noChild) {
return 'folder-open';
} else if (!noChild) {
return 'folder';
}
return 'file-text';
}}
onExpand={(key, expanded, data) => {
console.log(key, expanded, data);
}}
onSelected={(key, selected, item, evn) => {
console.log(key, selected, item, evn);
}}
/>
data={data}
showLine
icon={(data, {isOpen, noChild}) => {
if(noChild) {
return 'file-text';
}
}}
onExpand={(key, expanded, data) => {
console.log(key, expanded, data);
}}
onSelected={(key, selected, item, evn) => {
console.log(key, selected, item, evn);
}}
/>
|
)
export default Demo;
`$3
`jsx mdx:preview&bg=#fff
import React from 'react';
import { Tree, Card, Row, Col } from 'uiw';const data = [
{
label: '湖北省',
key: '0-0-0',
children:[
{
label: '武汉市',
key: '0-1-0',
children:[
{ label: '新洲区', key: '0-1-1' },
{ label: '武昌区', key: '0-1-2' },
{
label: '汉南区',
key: '0-1-3',
children:[
{ label: '汉南区1', key: '0-1-3-1' },
{ label: '汉南区2', key: '0-1-3-2' },
{ label: '汉南区3', key: '0-1-3-3' },
]
},
]
},
{ label: '黄冈市', key: '0-2-0' },
{
label: '黄石市',
key: '0-3-0',
children:[
{ label: '青山区', key: '0-3-1' },
{ label: '黄陂区', key: '0-3-2' },
{ label: '青山区', key: '0-3-3' },
]
},
]
},
{
label: '上海市',
key: '1-0-0',
children:[
{ label: '黄浦区', key: '1-0-1' },
{ label: '卢湾区', key: '1-0-2' },
{
label: '徐汇区',
key: '1-0-3',
children:[
{ label: '半淞园路街道', key: '1-1-0' },
{ label: '南京东路街道', key: '1-2-0' },
{ label: '外滩街道', key: '1-3-0' },
]
},
]
},
{
label: '北京市',
key: '2-0-0',
children:[
{ label: '东城区', key: '2-1-0' },
{ label: '西城区', key: '2-2-0' },
]
}
];
const Demo = () => (
data={data}
showLine
openKeys={['0-0-0', '0-1-0']}
iconAnimation={false}
icon={(data, {isOpen, noChild}) => {
if(isOpen && !noChild) {
return 'folder-open';
} else if (!noChild) {
return 'folder';
}
return 'file-text';
}}
onExpand={(key, expanded, data) => {
console.log(key, expanded, data);
}}
onSelected={(key, selected, item, evn) => {
console.log(key, selected, item, evn);
}}
/>
data={data}
showLine
defaultExpandAll
icon={(data, {isOpen, noChild}) => {
if(noChild) {
return 'file-text';
}
}}
onExpand={(key, expanded, data) => {
console.log(key, expanded, data);
}}
onSelected={(key, selected, item, evn) => {
console.log(key, selected, item, evn);
}}
/>
|
)
export default Demo;
`
$3
`jsx mdx:preview&bg=#fff
import React from 'react';
import { Tree, Row, Col, Form, Button } from 'uiw';const data = [
{
label: '湖北省',
key: '0-0-0',
children:[
{
label: '武汉市',
key: '0-1-0',
children:[
{ label: '新洲区', key: '0-1-1' },
{ label: '武昌区', key: '0-1-2' },
{
label: '汉南区',
key: '0-1-3',
children:[
{ label: '汉南区1', key: '0-1-3-1' },
{ label: '汉南区2', key: '0-1-3-2' },
{ label: '汉南区3', key: '0-1-3-3' },
]
},
]
},
{ label: '黄冈市', key: '0-2-0' },
{
label: '黄石市',
key: '0-3-0',
children:[
{ label: '青山区', key: '0-3-1' },
{ label: '黄陂区', key: '0-3-2' },
{ label: '青山区', key: '0-3-3' },
]
},
]
},
{
label: '上海市',
key: '1-0-0',
children:[
{ label: '黄浦区', key: '1-0-1' },
{ label: '卢湾区', key: '1-0-2' },
{
label: '徐汇区',
key: '1-0-3',
children:[
{ label: '半淞园路街道', key: '1-1-0' },
{ label: '南京东路街道', key: '1-2-0' },
{ label: '外滩街道', key: '1-3-0' },
]
},
]
},
{
label: '北京市',
key: '2-0-0',
children:[
{ label: '东城区', key: '2-1-0' },
{ label: '西城区', key: '2-2-0' },
]
}
];
const Demo = () => {
return (
onChange={({ initial, current }) => {}}
resetOnSubmit={false}
onSubmitError={(error) => error && error.filed ? { ...error.filed } : null}
onSubmit={({initial, current}) => {
console.log('current: ', current);
const ErrObj = {};
if (current.tree === 'unknown') {
ErrObj.radioGroup = '请选择性别!';
}
if(Object.keys(ErrObj).length > 0) {
const err = new Error();
err.filed = ErrObj;
throw err;
}
Notify.success({
title: '提交成功!', description: 填写:【填写成功】!
});
}}
fields={{
tree: {
value: 'region',
label: '请输入内容',
help: '必须选择地区!',
initialValue: ['0-1-1'],
children: // multiple
checkStrictly
data={data}
/>,
},
}}
>
{({ fields, state, canSubmit }) => {
return (
{fields.tree}
|
|
{JSON.stringify(state.current, null, 2)}
|
);
}}
)
}
export default Demo;
`
Props
| 参数 | 说明 | 类型 | 默认值 |
|--------- |-------- |--------- |-------- |
| data | 展示数据 | Array |
TreeData[] |
| openKeys | 节点展开 key | Array | [] |
| selectedKeys | 设置选中的树节点 | Array | [] |
| autoExpandParent | 是否自动展开父节点 | Boolean | true |
| defaultExpandAll | 默认展开所有树节点 | Boolean | false |
| iconAnimation | 展开收缩图标,参数设为 false 禁用动画 | Boolean | true |
| isSelected | 是否选中当前节点样式。 | Boolean | true |
| showLine | 是否展示连接线 | Boolean | false |
| checkStrictly | 子节点受父节点控制设置 true,需要配合 multiple 参数使用。 | Boolean | false |
| multiple | 支持点选多个节点 | Boolean | false |
| icon | 重新定义,展开收缩图标,当为函数时视为自定义图标,并展示非折叠项的图标。 | ~~Function(data: object, noChild: bool)/String/Node~~ @3.4.0+ Function(data: object, { selected: bool, noChild: bool })/String/Node| - |
| renderTitle | 重新定义每个标题节点的显示 | ~~Function(item, selected: bool, noChild: bool)~~ @3.4.0+ Function(item: TreeData, node?: Node) => React.ReactElement; | - |
| onSelected | 点击选择树节点触发 | Function(selectedKeys: array, key, selected: bool, data, e) | - |
| onExpand | 展开/收起节点时触发 | Function(key, expanded: bool, data, evn) | - |Node Type
| 参数 | 类型 | 版本 |
|--------- |-------- |-------- |
| selected | boolean | - |
| noChild | boolean | - |
| isHalfChecked | boolean | @3.4.0+ |
| openKeys | Props['openKeys'] | @3.4.0+ |
| selectedKeys | Props['selectedKeys'] | @3.4.0+ |
| disabled | boolean | @4.20.0+ |
| disabledClass | string | @4.20.0+ |
| disabledStyle | React.CSSProperties | @4.20.0+ |
$3
`json
[
{
"label": "湖北省",
"key": "0-0-0",
"disabled": false,
"children":[]
}
...
]
``