antd 的 Tree 控件没有提供点击展开的功能,只能通过左边的三角形实现展开和收起,没办法只好自己实现这个功能。

先看效果



如图实现的是类似 Mac 文件目录形式的结构,有箭头代表是个文件夹,点击展开文件夹,点击外层文件夹可以收起整个文件夹。

首先根据服务器返回的 Json 数据生成树形结构

const data = {
name: "root",
children: [{
name: "a",
value: "/a",
children: [{
name: "file_1",
value: "/a/file_1"
}, {
name: "a_1",
value: "/a/a_1",
children: [{
name: "file_2",
value: "/a/a_1/file_2"
}, {
name: "file_3",
value: "/a/a_1/file_3"
}]
}, {
name: "a_2",
value: "/a/a_2",
children: [{
name: "file_4",
value: "/a/a_2/file_4"
}, {
name: "file_5",
value: "/a/a_2/file_5"
}]
}]
}, {
name: "b",
value: "/b",
children: [{
name: "b_1",
value: "/b/b_1",
children: [{
name: "file_6",
value: "/b/b_1/file_6"
}]
}]
}]
}

数据结构中有 children 字段代表是个文件夹,因此需要递归遍历出 TreeNode 视图

import React from "react";
import Tree from 'antd/lib/tree';
import 'antd/lib/tree/style/css'; const TreeNode = Tree.TreeNode; class TreeView extends React.Component {
//遍历json绘制出tree结构
mapData = (children) => {
if (children && Array.isArray(children)) {
return children.map((ele) => {
if (ele.children && Array.isArray(ele.children)) {
return <TreeNode title={ele.name} key={ele.value}>
{this.mapData(ele.children)}
</TreeNode>
} else {
return <TreeNode title={ele.name} key={ele.value}/>
}
})
}
return []
} render() {
let content = [] let {name, children} = data
if (name) {
content.push(<TreeNode title={name} key="/">{this.mapData(children)}</TreeNode>)
} return (
<Tree>
{content}
</Tree>
);
}
} export default TreeView

已经完成第一步,生成树形结构视图。接下来就是要实现点击展开树形结构

state = {
expandedKeys: ["/"],
autoExpandParent: true,
selectedKeys: []
} //选中的回调
onSelect = (selectedKeys, obj) => {
let {expandedKeys} = this.state
let selectedKey = this.state.selectedKeys
//选中的状态
if (obj.selected) {
//判断是否已经展开,未展开就添加到 expandedKeys 中
//已经展开就不用管
let index = expandedKeys.indexOf(selectedKeys[0])
if (index === -1) {
expandedKeys.push(selectedKeys[0])
this.setState({
expandedKeys: expandedKeys,
selectedKeys: selectedKeys
})
} else {
this.setState({
selectedKeys: selectedKeys
})
} // 没有 children 代表当前已没有下一级目录
if (obj.event && obj.selectedNodes.length === 1 && !obj.selectedNodes[0].props.children) {
//do something
}
} else {
//selectedKey 是上次选中的元素 在 expandedKeys 肯定是存在的
//找到下标后需要过滤掉子类目录 例如上次选中的元素为 /a ,
//子类 /a/a_1 已经展开就需要从 expandedKeys 中移除这个元素
let index = expandedKeys.indexOf(selectedKey[0])
if (index !== -1) {
//过渡掉子类元素
expandedKeys = expandedKeys.filter((ele) => {
return !ele.includes(selectedKey[0])
})
this.setState({
expandedKeys: expandedKeys,
selectedKeys: []
})
} else {
this.setState({
selectedKeys: []
})
}
}
} //展开的回调
onExpend = (expandedKey, obj) => {
let {expandedKeys} = this.state
//展开的状态
if (obj.expanded) {
this.setState({
expandedKeys: expandedKey,
selectedKeys: []
})
} else {
//expandedKey 返回的是当前已经展开的元素 expandedKeys 是上次展开的元素
//比较两个数组中缺少的元素得出当前被收起的是哪个元素
let removeArray = this.diffArray(expandedKey, expandedKeys)
//收起的时候需要把里面展开的元素一并移除,不然会造成收起动作无效
expandedKeys = expandedKeys.filter((ele) => {
return !ele.includes(removeArray[0])
})
this.setState({
expandedKeys: expandedKeys,
selectedKeys: []
})
}
} //比较出2个数组中不一样的元素
diffArray = (arr1, arr2) => {
let arr3 = [];
for (let i = 0; i < arr1.length; i++) {
if (arr2.indexOf(arr1[i]) === -1)
arr3.push(arr1[i]);
}
for (let j = 0; j < arr2.length; j++) {
if (arr1.indexOf(arr2[j]) === -1)
arr3.push(arr2[j]);
}
return arr3;
}
......
render() {
return (
<Tree
onExpand={this.onExpend}
expandedKeys={this.state.expandedKeys}
autoExpandParent={this.state.autoExpandParent}
onSelect={this.onSelect}
selectedKeys={this.state.selectedKeys}>
{content}
</Tree>
)
}

根index.js文件

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker'; ReactDOM.render(<App />, document.getElementById('root'));
registerServiceWorker();

根APP组件

import React, {Component} from 'react';
import logo from './logo.svg';
import './App.css';
import TreeView from "./TreeView"; class App extends Component {
render() {
return (
<div className="App">
<div className="App-header">
<img src={logo} className="App-logo" alt="logo"/>
</div>
<div style={{marginTop: "100px"}}>
<TreeView/>
</div>
</div>
);
}
} export default App;

本文学习自:https://www.jianshu.com/p/d104f491b8c9

antd的Tree控件实现点击展开功能的更多相关文章

  1. vue+element项目中使用el-dialog弹出Tree控件报错问题

    1. 按正常的点击按钮,显示dialog弹出的Tree控件,然后把该条数据下的已经选中的checkbox , 用setCheckedNodes或者setCheckedKeys方法选择上 , 报下面这个 ...

  2. ElementUI Tree控件在懒加载模式下的重新加载和模糊查询

    之所以使用懒加载是为了提高性能,而且只有在懒加载模式下默认会给所有显示节点设置展开按钮.leaf也可以做到,但是要操作数据比较麻烦. 要实现懒加载模式下的模糊查询以及重新加载必须要使用data与laz ...

  3. Android 使用代码主动去调用控件的点击事件(模拟人手去触摸控件)

    使用代码主动去调用控件的点击事件(模拟人手去触摸控件) //View 可以是LinearLayout,Button,TextView View.performClick();

  4. easyui中tree控件添加自定义图标icon

    来源于:http://blog.163.com/lintianhuanhai@126/blog/static/165587366201421704420256/ <!DOCTYPE html&g ...

  5. DWZ (JUI) 教程 tree 控件的选中事件

    DWZ (JUI) 教程 tree 控件的选中事件 先简单说一下流程 第一步 当然是先定义好回调事件了 function checkCallback(json){ ........... ...... ...

  6. webdynpro tree控件使用

    1.  首先创建一个TREE控件 2.  在Tree下面创建一个TREE  NODE  TYPE ,node type 是可以继续展开的,而Item type是无法展开的. 3. 创建node.,下面 ...

  7. Kinect用体感来实现UI控件的点击

    用体感来实现UI控件的点击,如点击按钮. 做法:用一个图片表示左手手掌,图片位置追踪左手手掌移动,当手掌位于UI控件的矩形内时,握拳表示点击该控件. using UnityEngine; using ...

  8. UiAutomator2.0 - 控件实现点击操作原理

    目录 一.UiObject 二.UiObject2 穿梭各大技术博客网站,每天都能看到一些的新的技术.突然感觉UiAutomator 2.0相对于现在来说已经是个很久远的东西了ε=(´ο`*))).写 ...

  9. android中RecyclerView控件实现点击事件

    RecyclerView控件实现点击事件跟ListView控件不同,并没有提供类似setOnItemClickListener()这样的注册监听器方法,而是需要自己给子项具体的注册点击事件. 本文的例 ...

随机推荐

  1. Javascript数组系列五之增删改和强大的 splice()

    今天是我们介绍数组系列文章的第五篇,也是我们数组系列的最后一篇文章,只是数据系列的结束,所以大家不用担心,我们会持续的更新干货文章. 生命不息,更新不止! 今天我们就不那么多废话了,直接干货开始. 我 ...

  2. 【案例分享】crontab执行脚本异常问题

    很多时候我们会遇见这种情况,我们千辛万苦写了一个脚本,经过测试,一切正常,然后放到了crontab里面执行,结果,不管怎么配置,就是执行不正常. 结果发现环境问题,居然是这个异常的元凶. 我们先在我们 ...

  3. linux备份还原命令

    使用范围:1.可以作为系统还原点,还原到备份时的状态 2.系统完全损坏后无法启动,通过引导盘恢复 一.备份还原系统命令 方法一: 备份:tar cvpzf backup.tgz --exclude=/ ...

  4. $.extend()浅拷贝深拷贝

    参考网址:http://bijian1013.iteye.com/blog/2255037 jQuery.extend() 函数用于将一个或多个对象的内容合并到目标对象. 注意:1. 如果只为$.ex ...

  5. Luogu5058 [ZJOI2004]嗅探器

    $Luogu5058 [ZJOI2004]嗅探器 给定一张 \(n\) 个点, \(m\) 条边的无向图,和两点 \(s,\ t\) ,求 \(s\to t\) 编号最小的必经点(排除 \(s,\ t ...

  6. Spring的事件机制详解

    同步事件和异步事件 同步事件:在一个线程里,按顺序执行业务,做完一件事再去做下一件事. 异步事件:在一个线程里,做一个事的同事,可以另起一个新的线程执行另一件事,这样两件事可以同时执行. 用一个例子来 ...

  7. ZJOI2019做题笔记

    麻将(期望.DP套DP) 先考虑如何计算一个子集是否能胡. 设\(f_{i,0/1,j,k}\)表示考虑了子集中\(1 \sim i\)的牌,是否找到对子,\(i-1,i,i+1\)预计拿\(j\)个 ...

  8. 领域驱动设计系列文章(2)——浅析VO、DTO、DO、PO的概念、区别和用处

    本篇文章主要讨论一下我们经常会用到的一些对象:VO.DTO.DO和PO. 由于不同的项目和开发人员有不同的命名习惯,这里我首先对上述的概念进行一个简单描述,名字只是个标识,我们重点关注其概念: 概念: ...

  9. 如何基于Winform开发框架或混合框架基础上进行项目的快速开发

    在开发项目的时候,我们为了提高速度和质量,往往不是白手起家,需要基于一定的基础上进行项目的快速开发,这样可以利用整个框架的生态基础模块,以及成熟统一的开发方式,可以极大提高我们开发的效率.本篇随笔就是 ...

  10. linux安装tomcat部署web项目

    我用的是如下图的两个软件,连接linux服务器. 其中WinSCp是传输文件用的,SecureCRT是用来输入命令的. 1.复制tomcat到指定目录(可复制到你想要的目录下),命令如下: cp /路 ...