antd-tree树形组件带搜索框的实际应用

 

 需求视图

import React, { Component } from 'react';
import { Form, Input, Tree } from 'antd';
const TreeNode=Tree.TreeNode;

const { Search } = Input;
const treeData = [
    {
        deptName: '总部',
        deptId: 'HQ001',
        children: [
            {
                proName: '金街大厦',
                proId: 'ea23sdf',
                children: [
                    { proName: 'ceshi', proId: '15478cc' },
                    { proName: '测试项目', proId: 'cvb25sa' },
                    { proName: 'xxceshiyi', proId: 'f95esc2' },
                ],
            },
            {
                proName: '金街管理',
                proId: 'f23564d',
                children: [
                    { proName: '测试新增项目', proId: '25dfbn3' },
                    { proName: '建筑', proId: 'rt89gh2' },
                    { proName: '0-0-1-2', proId: 'sd9562v' },
                ],
            },
            {
                proName: 'haha',
                proId: '23148dg',
            },
        ],
    },
    {
        deptName: '北京',
        deptId: '548cvfg',
        children: [
            { proName: '北京1', proId: '1236llo' },
            { proName: '叨叨', proId: 'ea82ssk' },
            { proName: 'beijing', proId: 'fyu831x' },
        ],
    },
    {
        deptName: '上海',
        deptId: '54fae89',
    },
];


class Index extends Component {
    constructor(props) {
        super(props);
        this.state = {
            loading: false,
            expandedKeys: [], // 存树节点展开key
            treeData: []
            autoExpandParent: false, // 默认层级不展开
        }
    }


    expandedKeysFun = (treeData) => { // 展开 key函数
        if (treeData && treeData.length == 0) {
            return [];
        }
        //console.log(treeData)
        let arr = [];
        const expandedFn = (Data) => {
            Data.map((item, index) => {
                arr.push(item.key);
                if (item.children && item.children.length > 0) {
                    expandedKeysFn(item.children);
                }
            })
        }
        // 执行expandedFn函数,把treeData传给Data
        expandedFn(treeData);
        return arr;
    }

    // 点击搜索:若有子级符合搜索条件,显示展开过滤搜索出的子级;不符合的就不显示出来
    onSearch = (value) => {  // 搜索框
        if (value == "") { // 为空时层级不展开
            // 还要调接口刷新下页面,接口我略写
            axios.post('', {}).then(res => {})
            this.setState({
                expandedKeys: [],
                autoExpandParent: false, // 不展开层级
                loading: false,
            })
        } else {
            let res = this.arrayTreeFilter(treeData, this.filterFn, value);
            let expkey = this.expandedKeysFun(res);
            this.setState({
                expandedKeys: expkey,
                autoExpandParent: true,
            })
        }
    }

    // 过滤数据
    arrayTreeFilter = (data, predicate, filterText) => {
        const nodes = data;
        // 如果已经没有节点了,结束递归
        if (!(nodes && nodes.length)) {
            return;
        }
        const newChildren = [];
        for (const node of nodes) { // for..of循环, node即item
            if (predicate(node, filterText)) {
                // 如果自己(节点)符合条件,直接加入到新的节点集
                newChildren.push(node);
                // 并接着处理其 children,(因为父节点符合,子节点一定要在,所以这一步就不递归了)
                if(node.children && node.children.length > 0) {
                    node.children = this.arrayTreeFilter(node.children, predicate, filterText);
                }
            } else {
                // 如果自己不符合条件,需要根据子集来判断它是否将其加入新节点集
                // 根据递归调用 arrayTreeFilter() 的返回值来判断
                const subs = this.arrayTreeFilter(node.children, predicate, filterText);
                // 以下两个条件任何一个成立,当前节点都应该加入到新子节点集中
                // 1. 子孙节点中存在符合条件的,即 subs 数组中有值
                // 2. 自己本身符合条件
                if ((subs && subs.length) || predicate(node, filterText)) {
                    node.children = subs;
                    newChildren.push(node);
                }
            }
        }
        return newChildren;
    }

     //过滤函数
    filterFn = (data, filterText) => {
        if (!filterText) {
            return true;
        }
        return (
            new RegExp(filterText, "i").test(data.deptName|| data.proName) //根据xxname过滤 ,因为父级name与子级name不一样,写个||
        );
    }
 
    // 1. 生成树结构函数
    // 项目列表渲染的方法
    renderTreeNode = (data) => {
        if (data.length == 0) {
            return
        }
        let { expandedKeys, searchValue } = this.state;
        return data && data.length > 0 && data.map((item) => {
            if (item.children && item.children.length > 0) {
                
                return (
<TreeNode value={item.deptName} key={item.deptId} title={item.deptName} dataRef={item}>
                    {/* 展示父级数据 */}
                    {this.renderTreeNode(item.children)}
                </TreeNode>
                )
            }
            // 展示子级的数据
            return <TreeNode value={item.proName} key={item.proId} title={item.proName} dataRef={item}></TreeNode>
        })
    }
 
    onExpand = expandedKeys => {
        this.setState({
            expandedKeys,
            autoExpandParent: false,
        });
    };

    render() {
        const { expandedKeys, treeData, autoExpandParent, loading } = this.state;
        return (
            <div>
                <div>项目列表</div>
                <Search
                    placeholder="请输入项目名称"
                    enterButton="检索"
                    onSearch={value => this.onSearch(value)}
                />
                <div className={styles.listParentStyle}>
                    <Spin loading={loading}>
                        <Tree
                            allowClear
                            onExpand={this.onExpand}
                            expandedKeys={expandedKeys}
                            autoExpandParent={autoExpandParent}
                            blockNode // 节点占据一行,这样点击话不用必须点击字本身上才触发
                        >
                        {this.renderTreeNode(treeData)}
                        </Tree>
                    </Spin>
                </div>
            </div>
        )
    }
 
}
export default Index

 拓展----如果标题太长想要省略,还想要有文字提示Tooltip或者气泡卡片Popover

        部分代码:

import cutStringLength from 'utils/utils'


....

return data && data.length > 0 && data.map((item) => {
            if (item.children && item.children.length > 0) {
                
                return (
<TreeNode value={item.deptName} key={item.deptId} title={<Popover content={item.deptName} trigger='hover' palcement='right'><span style={{ border:'1px solid #fff', display: 'block'}}>{cutStringLength(item.deptName, 20)}</span></Popover>} dataRef={item} className={styles.listStyle}>
                    {/* 展示父级数据 */}
                    {this.renderTreeNode(item.children)}
                </TreeNode>
                )
            }
            // 展示子级的数据
            return <TreeNode value={item.proName} key={item.proId} title={<Popover content={item.proName} trigger='hover' palcement='right'><span style={{ border:'1px solid #fff', display: 'block'}}>{cutStringLength(item.proName, 20)}</span></Popover>} dataRef={item}></TreeNode>
        })




styles文件
    .listParentStyle {
        ul li {
            span:nth-child(2n){
                font-weight:600;
            }
        }
    .listStyle {
        ul li {
            span:nth-child(2n){
                font-weight:400;
            }
        }
        ul li .ant-tree-node-content-wrapper:hover {
            background-color: #f0fbff;
        }
    }
}    


utils/utils文件:
// strName 文本  len长度
export function cutStringLength (strName, len) {
    if(strName == null) {
        return ''
    }
    if(strName.length > len) {
        return `${strName.substring(0, len-1)}...`
    }
    return strName
}

参考图片

        即使不用点击文字本身,点击文字所在当前行,这行文字也会被点中,并且显示背景色

项目中用到Tree组件,并且还能进行搜索

代码供参考

博主写的不错:

http://t.csdnimg.cn/FSCqH

 相关文章

react–antd 实现TreeSelect树形选择组件,实现点开一层调一次接口

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据提供的代码,可以看出这是一个使用antd-v的table tree组件。要实现全部展开和全部折叠的功能,可以通过控制每一行的展开状态来实现。 首先,你可以在data中添加一个属性来表示每一行的展开状态,例如isExpanded。然后,在expandIcon方法中,根据isExpanded的值来确定展开图标的类型。 要实现全部展开的功能,你可以遍历data数组,将每一行的isExpanded属性设置为true。要实现全部折叠的功能,你可以将每一行的isExpanded属性设置为false。 最后,重新渲染table组件,根据每一行的isExpanded属性来确定展开图标的类型。 以下是一个示例代码,用于实现全部展开和全部折叠的功能: ```javascript // 在data中添加isExpanded属性 data.forEach(item => { item.isExpanded = true; // 默认全部展开 }); // 在expandIcon方法中根据isExpanded属性确定展开图标的类型 expandIcon(props) { if (props.record.children.length > 0) { if (props.record.isExpanded) { return ( <span class="table-icon" onClick={(e) => { props.onExpand(props.record, e); }}> <a-icon type="caret-down" /> </span> ); } else { return ( <span class="table-icon" onClick={(e) => { props.onExpand(props.record, e); }}> <a-icon type="caret-right" /> </span> ); } } else { return <span style="margin-right:19px"></span>; } } // 添加全部展开和全部折叠的功能 handleExpandAll() { data.forEach(item => { item.isExpanded = true; }); // 重新渲染table组件 // ... } handleCollapseAll() { data.forEach(item => { item.isExpanded = false; }); // 重新渲染table组件 // ... } ``` 通过调用handleExpandAll和handleCollapseAll方法,你可以实现全部展开和全部折叠的功能。 #### 引用[.reference_title] - *1* [antd-vue的树形table组件修改展开图标](https://blog.csdn.net/qq_40567849/article/details/124443188)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值