react echarts tree树图搜索展开功能示例详解

当用户需要展示树形结构数据时,react-echarts库提供了一个很好的解决方案:树图。除此之外,还可以为树图添加搜索和展开等交互功能,方便用户更好地查看数据。在本文中,我们将为您展示如何在react-echarts中实现这些功能。

当用户需要展示树形结构数据时,react-echarts库提供了一个很好的解决方案:树图。除此之外,还可以为树图添加搜索和展开等交互功能,方便用户更好地查看数据。在本文中,我们将为您展示如何在react-echarts中实现这些功能。

前置条件

在进行以下步骤之前,请确保您已经安装以下依赖项:

  1. React:16.8.0 以上版本
  2. Echarts:5.0.2 以上版本
  3. React-echarts:7.2.1 以上版本

树图

首先,我们需要安装React-echarts组件并导入它。

import ReactECharts from 'echarts-for-react';

接下来,让我们创建一个React组件,并在该组件中初始化一个简单的树图。具体来说,我们将创建一个带有简单大小的节点的树图,并设置其相关配置。

import React from 'react'
import ReactECharts from 'echarts-for-react'
const option = {
    tooltip: {},
    series: [
    {
        type: 'tree',

        data: [
            {
                name: 'node01',
                value: 1,
                children: [
                    {
                        name: 'node011',
                        value: 1
                    },
                    {
                        name: 'node012',
                        value: 1
                    }
                ]
            },
            {
                name: 'node02',
                value: 1,
                children: [
                    {
                        name: 'node021',
                        value: 1
                    },
                    {
                        name: 'node022',
                        value: 1
                    }
                ]
            }
        ],

        top: '1%',
        left: '7%',
        bottom: '1%',
        right: '20%',

        symbolSize: 7,

        label: {
            position: 'left',
            verticalAlign: 'middle',
            align: 'right'
        },

        leaves: {
            label: {
                position: 'right',
                verticalAlign: 'middle',
                align: 'left'
            }
        },

        expandAndCollapse: true,
        animationDuration: 550,
        animationDurationUpdate: 750
    }
  ]
};
export default function Example() {
  return (
    <ReactECharts
      option={option}
    />
  )
}

现在,我们已经有了一个简单的树图。

添加搜索功能

要为树图添加搜索功能,我们需要先定义一下两个变量:

const initTreeData = [
    {
        name: 'node01',
        value: 1,
        children: [
            {
                name: 'node011',
                value: 1
            },
            {
                name: 'node012',
                value: 1
            }
        ]
    },
    {
        name: 'node02',
        value: 1,
        children: [
            {
                name: 'node021',
                value: 1
            },
            {
                name: 'node022',
                value: 1
            }
        ]
    }
];
const [treeData, setTreeData] = React.useState(initTreeData);

其中,initTreeData为初始化的树形数据,treeData则是用来存储当前操作过程中的树形数据。

接下来,我们需要添加一个搜索框,并将用户输入的搜索关键字保存在一个状态变量中:

const [keyword, setKeyword] = React.useState('');
return(
  <div>
    <input type="text" onChange={(e) => setKeyword(e.target.value)} value={keyword} placeholder="搜索树形结构"/>
  </div>
)

接着,我们需要定义一个函数来处理搜索操作:

const handleSearch = (data, key) => {
    let result = [];
    for (let i = 0; i < data.length; i++) {
        let node = data[i];
        if (node.name.includes(key) || node.value.toString().includes(key)) {
            result.push(node);
        }
        if (node.children) {
            let childrenResult = handleSearch(node.children, key);
            if (childrenResult.length > 0) {
                result.push({
                    ...node,
                    children: childrenResult
                });
            }
        }
    }
    return result
}

此函数中,handleSearch接受两个参数,分别是需要搜索的节点数据和用户输入的搜索关键字。在函数中,我们将遍历节点数据,并将所有包含搜索关键字的节点过滤出来。并且,如果搜索结果有子节点,则递归查找子节点。

接下来,我们在搜索框value值发生变化时,调用该函数并将结果存入treeData中:

const handleSearchInputChange = (e) => {
    setKeyword(e.target.value);
    let result = handleSearch(initTreeData, e.target.value);
    setTreeData(result)
};
return (
  <div>
    <input onChange={handleSearchInputChange} value={keyword}/>
  </div>    
);

至此,我们已经为树图添加了搜索功能。

添加展开功能

为树图添加展开功能,我们首先需要在每个节点上定义一个按钮,并为按钮添加点击事件。点击事件将根据节点当前的展开情况,执行相应的展开或收起操作。在每个节点上添加按钮的代码如下所示:

const onExpandButtonClick = (e, node) => {
    e.stopPropagation();  // 阻止事件冒泡
    if (node.children) {
        node._children = node.children;
        node.children = null;
    } else {
        node.children = node._children;
        node._children = null;
    }

    setTreeData((prev) => {
        return [...prev]
    });
};
return(
  <div>
      {
         treeNode.children ? (
            <button
                onClick={(e) => {
                    onExpandButtonClick(e, treeNode)
                }}
            >
              {expanded ? '-' : '+'}
            </button>
          ) : null
      }
      <span>{treeNode.name}</span>
  </div>
)

在每个按钮上,我们添加了一个onExpandButtonClick函数,并将子节点列表的引用存储在每个节点上。然后,如果子节点列表当前是打开的,则从列表中删除子节点并将其放入另一个引用“_children”中。相反地,如果子节点列表当前是关闭的,则从“_children”中获取子节点列表并将其放回children中。最后,我们将用新的树形数据更新setTreeData。

现在,我们已经成功为树图添加了展开功能。

示例1:添加动画效果

我们可以为树图的展开动态效果添加动画效果:

const option = {
    tooltip: {},
    series: [
    {
        type: 'tree',

        data: treeData,

        top: '1%',
        left: '7%',
        bottom: '1%',
        right: '20%',

        symbolSize: 7,

        label: {
            position: 'left',
            verticalAlign: 'middle',
            align: 'right'
        },

        leaves: {
            label: {
                position: 'right',
                verticalAlign: 'middle',
                align: 'left'
            }
        },

        expandAndCollapse: true,
        animationDuration: 550,
        animationDurationUpdate: 750,
        emphasis: {
            focus: 'descendant'
        }
    }
  ]
};

export default function Example1() {
    const initTreeData = [
        {
            name: '我的网站',
            children: [
              {
                name: '技术文档',
                children: [
                  {
                    name: '机器学习'
                  },
                  {
                    name: '深度学习'
                  },
                  {
                    name: '自然语言处理'
                  }
                ]
              },
              {
                name: '个人博客',
                children: [
                  {
                    name: '个人日记'
                  },
                  {
                    name: '旅游攻略'
                  },
                  {
                    name: '美食评测'
                  }
                ]
              }
            ]
          },
    ];
    const [treeData, setTreeData] = React.useState(initTreeData);

    const [keyword, setKeyword] = React.useState('');

    const handleSearch = (data, key) => {
        let result = [];
        for (let i = 0; i < data.length; i++) {
            let node = data[i];
            if (node.name.includes(key)) {
                result.push(node);
            }
            if (node.children) {
                let childrenResult = handleSearch(node.children, key);
                if (childrenResult.length > 0) {
                    result.push({
                        ...node,
                        children: childrenResult
                    });
                }
            }
        }
        return result
    };

    const handleSearchInputChange = (e) => {
        setKeyword(e.target.value);
        let result = handleSearch(initTreeData, e.target.value);
        setTreeData(result)
    };

    const onExpandButtonClick = (e, node) => {
        e.stopPropagation();
        if (node.children) {
            node._children = node.children;
            node.children = null;
        } else {
            node.children = node._children;
            node._children = null;
        }

        setTreeData((prev) => {
            return [...prev]
        });
    };

    return (
        <React.Fragment>
            <input onChange={handleSearchInputChange} value={keyword}/>
            <ReactECharts
                option={option}
            />
        </React.Fragment>
    )
}

示例2:树图数据异步加载展示

在树图数据较大时,为了实现更流畅的展示效果,我们可以通过异步加载树图数据的方式取得更好的体验。

const option = {
    tooltip: {},
    series: [
    {
        type: 'tree',

        data: treeData,

        top: '1%',
        left: '7%',
        bottom: '1%',
        right: '20%',

        symbolSize: 7,

        label: {
            position: 'left',
            verticalAlign: 'middle',
            align: 'right'
        },

        leaves: {
            label: {
                position: 'right',
                verticalAlign: 'middle',
                align: 'left'
            }
        },

        expandAndCollapse: true,
        animationDuration: 550,
        animationDurationUpdate: 750,
        emphasis: {
            focus: 'descendant'
        }
    }
  ]
};

export default function Example2() {
    const [treeData, setTreeData] = React.useState([]);

    React.useEffect(() => {
        // 模拟异步加载数据
        setTimeout(() => {
            const initData = [
                {
                    name: '我的网站',
                    children: [
                        {
                            name: '技术文档',
                            children: [
                                {
                                    name: '机器学习'
                                },
                                {
                                    name: '深度学习'
                                },
                                {
                                    name: '自然语言处理'
                                }
                            ]
                        },
                        {
                            name: '个人博客',
                            children: [
                                {
                                    name: '个人日记'
                                },
                                {
                                    name: '旅游攻略'
                                },
                                {
                                    name: '美食评测'
                                }
                            ]
                        }
                    ]
                }
            ];
            setTreeData(initData);
        }, 2000)
    }, []);

    const [keyword, setKeyword] = React.useState('');

    const handleSearch = (data, key) => {
        let result = [];
        for (let i = 0; i < data.length; i++) {
            let node = data[i];
            if (node.name.includes(key)) {
                result.push(node);
            }
            if (node.children) {
                let childrenResult = handleSearch(node.children, key);
                if (childrenResult.length > 0) {
                    result.push({
                        ...node,
                        children: childrenResult
                    });
                }
            }
        }
        return result
    };

    const handleSearchInputChange = (e) => {
        setKeyword(e.target.value);
        let result = handleSearch(treeData, e.target.value);
        setTreeData(result)
    };

    const onExpandButtonClick = (e, node) => {
        e.stopPropagation();
        if (node.children) {
            node._children = node.children;
            node.children = null;
        } else {
            node.children = node._children;
            node._children = null;
        }

        setTreeData((prev) => {
            return [...prev]
        });
    };

    return (
        <React.Fragment>
            <input onChange={handleSearchInputChange} value={keyword}/>
            <ReactECharts
                option={option}
            />
        </React.Fragment>
    )
}

在这个例子中,我们在useEffect钩子中异步加载了根节点数据,然后在组件初始渲染时显示空的树图。当数据加载完成之后,我们将使用setTreeData函数将其存储在树形数据中。

结论

本文在React-echarts基础上,通过示例演示了如何实现树图搜索和展开功能,并讨论树图动态效果添加和异步加载等高级技术。通过了解这些基于react-echarts库的技术,您可以创建出高度交互的树形结构,为用户提供更好的数据展示和使用体验。

本文标题为:react echarts tree树图搜索展开功能示例详解

基础教程推荐