React+Hooks+antd Tree组件简单总结

Tree组件一般使用于:文件夹、组织架构、生物分类、国家地区等等,世间万物的大多数结构都是树形结构。使用 树控件 可以完整展现其中的层级关系,并具有展开收起选择等交互功能。

1、简单的使用(基本tree)

import React, { useEffect, useState, useRef } from 'react';//首先引入hooks常用方法
import { connect } from 'react-redux';
import { Tree } from 'antd';  //引入组件
import { DownOutlined } from '@ant-design/icons'; //引入图标
const myDemo=(props)=>{
  const treeData=[{
            title: 'parent 1',
            key: '0-0',
            children: [
                {
                    title: 'parent 1-0',
                    key: '0-0-0',
                    children: [
                        {
                            title: 'leaf',
                            key: '0-0-0-0',
                        },
                        {
                            title: 'leaf',
                            key: '0-0-0-1',
                        },
                        {
                            title: 'leaf',
                            key: '0-0-0-2',
                        },
                    ],
                },
                {
                    title: 'parent 1-1',
                    key: '0-0-1',
                    children: [
                        {
                            title: 'leaf',
                            key: '0-0-1-0',
                        },
                    ],
                },
            ],
  const onSelect=(selectedKeys, info)=>{
        console.log('selected', selectedKeys, info);
  }
  
  
  return (
   <div className="myDemo">
    <Tree
        showLine={true}   //是否开启节点之间带连接线的树  开启之后可以用 switcherIcon 修改默认图标
        switcherIcon={<DownOutlined />}  //默认图标
        defaultExpandedKeys={['0-0-0']}  //默认展开指定的树节点 key 
        onSelect={onSelect}  //点击树节点触发的回调
        treeData={treeData}
     />  
           
   </div>
  )
}
//暴露此组件
export default myDemo

注意点:传入的treeData中的key值要唯一,一般实际开发中后端从数据库拿的都是id,因此存在从多个库拿数据id相同的问题,此时需要加上—_或则- 拼接id 是比较好的方法

2、hooks改写官网的搜索树(官网demo是使用class的方式写的…)

index.jsx文件

import React, { useEffect, useState, useRef } from 'react';//首先引入hooks常用方法
import { connect } from 'react-redux';
import { Tree,Input } from 'antd';  //引入组件
const { Search } = Input;
const myDemo=(props)=>{
    const [treeData,setTreeData]=useState([]) //tree数据   这里数据接口获取 结构同上  就不再写了  后面直接用
    const [searchData, setsearchData] = useState('')  //搜索
    const [tree, setTree] = useState([]);
    const [autoExpandParent, setAutoExpandParent] = useState(false)
    const [expandedKeys, setExpandedKeys] = useState([])
    
    const searchValue = () => {  //点击搜索
      let value = searchData
      setAutoExpandParent(true)
      const expandedKey = getKey(value, tree)
      setExpandedKeys(expandedKey)
      setTreeData(fliterData(tree))
  }
  const updataSearch = (e) => { //更新input值
     setsearchData(e.target.value)
     if (e.target.value == '') {
        setTreeData(tree)
     }

   }
  const handelSelect = (selectedKeys, e) => { //点击 选中树节点 触发 
        const { title, key } = e.node
        console.log(title,key);
        //后面的业务逻辑根据实际情况来
        ...
        
  }
  const getParentKey = (key, tree) => { //传入当前节点key,返回父节点key 
    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 fliterData = data => data.map((item, i) => { //过滤数据 将input的搜索值 高亮显示
    const index = item.title.indexOf(searchData);
    const beforeStr = item.title.substr(0, index);
    const afterStr = item.title.substr(index + searchData.length);
    const title =
      index > -1 ? (
        <span>
          {beforeStr}
          <span className="site-tree-search-value">{searchData}</span>
          {afterStr}
        </span>
      ) : (
        <span>{item.title}</span>
      );
    if (item.children) {
      return { title, key: item.key, children: fliterData(item.children) };
    }
    return {
      title,
      key: item.key,
    };
  })

  let keyArr2 = [] //存放匹配key 的数组
  //传入input value值 模糊搜索 匹配key值数组
  const getKey = (value, data) => {  
    data.map(item => {
      if (item.title.indexOf(value) > -1) {
        keyArr2.push(getParentKey(item.key, treeData))
      }
      if (item.children) {
        getKey(value, item.children)
      }
    })
    return keyArr2.filter((item, i, self) => item && self.indexOf(item) === i);
    //过滤数组中相同的key值

  }

  const onExpand = expandedKeys => {  //展开/收起节点时触发
    setExpandedKeys(expandedKeys)
    setAutoExpandParent(false)
  };
  
  //获取数据
   useEffect(() => {
        const createData = async () => {
        //这里的请求是自己封装的  按自己项目中的请求来
            const result = await ajax({ url: `/api/XXX`, data: { data_type: 1 } })
            setTreeData(result.node)
            setTree(result.node)
        }
        createData()

    }, [])
    return(
      <div className="myDemo">
       <Search
                placeholder="请输入内容"
                className="searchBox"
                value={searchData}
                onChange={updataSearch}
                onSearch={searchValue}
                size="middle"
                allowClear
              />
      <Tree
                showLine={{showLeafIcon: false}}
                showIcon
                className="datatree"
                autoExpandParent={autoExpandParent}  
                onSelect={handelSelect}
                onExpand={onExpand}
                expandedKeys={expandedKeys}
                treeData={treeData}
              />
      </div>
    )

}

//暴露此组件
export default myDemo

index.scss文件

.site-tree-search-value{
  color:red;
}
其他样式 自己根据ui图来 这里随便给个颜色 ...

效果图

image.png

(未完待续,持续更新中…)

  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值