java tree展开,antd的Tree控件实现点击展开功能

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

13977af42069cdf496a9799923b41351.gif 如图实现的是类似 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

{this.mapData(ele.children)}

} else {

return

}

})

}

return []

}

render() {

let content = []

let {name, children} = data

if (name) {

content.push({this.mapData(children)})

}

return (

{content}

);

}

}

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 (

onExpand={this.onExpend}

expandedKeys={this.state.expandedKeys}

autoExpandParent={this.state.autoExpandParent}

onSelect={this.onSelect}

selectedKeys={this.state.selectedKeys}>

{content}

)

}

根index.js文件

import React from 'react';

import ReactDOM from 'react-dom';

import './index.css';

import App from './App';

import registerServiceWorker from './registerServiceWorker';

ReactDOM.render(, 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 (

logo

);

}

}

export default App;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值