Tree 树形控件

何时使用#

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

API#

Tree props#

参数 说明 类型 默认值
multiple 是否支持多选 bool false
checkable 是否支持选中 bool false
defaultExpandAll 设置展开所有树节点 bool false
defaultExpandedKeys 展开指定的树节点 String[] false
defaultCheckedKeys 默认选中复选框的树节点 String[] []
defaultSelectedKeys 默认选中的树节点 String[] []
onCheck 点击树节点或复选框触发 function(e:{checked:bool,node,checkedKeys,event}) -
onSelect 点击树节点触发 function(e:{checked:bool,node,checkedKeys,event}) -
onDataLoaded 异步加载数据 function(node) -

TreeNode props#

参数 说明 类型 默认值
disabled 禁掉响应 bool false
title 标题 String '---'
key 被树的defaultCheckedKeys/defaultSelectedKeys/defaultExpandedKeys所用 String 内部计算出的节点位置

代码演示

import { Tree } from 'antd';
const TreeNode = Tree.TreeNode;

ReactDOM.render(
  <Tree defaultExpandAll={false}>
    <TreeNode title="parent 1">
      <TreeNode title="leaf" />
      <TreeNode title="parent 1-1">
        <TreeNode title="parent 2-1">
          <TreeNode title="leaf" />
          <TreeNode title="leaf" />
        </TreeNode>
        <TreeNode title="leaf" />
      </TreeNode>
    </TreeNode>
  </Tree>
, document.getElementById('components-tree-demo-basic'));

最简单的用法。

import { Tree, Button } from 'antd';
const TreeNode = Tree.TreeNode;

class TreeDemo extends React.Component {
  constructor(props) {
    super(props);
    ['handleClick', 'handleCheck', 'handleSelect'].forEach((m)=> {
      this[m] = this[m].bind(this);
    });
    this.state = {
      checkedKeys: [],
      selectedKeys: []
    };
  }
  handleClick() {
    this.setState({
      checkedKeys: ['p11'],
      selectedKeys: ['p21', 'p11']
    });
  }
  handleCheck(info) {
    console.log('check: ', info);
    this.setState({
      checkedKeys: ['p21'],
      selectedKeys: ['p1', 'p21']
    });
  }
  handleSelect(info) {
    console.log('selected: ', info);
    this.setState({
      checkedKeys: ['p21'],
      selectedKeys: ['p21']
    });
  }
  render() {
    return (<div>
      <Tree defaultExpandAll checkable
            onCheck={this.handleCheck} checkedKeys={this.state.checkedKeys}
            onSelect={this.handleSelect} selectedKeys={this.state.selectedKeys} multiple>
        <TreeNode title="parent 1" key="p1">
          <TreeNode key="p10" title="leaf"/>
          <TreeNode title="parent 1-1" key="p11">
            <TreeNode title="parent 2-1" key="p21">
              <TreeNode title="test" />
              <TreeNode title={<span>sss</span>}/>
            </TreeNode>
            <TreeNode key="p22" title="leaf"/>
          </TreeNode>
        </TreeNode>
        <TreeNode key="p12" title="leaf"/>
      </Tree>
      <Button type="primary" size="small" onClick={this.handleClick}>点此控制树节点</Button>
    </div>);
  }
}

ReactDOM.render(<TreeDemo />, document.getElementById('components-tree-demo-special'));

受控组件,外部传入参数,控制树对象节点。

import { Tree } from 'antd';
const TreeNode = Tree.TreeNode;

function handleCheck(info) {
  console.log('check: ', info);
}

ReactDOM.render(<div>
 <Tree defaultExpandAll checkable onCheck={handleCheck}>
    <TreeNode title="parent 1">
      <TreeNode title="leaf" />
      <TreeNode title="parent 1-1">
        <TreeNode title="parent 2-1">
          <TreeNode title="leaf" />
          <TreeNode title="leaf" />
        </TreeNode>
        <TreeNode title="leaf" />
      </TreeNode>
    </TreeNode>
  </Tree>
</div>
, document.getElementById('components-tree-demo-checkbox'));

提供复选框操作功能。

import { Tree } from 'antd';
const TreeNode = Tree.TreeNode;

const asyncTree = [{
  name: 'pNode 01',
  key: '0-0'
}];

const generateTreeNodes = () => {
  return [{
    name: '伯约',
    key: '0-0-0'
  }];
};

const TreeDemo = React.createClass({
  timeout(duration = 0) {
    return new Promise((resolve, reject) => {
      setTimeout(resolve.bind(this), duration);
    });
  },
  getInitialState() {
    return {
      treeData: []
    };
  },
  componentDidMount() {
    this.timeout(1000).then(() => {
      this.setState({
        treeData: asyncTree
      });
      return asyncTree;
    });
  },
  handleSelect(info) {
    console.log('selected', info);
  },
  handleDataLoaded(treeNode) {
    return this.timeout(1000).then(() => {
      const child = generateTreeNodes();
      const treeData = [...this.state.treeData];
      treeData.forEach((item) => {
        if (item.key === treeNode.props.eventKey) {
          item.children = child;
        }
      });
      this.setState({treeData});
      return child;
    });
  },
  render() {
    const loop = (data) => {
      return data.map((item) => {
        if (item.children) {
          return <TreeNode title={item.name} key={item.key}>{loop(item.children)}</TreeNode>;
        } else {
          return <TreeNode title={item.name} key={item.key} />;
        }
      });
    };
    const parseTreeNode = data => loop(data);
    let treeNodes = parseTreeNode(this.state.treeData);
    return (
      <Tree onSelect={this.handleSelect} onDataLoaded={this.handleDataLoaded} showLine={false}>
        {treeNodes}
      </Tree>
    );
  }
});

ReactDOM.render(<TreeDemo />, document.getElementById('components-tree-demo-dynamic'));

异步加载数据