zoukankan      html  css  js  c++  java
  • antd的Tree控件实现点击展开功能

    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

  • 相关阅读:
    error C2065: “SHCNE_DELETE”: 未声明的标识符
    error C2872: ‘ofstream’ : ambiguous symbol
    error C2065: ‘__in’ : undeclared identifier
    LINK : fatal error LNK1561: 必须定义入口点
    VS2010提示error TRK0002: Failed to execute command
    js怎么获取一个单位为rem的元素真实宽/高度?
    将时间转化为几秒前 几分钟前 几小时前...
    uni-app picker 组件实现二级联动?
    uni-app scroll-view 点击实现元素居中?
    初始化CSS样式
  • 原文地址:https://www.cnblogs.com/smart-girl/p/10782797.html
Copyright © 2011-2022 走看看