antd-tree组件带搜索框的使用及踩坑(只保留搜索的内容并且标红)

前言:

最近再用Tree组件做项目,记录一下使用方法。

一、预期的效果

 antd-tree带搜索框的示例(官网):官网只是标红

我预期的效果是搜索并且标红,只保留包含搜索的值。

二、antd-tree组件带搜索框的使用及踩坑(只保留搜索的内容并且标红)

      一、方案一

  这个类似于官网的例子,但官网的例子,不是很清晰,代码很多。 

import React, { Component } from 'react';
import { Tree, Input } from 'antd';
import styles from '../../assets/index.css';
const { TreeNode } = Tree;
const { Search } = Input;
class Index extends Component {
    constructor(props) {
        super(props)
        this.state = {
            data: [
                {
                    title: "十三中学",
                    key: 1,
                    children: [
                        {
                            title: "初一年级",
                            key: 2,
                            children: [
                                {
                                    title: "一班",
                                    key: 3,
                                },
                                {
                                    title: "二班",
                                    key: 4,
                                }
                            ]
                        },
                        {
                            title: "初二年级",
                            key: 20,
                        }
                    ]
                },
                {
                    title: "八十中学",
                    key: 5,
                    children: [
                        {
                            title: "初一年级",
                            key: 6,
                            children: [
                                {
                                    title: "一班",
                                    key: 7,
                                    children: [

                                    ]
                                },
                                {
                                    title: "二班",
                                    key: 8,
                                    children: [
                                        {
                                            title: "一组",
                                            key: 9,
                                            children: []
                                        },
                                        {
                                            title: "vv组",
                                            key: 999,
                                            children: []
                                        }
                                    ]
                                }
                            ]
                        },
                        {
                            title: "初二年级",
                            key: 55,
                            children: []
                        }
                    ]
                }
            ],
            expandedKeys: [], //展开的key值
            autoExpandParent: true,
            checkedKeys: [], //选中的key,
            searchValue: '',
            searchTreeKey: [] //搜索得key
        }
    }
    //给子级添加父级Key
    addParentKeyWrapper = (tree) => {
        //深度克隆
        const data = JSON.parse(JSON.stringify(tree));
        function addParentKey(data, parentKey) {
            data.forEach(ele => {
                const { children, key } = ele;
                ele.parent_key = parentKey;
                if (children) {//如果唯一标识不是code可以自行改变
                    addParentKey(children, key)
                }
            })
        }
        addParentKey(data, null); //一开始为null,根节点没有父级
        return data;
    }
    componentDidMount() {
        this.expandedKeysFn();

        this.setState({
            data: this.addParentKeyWrapper(this.state.data) //调用添加父元素key
        })
    }
    onChange = (e) => { //search变化
        const { value } = e.target;
        console.log(value)
        const dataList = [];
        let searchElement = [];
        let allParentkey = [];
        if (value) {
            const generateList = data => { //tree树片扁平化
                for (let i = 0; i < data.length; i++) {
                    const node = data[i];
                    const { key, title, parent_key } = node;
                    dataList.push({ key, title: title, parent_key: parent_key });
                    if (node.children) {
                        generateList(node.children);
                    }
                }
            };
            generateList(this.state.data);

            const getParentKey = (key, tree) => { //获取父元素可以
                let parentKey;
                for (let i = 0; i < tree.length; i++) {
                    const node = tree[i];
                    if (node.children) {
                        if (node.children.some(item => item.key === key)) {
                            parentKey = node.key;
                        } else if (getParentKey(key, node.children)) {
                            parentKey = getParentKey(key, node.children);
                        }
                    }
                }
                return parentKey;
            };
            //上级元素
            const getParentElementKey = (searchElement, dataList) => {
                for (let i = 0; i < searchElement.length; i++) {
                    for (let j = 0; j < dataList.length; j++) {
                        if (searchElement[i] == dataList[j].key) {
                            allParentkey.push(dataList[j].key);
                            getParentElementKey([dataList[j].parent_key], dataList);
                        }
                    }
                }
            }
            const expandedKeys = dataList
                .map(item => {
                    if (item.title.indexOf(value) > -1) {
                        searchElement.push(item.key);
                        return getParentKey(item.key, this.state.data);
                    }
                    return null;
                })
                .filter((item, i, self) => item && self.indexOf(item) === i);
            getParentElementKey(searchElement, dataList);
            this.setState({
                expandedKeys: expandedKeys,
                searchValue: value,
                autoExpandParent: true,
                searchTreeKey: allParentkey
            })
        } else {
            this.expandedKeysFn() //重置展开key
            this.setState({
                searchValue: value,
                autoExpandParent: true,
                searchTreeKey: allParentkey
            })
        }
    }
    renderTreeNode = (data) => { //生成树结构函数
        if (data.length == 0) {
            return
        }
        let { expandedKeys, searchValue, searchTreeKey } = this.state;
        return data.map((item) => {
            const index = item.title.indexOf(searchValue);
            const beforeStr = item.title.substr(0, index);
            const afterStr = item.title.substr(index + searchValue.length);
            const title =
                index > -1 ? (
                    <span>
                        {beforeStr}
                        <span style={{ color: "red" }}>{searchValue}</span>
                        {afterStr}
                    </span>
                ) : (
                    <span>{item.title}</span>
                );
            if (item.children && item.children.length > 0) {
                //className={searchTreeKey.indexOf(item.key) > -1 ? styles.yes : styles.no}
                return <TreeNode className={searchTreeKey.length > 0 ? (searchTreeKey.indexOf(item.key) > -1 ? styles.yes : styles.no) : styles.yes} title={title} key={item.key} >
                    {
                        this.renderTreeNode(item.children)
                    }
                </TreeNode>
            }
            return <TreeNode className={searchTreeKey.length > 0 ? (searchTreeKey.indexOf(item.key) > -1 ? styles.yes : styles.no) : styles.yes} title={title}  ></TreeNode>
        })
    }
    expandedKeysFn = () => {
        let { data } = this.state;
        let arr = [];
        let loop = (data) => {
            data.map((item, index) => {
                arr.push(item.key);
                if (item.children && item.children.length > 0) {
                    loop(item.children)
                }
            })
        }
        loop(data);
        this.setState({
            expandedKeys: arr
        })
    }
    onExpand = expandedKeys => {
        console.log('onExpand', expandedKeys);
        this.setState({
            expandedKeys,
            autoExpandParent: false
        });
    };
    onCheck = (checkedKeys) => {
        this.setState({ checkedKeys })
    }
    render() {
        let { data, expandedKeys, autoExpandParent, checkedKeys } = this.state;
        return (
            <div>
                <Search style={{ marginBottom: 8 }} placeholder="Search" onChange={this.onChange} />
                <Tree
                    checkable
                    expandedKeys={expandedKeys} //默认展开的key
                    onExpand={this.onExpand} //展开事件
                    autoExpandParent={autoExpandParent} //是否自动展开父节点
                    checkedKeys={checkedKeys} //选中的key
                    onCheck={this.onCheck} //选中事件
                >
                    {this.renderTreeNode(data)}
                </Tree>
            </div>
        );
    }
}

export default Index

index.css 

.yes{
   
    display: block;
}
.no{
    display: none;
}

   二、 我自己写的(2021-09-09补充)

import React, { Component } from 'react';
import { Form, Input, Tree } from 'antd';
const TreeNode=Tree.TreeNode;
import styles from './index.less';
const { Search } = Input;
const treeData = [
    {
        title: '0-0',
        key: '0-0',
        children: [
            {
                title: '0-0-0',
                key: '0-0-0',
                children: [
                    { title: '0-0-0-0-88', key: '0-0-0-0' },
                    { title: '0-0-0-1', key: '0-0-0-1' },
                    { title: '0-0-0-2', key: '0-0-0-2' },
                ],
            },
            {
                title: '0-0-1',
                key: '0-0-1',
                children: [
                    { title: '0-0-1-0', key: '0-0-1-0' },
                    { title: '0-0-1-1', key: '0-0-1-1' },
                    { title: '0-0-1-2', key: '0-0-1-2' },
                ],
            },
            {
                title: '0-0-2',
                key: '0-0-2',
            },
        ],
    },
    {
        title: '99',
        key: '0-1',
        children: [
            { title: '0-1-0-0', key: '0-1-0-0' },
            { title: '9988', key: '0-1-0-1' },
            { title: '0-1-0-2-99988', key: '0-1-0-2' },
        ],
    },
    {
        title: '0-2',
        key: '0-2',
    },
];
class Index extends Component {
    constructor(props) {
        super(props);
        this.state = {
            expandedKeys: [],//树节点展开key
            treeData: [],
            copyTree: [],//备份 treeData
            copyExpandedKeys: [], //备份 展开key 
            searchValue: ""
        }
    }
    componentDidMount() {
        let a = this.expandedKeysFun(treeData); //展开key
        let cp = JSON.stringify(treeData); //这个是最简单的 深拷贝
        this.setState({
            treeData: treeData,
            expandedKeys: a,
            copyTree: cp,
            copyExpandedKeys: a
        })
    }

    arrayTreeFilter = (data, predicate, filterText) => {
        const nodes = data;
        // 如果已经没有节点了,结束递归
        if (!(nodes && nodes.length)) {
            return;
        }
        const newChildren = [];
        for (const node of nodes) {
            if (predicate(node, filterText)) {
                // 如果自己(节点)符合条件,直接加入到新的节点集
                newChildren.push(node);
                // 并接着处理其 children,(因为父节点符合,子节点一定要在,所以这一步就不递归了)
                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.title) //我是一title过滤 ,你可以根据自己需求改动
        );
    }
    flatTreeFun = (treeData) => { //扁平化 tree
        let arr = [];
        const flatTree = (treeData) => {
            treeData.map((item, index) => {
                arr.push(item);
                if (item.children && item.children.length > 0) {
                    flatTree(item.children);
                    item.children = [];
                }
            })
        }
        flatTree(treeData);
        return arr;
    }
    expandedKeysFun = (treeData) => { //展开 key函数
        if (treeData && treeData.length == 0) {
            return [];
        }
        //console.log(treeData)
        let arr = [];
        const expandedKeysFn = (treeData) => {
            treeData.map((item, index) => {
                arr.push(item.key);
                if (item.children && item.children.length > 0) {
                    expandedKeysFn(item.children);
                }
            })
        }
        expandedKeysFn(treeData);
        return arr;
    }
    onChange = (e) => { //搜索框 change事件
        let value = e.target.value;
        if (value == "") { //为空时要回到最初 的树节点
            let { copyTree, copyExpandedKeys } = this.state;
            // let res = this.arrayTreeFilter(JSON.parse(copyTree), this.filterFn, value);
            // let expkey = this.expandedKeysFun(res);
            this.setState({
                treeData: JSON.parse(copyTree),
                expandedKeys: copyExpandedKeys
            })
        } else {
            let res = this.arrayTreeFilter(treeData, this.filterFn, value);
            let expkey = this.expandedKeysFun(res);
            this.setState({
                treeData: res,
                expandedKeys: expkey,
                searchValue:value
            })
        }
    }

    renderTreeNode = (data) => { //生成树结构函数
        if (data.length == 0) {
            return
        }
        let { expandedKeys, searchValue } = this.state;
        return data.map((item) => {
            const index = item.title.indexOf(searchValue);
            const beforeStr = item.title.substr(0, index);
            const afterStr = item.title.substr(index + searchValue.length);
            const title =
                index > -1 ? (
                    <span>
                        {beforeStr}
                        <span style={{ color: "red" }}>{searchValue}</span>
                        {afterStr}
                    </span>
                ) : (
                    <span>{item.title}</span>
                );
            if (item.children && item.children.length > 0) {
                return <TreeNode key={item.key} title={title} >
                    {
                        this.renderTreeNode(item.children)
                    }
                </TreeNode>
            }
            return <TreeNode key={item.key} title={title}  ></TreeNode>
        })
    }

    onExpand = expandedKeys => {
        this.setState({
            expandedKeys,
        });
    };
    render() {
        let { expandedKeys, treeData } = this.state;
        return (
            <div>
                <Search style={{ marginBottom: 8 }} placeholder="Search" onChange={this.onChange} />
                <Tree
                    checkable
                    onExpand={this.onExpand}
                    expandedKeys={expandedKeys}
                    autoExpandParent={true}
                // treeData={treeData}
                >
                    {
                        this.renderTreeNode(treeData)
                    }
                </Tree>
            </div>
        )
    }

}
export default Index

antd Tree组件 搜索标红 例子

 数据量大造成的卡顿

可以给Tree加一个height属性:使用 height 属性则切换为虚拟滚动。

<Tree height={500}/>

这样可以缓解卡顿现象

antd tree虚拟滚动

总结:

想要antd-tree组件带搜索框的使用及踩坑(只标红)可以看这篇。

我自己实现的antd Tree带搜索 

react-antd Tree(树形组件)默认展开和选中踩坑及使用 可以看这篇

  • 7
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
antd-datepicker是Ant Design中提供的日期选择器组件,可用于选择日期和时间值。获取时间值的方式有以下几种: 1. 使用onChange事件:在DatePicker组件上绑定onChange事件,当用户选择了日期或时间时,会触发该事件并将选择的时间值作为参数传递给回调函数。可以通过e.target.value来获取选择的时间值。 ```jsx <DatePicker onChange={handleDateChange} /> ``` ```jsx const handleDateChange = (value) => { console.log(value); // 可以对选择的时间值进行相关处理 } ``` 2. 使用moment.js库:Ant Design的DatePicker组件默认返回的是Moment.js对象,可以使用该库提供的方法来获取和处理时间值。 ```jsx import moment from 'moment'; <DatePicker onChange={handleDateChange} /> ``` ```jsx const handleDateChange = (value) => { const selectedValue = moment(value).format('YYYY-MM-DD'); console.log(selectedValue); // 可以对选择的时间值进行相关处理 } ``` 相关设置方式包括: 1. 默认时间值:可以通过设置defaultValue属性来指定DatePicker组件的默认时间值。 ```jsx <DatePicker defaultValue={moment('2022-01-01', 'YYYY-MM-DD')} /> ``` 2. 可选时间范围:可以通过设置disabledDate属性来限制可选的时间范围。该属性接收一个函数,根据函数的返回值来控制禁用的日期。 ```jsx <DatePicker disabledDate={disabledDate} /> ``` ```jsx const disabledDate = (current) => { // 返回true表示禁用该日期 return current && current < moment().endOf('day'); } ``` 3. 时间格式:可以通过设置format属性来指定DatePicker组件的时间格式。 ```jsx <DatePicker format="YYYY-MM-DD HH:mm:ss" /> ``` 以上就是antd-datepicker组件获取时间值及相关设置方式的介绍。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

崽崽的谷雨

漫漫前端路,摸爬滚打

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值