美文网首页让前端飞Web前端之路
基于Ant Design的Tree可搜索树形组件

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

作者: 虚拟J | 来源:发表于2020-03-12 11:35 被阅读0次

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

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

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

    • 方案:

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

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

    直接上假数据和代码

    [{
            "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') ?
                        <TreeNode title={<span style={item.knowledgeName.includes(antistop) ? { color: 'rgb(255, 85, 0)' } : {}}>{item.knowledgeName}</span>} key={item.knowledgeId} icon={<><Icon type="plus-circle" /><Icon type="minus-circle" /></>} >
                            <> {recursion(item.children)}</>
                        </TreeNode> :
                        <TreeNode title={<span style={item.knowledgeName.includes(antistop) ? { color: 'rgb(255, 85, 0)' } : {
                            color: `${nowSelect == item.knowledgeId ? '#409EFF' : ''}`
                        }}>{item.knowledgeName}</span>} key={item.knowledgeId} />
                ))
            }
            </>
        }
    
        return (
          <Sider className={style.left}>
                <Search className={style.keyword} placeholder="输入知识点关键字" onChange={onChange} />
                <div style={{ position: 'relative', left: '-20px', width: 270, overflow: 'scroll', height: 'calc( 100% - 65px)' }}  >
                    <Tree
                        switcherIcon={<></>}
                        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)}
                    </Tree>
                </div>
         </Sider>
        )
    }
    
    .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;
                    }
                }
            }
        }
    }
    

    相关文章

      网友评论

        本文标题:基于Ant Design的Tree可搜索树形组件

        本文链接:https://www.haomeiwen.com/subject/vtyyjhtx.html