Tree树形控件

多层次的结构列表。

何时使用

文件夹、组织架构、生物分类、国家地区等等,世间万物的大多数结构都是树形结构。使用 树控件 可以完整展现其中的层级关系,并具有展开收起选择等交互功能。

代码演示

Tree树形控件 - 图1

基本

最简单的用法,展示可勾选,可选中,禁用,默认展开等功能。

TypeScript

JavaScript

Tree树形控件 - 图2

  1. import { Tree } from 'antd';
  2. const treeData = [
  3. {
  4. title: 'parent 1',
  5. key: '0-0',
  6. children: [
  7. {
  8. title: 'parent 1-0',
  9. key: '0-0-0',
  10. disabled: true,
  11. children: [
  12. {
  13. title: 'leaf',
  14. key: '0-0-0-0',
  15. disableCheckbox: true,
  16. },
  17. {
  18. title: 'leaf',
  19. key: '0-0-0-1',
  20. },
  21. ],
  22. },
  23. {
  24. title: 'parent 1-1',
  25. key: '0-0-1',
  26. children: [{ title: <span style={{ color: '#1890ff' }}>sss</span>, key: '0-0-1-0' }],
  27. },
  28. ],
  29. },
  30. ];
  31. const Demo = () => {
  32. const onSelect = (selectedKeys: React.Key[], info: any) => {
  33. console.log('selected', selectedKeys, info);
  34. };
  35. const onCheck = (checkedKeys: React.Key[], info: any) => {
  36. console.log('onCheck', checkedKeys, info);
  37. };
  38. return (
  39. <Tree
  40. checkable
  41. defaultExpandedKeys={['0-0-0', '0-0-1']}
  42. defaultSelectedKeys={['0-0-0', '0-0-1']}
  43. defaultCheckedKeys={['0-0-0', '0-0-1']}
  44. onSelect={onSelect}
  45. onCheck={onCheck}
  46. treeData={treeData}
  47. />
  48. );
  49. };
  50. ReactDOM.render(<Demo />, mountNode);

Tree树形控件 - 图3

拖动示例

将节点拖拽到其他节点内部或前后。

  1. import { Tree } from 'antd';
  2. const x = 3;
  3. const y = 2;
  4. const z = 1;
  5. const gData = [];
  6. const generateData = (_level, _preKey, _tns) => {
  7. const preKey = _preKey || '0';
  8. const tns = _tns || gData;
  9. const children = [];
  10. for (let i = 0; i < x; i++) {
  11. const key = `${preKey}-${i}`;
  12. tns.push({ title: key, key });
  13. if (i < y) {
  14. children.push(key);
  15. }
  16. }
  17. if (_level < 0) {
  18. return tns;
  19. }
  20. const level = _level - 1;
  21. children.forEach((key, index) => {
  22. tns[index].children = [];
  23. return generateData(level, key, tns[index].children);
  24. });
  25. };
  26. generateData(z);
  27. class Demo extends React.Component {
  28. state = {
  29. gData,
  30. expandedKeys: ['0-0', '0-0-0', '0-0-0-0'],
  31. };
  32. onDragEnter = info => {
  33. console.log(info);
  34. // expandedKeys 需要受控时设置
  35. // this.setState({
  36. // expandedKeys: info.expandedKeys,
  37. // });
  38. };
  39. onDrop = info => {
  40. console.log(info);
  41. const dropKey = info.node.key;
  42. const dragKey = info.dragNode.key;
  43. const dropPos = info.node.pos.split('-');
  44. const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1]);
  45. const loop = (data, key, callback) => {
  46. for (let i = 0; i < data.length; i++) {
  47. if (data[i].key === key) {
  48. return callback(data[i], i, data);
  49. }
  50. if (data[i].children) {
  51. loop(data[i].children, key, callback);
  52. }
  53. }
  54. };
  55. const data = [...this.state.gData];
  56. // Find dragObject
  57. let dragObj;
  58. loop(data, dragKey, (item, index, arr) => {
  59. arr.splice(index, 1);
  60. dragObj = item;
  61. });
  62. if (!info.dropToGap) {
  63. // Drop on the content
  64. loop(data, dropKey, item => {
  65. item.children = item.children || [];
  66. // where to insert 示例添加到头部,可以是随意位置
  67. item.children.unshift(dragObj);
  68. });
  69. } else if (
  70. (info.node.props.children || []).length > 0 && // Has children
  71. info.node.props.expanded && // Is expanded
  72. dropPosition === 1 // On the bottom gap
  73. ) {
  74. loop(data, dropKey, item => {
  75. item.children = item.children || [];
  76. // where to insert 示例添加到头部,可以是随意位置
  77. item.children.unshift(dragObj);
  78. // in previous version, we use item.children.push(dragObj) to insert the
  79. // item to the tail of the children
  80. });
  81. } else {
  82. let ar;
  83. let i;
  84. loop(data, dropKey, (item, index, arr) => {
  85. ar = arr;
  86. i = index;
  87. });
  88. if (dropPosition === -1) {
  89. ar.splice(i, 0, dragObj);
  90. } else {
  91. ar.splice(i + 1, 0, dragObj);
  92. }
  93. }
  94. this.setState({
  95. gData: data,
  96. });
  97. };
  98. render() {
  99. return (
  100. <Tree
  101. className="draggable-tree"
  102. defaultExpandedKeys={this.state.expandedKeys}
  103. draggable
  104. blockNode
  105. onDragEnter={this.onDragEnter}
  106. onDrop={this.onDrop}
  107. treeData={this.state.gData}
  108. />
  109. );
  110. }
  111. }
  112. ReactDOM.render(<Demo />, mountNode);

Tree树形控件 - 图4

可搜索

可搜索的树。

  1. import { Tree, Input } from 'antd';
  2. const { Search } = Input;
  3. const x = 3;
  4. const y = 2;
  5. const z = 1;
  6. const gData = [];
  7. const generateData = (_level, _preKey, _tns) => {
  8. const preKey = _preKey || '0';
  9. const tns = _tns || gData;
  10. const children = [];
  11. for (let i = 0; i < x; i++) {
  12. const key = `${preKey}-${i}`;
  13. tns.push({ title: key, key });
  14. if (i < y) {
  15. children.push(key);
  16. }
  17. }
  18. if (_level < 0) {
  19. return tns;
  20. }
  21. const level = _level - 1;
  22. children.forEach((key, index) => {
  23. tns[index].children = [];
  24. return generateData(level, key, tns[index].children);
  25. });
  26. };
  27. generateData(z);
  28. const dataList = [];
  29. const generateList = data => {
  30. for (let i = 0; i < data.length; i++) {
  31. const node = data[i];
  32. const { key } = node;
  33. dataList.push({ key, title: key });
  34. if (node.children) {
  35. generateList(node.children);
  36. }
  37. }
  38. };
  39. generateList(gData);
  40. const getParentKey = (key, tree) => {
  41. let parentKey;
  42. for (let i = 0; i < tree.length; i++) {
  43. const node = tree[i];
  44. if (node.children) {
  45. if (node.children.some(item => item.key === key)) {
  46. parentKey = node.key;
  47. } else if (getParentKey(key, node.children)) {
  48. parentKey = getParentKey(key, node.children);
  49. }
  50. }
  51. }
  52. return parentKey;
  53. };
  54. class SearchTree extends React.Component {
  55. state = {
  56. expandedKeys: [],
  57. searchValue: '',
  58. autoExpandParent: true,
  59. };
  60. onExpand = expandedKeys => {
  61. this.setState({
  62. expandedKeys,
  63. autoExpandParent: false,
  64. });
  65. };
  66. onChange = e => {
  67. const { value } = e.target;
  68. const expandedKeys = dataList
  69. .map(item => {
  70. if (item.title.indexOf(value) > -1) {
  71. return getParentKey(item.key, gData);
  72. }
  73. return null;
  74. })
  75. .filter((item, i, self) => item && self.indexOf(item) === i);
  76. this.setState({
  77. expandedKeys,
  78. searchValue: value,
  79. autoExpandParent: true,
  80. });
  81. };
  82. render() {
  83. const { searchValue, expandedKeys, autoExpandParent } = this.state;
  84. const loop = data =>
  85. data.map(item => {
  86. const index = item.title.indexOf(searchValue);
  87. const beforeStr = item.title.substr(0, index);
  88. const afterStr = item.title.substr(index + searchValue.length);
  89. const title =
  90. index > -1 ? (
  91. <span>
  92. {beforeStr}
  93. <span className="site-tree-search-value">{searchValue}</span>
  94. {afterStr}
  95. </span>
  96. ) : (
  97. <span>{item.title}</span>
  98. );
  99. if (item.children) {
  100. return { title, key: item.key, children: loop(item.children) };
  101. }
  102. return {
  103. title,
  104. key: item.key,
  105. };
  106. });
  107. return (
  108. <div>
  109. <Search style={{ marginBottom: 8 }} placeholder="Search" onChange={this.onChange} />
  110. <Tree
  111. onExpand={this.onExpand}
  112. expandedKeys={expandedKeys}
  113. autoExpandParent={autoExpandParent}
  114. treeData={loop(gData)}
  115. />
  116. </div>
  117. );
  118. }
  119. }
  120. ReactDOM.render(<SearchTree />, mountNode);
  1. .site-tree-search-value {
  2. color: #f50;
  3. }

Tree树形控件 - 图5

自定义图标

可以针对不同的节点定制图标。

  1. import { Tree } from 'antd';
  2. import {
  3. DownOutlined,
  4. FrownOutlined,
  5. SmileOutlined,
  6. MehOutlined,
  7. FrownFilled,
  8. } from '@ant-design/icons';
  9. const treeData = [
  10. {
  11. title: 'parent 1',
  12. key: '0-0',
  13. icon: <SmileOutlined />,
  14. children: [
  15. {
  16. title: 'leaf',
  17. key: '0-0-0',
  18. icon: <MehOutlined />,
  19. },
  20. {
  21. title: 'leaf',
  22. key: '0-0-1',
  23. icon: ({ selected }) => (selected ? <FrownFilled /> : <FrownOutlined />),
  24. },
  25. ],
  26. },
  27. ];
  28. ReactDOM.render(
  29. <Tree
  30. showIcon
  31. defaultExpandAll
  32. defaultSelectedKeys={['0-0-0']}
  33. switcherIcon={<DownOutlined />}
  34. treeData={treeData}
  35. />,
  36. mountNode,
  37. );

Tree树形控件 - 图6

自定义展开/折叠图标

自定义展开/折叠图标。

  1. import { Tree } from 'antd';
  2. import { DownOutlined } from '@ant-design/icons';
  3. class Demo extends React.Component {
  4. onSelect = (selectedKeys, info) => {
  5. console.log('selected', selectedKeys, info);
  6. };
  7. render() {
  8. return (
  9. <Tree
  10. showLine
  11. switcherIcon={<DownOutlined />}
  12. defaultExpandedKeys={['0-0-0']}
  13. onSelect={this.onSelect}
  14. treeData={[
  15. {
  16. title: 'parent 1',
  17. key: '0-0',
  18. children: [
  19. {
  20. title: 'parent 1-0',
  21. key: '0-0-0',
  22. children: [
  23. {
  24. title: 'leaf',
  25. key: '0-0-0-0',
  26. },
  27. {
  28. title: 'leaf',
  29. key: '0-0-0-1',
  30. },
  31. {
  32. title: 'leaf',
  33. key: '0-0-0-2',
  34. },
  35. ],
  36. },
  37. {
  38. title: 'parent 1-1',
  39. key: '0-0-1',
  40. children: [
  41. {
  42. title: 'leaf',
  43. key: '0-0-1-0',
  44. },
  45. ],
  46. },
  47. {
  48. title: 'parent 1-2',
  49. key: '0-0-2',
  50. children: [
  51. {
  52. title: 'leaf',
  53. key: '0-0-2-0',
  54. },
  55. {
  56. title: 'leaf',
  57. key: '0-0-2-1',
  58. },
  59. ],
  60. },
  61. ],
  62. },
  63. ]}
  64. />
  65. );
  66. }
  67. }
  68. ReactDOM.render(<Demo />, mountNode);

Tree树形控件 - 图7

受控操作示例

受控操作示例

TypeScript

JavaScript

Tree树形控件 - 图8

  1. import React, { useState } from 'react';
  2. import { Tree } from 'antd';
  3. const treeData = [
  4. {
  5. title: '0-0',
  6. key: '0-0',
  7. children: [
  8. {
  9. title: '0-0-0',
  10. key: '0-0-0',
  11. children: [
  12. { title: '0-0-0-0', key: '0-0-0-0' },
  13. { title: '0-0-0-1', key: '0-0-0-1' },
  14. { title: '0-0-0-2', key: '0-0-0-2' },
  15. ],
  16. },
  17. {
  18. title: '0-0-1',
  19. key: '0-0-1',
  20. children: [
  21. { title: '0-0-1-0', key: '0-0-1-0' },
  22. { title: '0-0-1-1', key: '0-0-1-1' },
  23. { title: '0-0-1-2', key: '0-0-1-2' },
  24. ],
  25. },
  26. {
  27. title: '0-0-2',
  28. key: '0-0-2',
  29. },
  30. ],
  31. },
  32. {
  33. title: '0-1',
  34. key: '0-1',
  35. children: [
  36. { title: '0-1-0-0', key: '0-1-0-0' },
  37. { title: '0-1-0-1', key: '0-1-0-1' },
  38. { title: '0-1-0-2', key: '0-1-0-2' },
  39. ],
  40. },
  41. {
  42. title: '0-2',
  43. key: '0-2',
  44. },
  45. ];
  46. const Demo = () => {
  47. const [expandedKeys, setExpandedKeys] = useState<React.Key[]>(['0-0-0', '0-0-1']);
  48. const [checkedKeys, setCheckedKeys] = useState<React.Key[]>(['0-0-0']);
  49. const [selectedKeys, setSelectedKeys] = useState<React.Key[]>([]);
  50. const [autoExpandParent, setAutoExpandParent] = useState<boolean>(true);
  51. const onExpand = (expandedKeysValue: React.Key[]) => {
  52. console.log('onExpand', expandedKeysValue);
  53. // if not set autoExpandParent to false, if children expanded, parent can not collapse.
  54. // or, you can remove all expanded children keys.
  55. setExpandedKeys(expandedKeysValue);
  56. setAutoExpandParent(false);
  57. };
  58. const onCheck = (checkedKeysValue: React.Key[]) => {
  59. console.log('onCheck', checkedKeysValue);
  60. setCheckedKeys(checkedKeysValue);
  61. };
  62. const onSelect = (selectedKeysValue: React.Key[], info: any) => {
  63. console.log('onSelect', info);
  64. setSelectedKeys(selectedKeysValue);
  65. };
  66. return (
  67. <Tree
  68. checkable
  69. onExpand={onExpand}
  70. expandedKeys={expandedKeys}
  71. autoExpandParent={autoExpandParent}
  72. onCheck={onCheck}
  73. checkedKeys={checkedKeys}
  74. onSelect={onSelect}
  75. selectedKeys={selectedKeys}
  76. treeData={treeData}
  77. />
  78. );
  79. };
  80. ReactDOM.render(<Demo />, mountNode);

Tree树形控件 - 图9

异步数据加载

点击展开节点,动态加载数据。

TypeScript

JavaScript

Tree树形控件 - 图10

  1. import React, { useState } from 'react';
  2. import { Tree } from 'antd';
  3. interface DataNode {
  4. title: string;
  5. key: string;
  6. isLeaf?: boolean;
  7. children?: DataNode[];
  8. }
  9. const initTreeData: DataNode[] = [
  10. { title: 'Expand to load', key: '0' },
  11. { title: 'Expand to load', key: '1' },
  12. { title: 'Tree Node', key: '2', isLeaf: true },
  13. ];
  14. // It's just a simple demo. You can use tree map to optimize update perf.
  15. function updateTreeData(list: DataNode[], key: React.Key, children: DataNode[]): DataNode[] {
  16. return list.map(node => {
  17. if (node.key === key) {
  18. return {
  19. ...node,
  20. children,
  21. };
  22. }
  23. if (node.children) {
  24. return {
  25. ...node,
  26. children: updateTreeData(node.children, key, children),
  27. };
  28. }
  29. return node;
  30. });
  31. }
  32. const Demo: React.FC<{}> = () => {
  33. const [treeData, setTreeData] = useState(initTreeData);
  34. function onLoadData({ key, children }: any) {
  35. return new Promise<void>(resolve => {
  36. if (children) {
  37. resolve();
  38. return;
  39. }
  40. setTimeout(() => {
  41. setTreeData(origin =>
  42. updateTreeData(origin, key, [
  43. { title: 'Child Node', key: `${key}-0` },
  44. { title: 'Child Node', key: `${key}-1` },
  45. ]),
  46. );
  47. resolve();
  48. }, 1000);
  49. });
  50. }
  51. return <Tree loadData={onLoadData} treeData={treeData} />;
  52. };
  53. ReactDOM.render(<Demo />, mountNode);

Tree树形控件 - 图11

连接线

节点之间带连接线的树,常用于文件目录结构展示。使用 showLine 开启,可以用 switcherIcon 修改默认图标。

TypeScript

JavaScript

Tree树形控件 - 图12

  1. import React, { useState } from 'react';
  2. import { Tree, Switch } from 'antd';
  3. import { CarryOutOutlined, FormOutlined } from '@ant-design/icons';
  4. const treeData = [
  5. {
  6. title: 'parent 1',
  7. key: '0-0',
  8. icon: <CarryOutOutlined />,
  9. children: [
  10. {
  11. title: 'parent 1-0',
  12. key: '0-0-0',
  13. icon: <CarryOutOutlined />,
  14. children: [
  15. { title: 'leaf', key: '0-0-0-0', icon: <CarryOutOutlined /> },
  16. {
  17. title: (
  18. <>
  19. <div>multiple line title</div>
  20. <div>multiple line title</div>
  21. </>
  22. ),
  23. key: '0-0-0-1',
  24. icon: <CarryOutOutlined />,
  25. },
  26. { title: 'leaf', key: '0-0-0-2', icon: <CarryOutOutlined /> },
  27. ],
  28. },
  29. {
  30. title: 'parent 1-1',
  31. key: '0-0-1',
  32. icon: <CarryOutOutlined />,
  33. children: [{ title: 'leaf', key: '0-0-1-0', icon: <CarryOutOutlined /> }],
  34. },
  35. {
  36. title: 'parent 1-2',
  37. key: '0-0-2',
  38. icon: <CarryOutOutlined />,
  39. children: [
  40. { title: 'leaf', key: '0-0-2-0', icon: <CarryOutOutlined /> },
  41. {
  42. title: 'leaf',
  43. key: '0-0-2-1',
  44. icon: <CarryOutOutlined />,
  45. switcherIcon: <FormOutlined />,
  46. },
  47. ],
  48. },
  49. ],
  50. },
  51. {
  52. title: 'parent 2',
  53. key: '0-1',
  54. icon: <CarryOutOutlined />,
  55. children: [
  56. {
  57. title: 'parent 2-0',
  58. key: '0-1-0',
  59. icon: <CarryOutOutlined />,
  60. children: [
  61. { title: 'leaf', key: '0-1-0-0', icon: <CarryOutOutlined /> },
  62. { title: 'leaf', key: '0-1-0-1', icon: <CarryOutOutlined /> },
  63. ],
  64. },
  65. ],
  66. },
  67. ];
  68. const Demo: React.FC<{}> = () => {
  69. const [showLine, setShowLine] = useState<boolean | { showLeafIcon: boolean }>(true);
  70. const [showIcon, setShowIcon] = useState<boolean>(false);
  71. const [showLeafIcon, setShowLeafIcon] = useState<boolean>(true);
  72. const onSelect = (selectedKeys: React.Key[], info: any) => {
  73. console.log('selected', selectedKeys, info);
  74. };
  75. const onSetLeafIcon = (checked: boolean) => {
  76. setShowLeafIcon(checked);
  77. setShowLine({ showLeafIcon: checked });
  78. };
  79. const onSetShowLine = (checked: boolean) => {
  80. setShowLine(checked ? { showLeafIcon } : false);
  81. };
  82. return (
  83. <div>
  84. <div style={{ marginBottom: 16 }}>
  85. showLine: <Switch checked={!!showLine} onChange={onSetShowLine} />
  86. <br />
  87. <br />
  88. showIcon: <Switch checked={showIcon} onChange={setShowIcon} />
  89. <br />
  90. <br />
  91. showLeafIcon: <Switch checked={showLeafIcon} onChange={onSetLeafIcon} />
  92. </div>
  93. <Tree
  94. showLine={showLine}
  95. showIcon={showIcon}
  96. defaultExpandedKeys={['0-0-0']}
  97. onSelect={onSelect}
  98. treeData={treeData}
  99. />
  100. </div>
  101. );
  102. };
  103. ReactDOM.render(<Demo />, mountNode);

Tree树形控件 - 图13

目录

内置的目录树,multiple 模式支持 ctrl(Windows) / command(Mac) 复选。

TypeScript

JavaScript

Tree树形控件 - 图14

  1. import { Tree } from 'antd';
  2. const { DirectoryTree } = Tree;
  3. const treeData = [
  4. {
  5. title: 'parent 0',
  6. key: '0-0',
  7. children: [
  8. { title: 'leaf 0-0', key: '0-0-0', isLeaf: true },
  9. { title: 'leaf 0-1', key: '0-0-1', isLeaf: true },
  10. ],
  11. },
  12. {
  13. title: 'parent 1',
  14. key: '0-1',
  15. children: [
  16. { title: 'leaf 1-0', key: '0-1-0', isLeaf: true },
  17. { title: 'leaf 1-1', key: '0-1-1', isLeaf: true },
  18. ],
  19. },
  20. ];
  21. const Demo: React.FC<{}> = () => {
  22. const onSelect = (keys: React.Key[], info: any) => {
  23. console.log('Trigger Select', keys, info);
  24. };
  25. const onExpand = () => {
  26. console.log('Trigger Expand');
  27. };
  28. return (
  29. <DirectoryTree
  30. multiple
  31. defaultExpandAll
  32. onSelect={onSelect}
  33. onExpand={onExpand}
  34. treeData={treeData}
  35. />
  36. );
  37. };
  38. ReactDOM.render(<Demo />, mountNode);

Tree树形控件 - 图15

虚拟滚动

使用 height 属性则切换为虚拟滚动。

  1. import { Tree } from 'antd';
  2. function dig(path = '0', level = 3) {
  3. const list = [];
  4. for (let i = 0; i < 10; i += 1) {
  5. const key = `${path}-${i}`;
  6. const treeNode = {
  7. title: key,
  8. key,
  9. };
  10. if (level > 0) {
  11. treeNode.children = dig(key, level - 1);
  12. }
  13. list.push(treeNode);
  14. }
  15. return list;
  16. }
  17. const treeData = dig();
  18. ReactDOM.render(<Tree treeData={treeData} height={233} defaultExpandAll />, mountNode);

API

Tree props

参数说明类型默认值版本
allowDrop是否允许拖拽时放置在该节点({ dropNode, dropPosition }) => boolean-
autoExpandParent是否自动展开父节点booleanfalse
blockNode是否节点占据一行booleanfalse
checkable节点前添加 Checkbox 复选框booleanfalse
checkedKeys(受控)选中复选框的树节点(注意:父子节点有关联,如果传入父节点 key,则子节点自动选中;相应当子节点 key 都传入,父节点也自动选中。当设置 checkablecheckStrictly,它是一个有checkedhalfChecked属性的对象,并且父子节点的选中与否不再关联string[] | {checked: string[], halfChecked: string[]}[]
checkStrictlycheckable 状态下节点选择完全受控(父子节点选中状态不再关联)booleanfalse
defaultCheckedKeys默认选中复选框的树节点string[][]
defaultExpandAll默认展开所有树节点booleanfalse
defaultExpandedKeys默认展开指定的树节点string[][]
defaultExpandParent默认展开父节点booleantrue
defaultSelectedKeys默认选中的树节点string[][]
disabled将树禁用booleanfalse
draggable设置节点可拖拽(IE>8)boolean | ((node: DataNode) => boolean)false
expandedKeys(受控)展开指定的树节点string[][]
filterTreeNode按需筛选树节点(高亮),返回 truefunction(node)-
height设置虚拟滚动容器高度,设置后内部节点不再支持横向滚动number-
icon自定义树节点图标。ReactNode | (props) => ReactNode-
loadData异步加载数据function(node)-
loadedKeys(受控)已经加载的节点,需要配合 loadData 使用string[][]
multiple支持点选多个节点(节点本身)booleanfalse
selectable是否可选中booleantrue
selectedKeys(受控)设置选中的树节点string[]-
showIcon是否展示 TreeNode title 前的图标,没有默认样式,如设置为 true,需要自行定义图标相关样式booleanfalse
showLine是否展示连接线boolean | {showLeafIcon: boolean}false
switcherIcon自定义树节点的展开/折叠图标ReactNode-
titleRender自定义渲染节点(nodeData) => ReactNode-4.5.0
treeDatatreeNodes 数据,如果设置则不需要手动构造 TreeNode 节点(key 在整个树范围内唯一)array<{key, title, children, [disabled, selectable]}>-
virtual设置 false 时关闭虚拟滚动booleantrue4.1.0
onCheck点击复选框触发function(checkedKeys, e:{checked: bool, checkedNodes, node, event, halfCheckedKeys})-
onDragEnddragend 触发时调用function({event, node})-
onDragEnterdragenter 触发时调用function({event, node, expandedKeys})-
onDragLeavedragleave 触发时调用function({event, node})-
onDragOverdragover 触发时调用function({event, node})-
onDragStart开始拖拽时调用function({event, node})-
onDropdrop 触发时调用function({event, node, dragNode, dragNodesKeys})-
onExpand展开/收起节点时触发function(expandedKeys, {expanded: bool, node})-
onLoad节点加载完毕时触发function(loadedKeys, {event, node})-
onRightClick响应右键点击function({event, node})-
onSelect点击树节点触发function(selectedKeys, e:{selected: bool, selectedNodes, node, event})-

TreeNode props

参数说明类型默认值
checkable当树为 checkable 时,设置独立节点是否展示 Checkboxboolean-
disableCheckbox禁掉 checkboxbooleanfalse
disabled禁掉响应booleanfalse
icon自定义图标。可接收组件,props 为当前节点 propsReactNode | (props) => ReactNode-
isLeaf设置为叶子节点 (设置了 loadData 时有效)。为 false 时会强制将其作为父节点boolean-
key被树的 (default)ExpandedKeys / (default)CheckedKeys / (default)SelectedKeys 属性所用。注意:整个树范围内的所有节点的 key 值不能重复!string(内部计算出的节点位置)
selectable设置节点是否可被选中booleantrue
title标题ReactNode—-

DirectoryTree props

参数说明类型默认值
expandAction目录展开逻辑,可选:false | click | doubleClickstring | booleanclick

注意

3.4.0 之前:树节点可以有很多,但在设置 checkable 时,将会花费更多的计算时间,因此我们缓存了一些计算结果(this.treeNodesStates)来复用,避免多次重复计算,以此提高性能。但这也带来了一些限制,当你异步加载树节点时,你需要这样渲染树:

  1. {
  2. this.state.treeData.length ? (
  3. <Tree>
  4. {this.state.treeData.map(data => (
  5. <TreeNode />
  6. ))}
  7. </Tree>
  8. ) : (
  9. 'loading tree'
  10. );
  11. }

Tree 方法

名称说明
scrollTo({ key: string | number; align?: ‘top’ | ‘bottom’ | ‘auto’; offset?: number })虚拟滚动下,滚动到指定 key 条目

FAQ

在 showLine 时,如何隐藏子节点图标?

文件图标通过 switcherIcon 来实现,如果不需要你可以覆盖对应的样式:https://codesandbox.io/s/883vo47xp8

defaultExpandedAll 在异步加载数据时为何不生效?

default 前缀属性只有在初始化时生效,因而异步加载数据时 defaultExpandedAll 已经执行完成。你可以通过受控 expandedKeys 或者在数据加载完成后渲染 Tree 来实现全部展开。

虚拟滚动的限制

虚拟滚动通过在仅渲染可视区域的元素来提升渲染性能。但是同时由于不会渲染所有节点,所以无法自动拓转横向宽度(比如超长 title 的横向滚动条)。

disabled 节点在树中的关系是什么?

Tree 通过传导方式进行数据变更。无论是展开还是勾选,它都会从变更的节点开始向上、向下传导变化,直到遍历的当前节点是 disabled 时停止。因而如果控制的节点本身为 disabled 时,那么它只会修改本身而不会影响其他节点。举例来说,一个父节点包含 3 个子节点,其中一个为 disabled 状态。那么勾选父节点,只会影响其余两个子节点变成勾选状态。勾选两个子节点后,无论 disabled 节点什么状态,父节点都会变成勾选状态。

这种传导终止的方式是为了防止通过勾选子节点使得 disabled 父节点变成勾选状态,而用户无法直接勾选 disabled 父节点更改其状态导致的交互矛盾。如果你有着自己的传导需求,可以通过 checkStrictly 自定义勾选逻辑。