基于Ant Design的Tree可搜索树形组件

Ant Design中的Tree不能直接拿来满足设计图的样子和需求,按还是基于andt的Tree进行了一些改造。

  • 问题:自定义树节点的展开/折叠图标
antd提供了一个switcherIcon属性,用来自定义图标

但是没有专门区分展开和折叠的图标样子,展开和折叠图标的区别,就是旋转角度而已。所以做不到设计图上的样子。

  • 方案:

icon={<>}
我是通过在TreeNode节点上的icon属性上加入了2个图标,通过class去控制图标的显示。

生成的节点和搜索功能,都是通过函数的递归调用去完成。

直接上假数据和代码(提醒:下面是有涉及到 less 和 CSSModules 的用法)

[{
        "knowledgeId": 1,
        "knowledgeName": "数与式",
        "subjectId": 2,
        "phaseId": 2,
        "children": [{
            "knowledgeId": 2,
            "knowledgeName": "有理数",
            "subjectId": 2,
            "phaseId": 2,
            "children": [{
                "knowledgeId": 3,
                "knowledgeName": "正式和负数",
                "subjectId": 2,
                "phaseId": 2,
                "children": [{
                    "knowledgeId": 4,
                    "knowledgeName": "正式、负数的意义",
                    "subjectId": 2,
                    "phaseId": 2,
                }, {
                    "knowledgeId": 5,
                    "knowledgeName": "相反意义的量",
                    "subjectId": 2,
                    "phaseId": 2,
                }, {
                    "knowledgeId": 6,
                    "knowledgeName": "正负数在实际生活",
                    "subjectId": 2,
                    "phaseId": 2,
                }]
            }, {
                "knowledgeId": 7,
                "knowledgeName": "有理数的初步认识",
                "subjectId": 2,
                "phaseId": 2,
            }]
        }]
    }, {
        "knowledgeId": 8,
        "knowledgeName": "方程与不等式",
        "subjectId": 2,
        "phaseId": 2,
        "children": [{
            "knowledgeId": 9,
            "knowledgeName": "一元二次方程",
            "subjectId": 2,
            "phaseId": 2,
        }]
    }]
import React, { useState, useEffect } from 'react';
import style from './fineQuestion.less';
import { Icon, Select, Tree, Input } from "antd";
const { Search } = Input;
const { TreeNode } = Tree;

export default function QuestionMenu(props) {
    const [unfolds, setUnfolds] = useState([]);
    const [nowSelect, setNowSelect] = useState('');
    const [autoExpandParent, setAutoExpandParent] = useState(false);
    const [antistop, setAntistop] = useState(false);

//获取需要展开的节点
    function getKey(data, cun, value, expandedKeys) {
        data.map((item, i) => {
            cun = cun + ',' + item.knowledgeId;
            if (item.knowledgeName.indexOf(value) > -1) {
                expandedKeys.push(...cun.split(','))
            }
            if (item.hasOwnProperty('children')) {
                getKey(item.children, cun, value, expandedKeys);
            }
        })
    }
//输入框关键词搜索
    function onChange(e) {
        const { value } = e.target;
        const expandedKeys = [];
        if (value === '') {
            setAntistop(false)
            return
        }
        props.treeStructure.map(item => {
            let cun = item.knowledgeId;
            getKey(item.children, cun, value, expandedKeys);
        })

        setAntistop(value)
        setAutoExpandParent(true)
        setUnfolds([...new Set(expandedKeys)])
    };

//生成树节点
    function recursion(data) {
        return <>  {
            data.map((item, i) => (
                item.hasOwnProperty('children') ?
                    {item.knowledgeName}} key={item.knowledgeId} icon={<>} >
                        <> {recursion(item.children)}
                     :
                    {item.knowledgeName}} key={item.knowledgeId} />
            ))
        }
        
    }

    return (
      
} showIcon={true} expandedKeys={unfolds} autoExpandParent={autoExpandParent} onSelect={(selectedKeys, e) => { let key = e.node.props.eventKey; if (unfolds.length === 0) { setUnfolds(selectedKeys) return; } if (e.node.props.hasOwnProperty('children') && !unfolds.includes(key)) { //展开 unfolds.push(key) } else if (e.selectedNodes.length > 0 && !e.selectedNodes[0].props.children) { // 最后一层 setNowSelect(key) } else if (unfolds.includes(key)) { // 收缩 let index = unfolds.indexOf(key) unfolds.splice(index, 1) } setUnfolds(unfolds) setAutoExpandParent(false) }}> {recursion(props.treeStructure)}
) } /* treeStructure 树结构数据 */ QuestionMenu.defaultProps = { treeStructure: [] };
.left {
    background   : rgba(255, 255, 255, 1);
    border-radius: 3px 3px 3px 3px;
    height       : 100%;
    flex         : 0 0 250px !important;
    max-width    : 250px !important;
    overflow     : hidden;
    .keyword {
        margin : 20px 0 10px;
        padding: 0 13px;
        height : 36px;
        input {
            border-radius: 18px;
            padding-left : 16px;
        }
        span {
            font-size: 20px;
            right    : 30px;
        }
    }
    :global(.ant-tree-node-content-wrapper-close) {
        :global(.anticon-minus-circle) {
            display: none;
        }
    }
    :global(.ant-tree-node-content-wrapper-open) {
        :global(.anticon-plus-circle) {
            display: none;
        }
    }
    :global(.ant-tree) {
        li {
            :global(.ant-tree-node-content-wrapper.ant-tree-node-selected) {
                background: #fff !important;
                color     : #000000 !important;
            }
            :global(.ant-tree-node-content-wrapper) {
                color: #000000;
                &:hover {
                    background: #fff !important;
                    color     : #409EFF !important;
                }
            }
        }
    }
}

因为数据量大,可能会接口比较慢,或者这边生成时间比较长,加一个Spin组件,用户体验会好点。

你可能感兴趣的:(基于Ant Design的Tree可搜索树形组件)