Antd的TreeSelect组件收起展开热区扩展

我认为TreeSelect组件和Tree组件的区别是把Tree组件放到了Select组件里面。

单纯的下拉框中的Tree形结构收起展开热区的扩展和Tree组件是一样的。

可以参考我的上一篇文章:

(11条消息) Antd的Tree组件收起展开热区扩展_憨逗君的博客-CSDN博客

不同的地方是:

1.树形节点被点击时下拉框显藏示隐的状态的控制。

热区改变之后,点击节点应该有两种效果:

(1)一种是只控制树形的收起与展开,下拉框不用隐藏,

(2)另一种是点击节点被选中,下拉框隐藏。

我这里是叶子节点被点击时是选中效果,其他节点被点击时就是单纯的控制树形的收起与展开

代码如下:

const [open, setOpen] = useState(false);
//通过open控制下拉框的显示与隐藏,默认值为false
open={open}
// 当select组件被聚焦时下拉框显示
onFocus={() => setOpen(true)}
// 当select组件失焦时下拉框隐藏

还有当组件被点击时,触发onSelect函数,判断是否为叶子节点,如果为叶子节点则将下拉框隐藏,即将open值置为false。

那么我们怎么判断一个当前节点是否为叶子节点呐

onSelect回调函数可以接收两个参数,第一个参数为被点击节点的key值,第二个参数为被点击节点的所有信息。具体有哪些信息是由传入的treeData决定的。

默认的treeData格式如下:

 所以onSelect回调函数第二个参数接收的信息也就只有title,value和children,具体如下图:

Antd的TreeSelect组件收起展开热区扩展_第1张图片

 所以我们可以对传入的treeData数据进行改造,改造函数如下:

// 生成一个含有三级的树状数据,每个节点的值含有自己的title,value和自己的子节点的值
const dig = (path = "0", level = 3) => {
  const list = [];

  for (let i = 0; i < 10; i += 1) {
    const key = `${path}-${i}`;
    const treeNode = {
      title: key,
      value: key,
    };

    if (level > 0) {
      treeNode.children = dig(key, level - 1);
    }

    list.push(treeNode);
  }

  return list;
};
const treeData = dig();


const pupinTreeData = [];

// (1)给每个节点加上isLeaf 为true则为子节点,为false则不是子节点
// (2) 把初始的树状数据打平放入pupinTreeData中
// (3) 给每个节点拼接上parentKey,值是改节点的所有父节点的key值拼接成的数组
const formatTreeData = (parentKey = []) => {
  treeData.forEach((element) => {
    const { value, children = [] } = element;
    element.parentKey = parentKey;
    let newParentKey = parentKey.concat(value);
    if (children.length > 0) {
      formatTreeData(children, newParentKey);
      element.isLeaf = false;
    } else {
      element.isLeaf = true;
    }
    pupinTreeData.push(Object.assign({}, element, { children: [] }));
  });
};

formatTreeData();

改造之后onSelect回调函数第二个参数就变为如下:

Antd的TreeSelect组件收起展开热区扩展_第2张图片

 然后我们在onSelect回调函数中就可以

// 如果该节点为叶子节点,则下拉框的值变为该节点的key值,同时下拉框隐藏
if (node.isLeaf) {
      setValue(value);
//让treeSelect组件失焦
    treeSelect.current.blur();
}

这样我们就完成了treeSelect组件,在树形节点被点击时,下拉框显示隐藏的交互。

2.在输入框搜索时被匹配到的节点值应该全部被展开

实现方法就是,根据输入的值去匹配树状数据中的节点,将匹配到的节点key值存到expandedKeys中即可。

这样还是有问题,如果一个子节点的key值被存到expandedKeys中,但是他的上层节点的key值没有存放带expandedKeys中的话,这样也是不能完成展开效果的。

所以就需要在格式化树状数据的时候

第一将树状数据铺平,是为了匹配到key值包含输入框中输入值的所有节点,

第二给每个节点的加上parentKey,使得能够在将自身key值放到expandedkey中时,将所有上层节点的key值也一并存进去,然后进行去重,这样才能完成展开效果。具体代码如下:

// 根据输入框的值将所有匹配到的节点的key值存到expandedKeys中
  function findAllNodeExpand(val) {
    let allExpand = [];
    pupinTreeData.forEach((item) => {
      if (item.value.indexOf(val) > -1) {
        allExpand.push(item.value);
        allExpand = allExpand.concat(item.parentKey);
      }
    });
    allExpand = [...new Set(allExpand)];
    setExpandedKeys(allExpand);
    return allExpand;
  }

综上,就完成了Antd的TreeSelect组件收起展开热区扩展

完整代码如下:

import { TreeSelect } from "antd";
import { useState, useRef } from "react";
import { debounce } from "../../utils/debounce";

const dig = (path = "0", level = 3) => {
  const list = [];

  for (let i = 0; i < 10; i += 1) {
    const key = `${path}-${i}`;
    const treeNode = {
      title: key,
      value: key,
    };

    if (level > 0) {
      treeNode.children = dig(key, level - 1);
    }

    list.push(treeNode);
  }

  return list;
};
const treeData = dig();
const pupinTreeData = [];

const formatTreeData = (treeData, parentKey = []) => {
  treeData.forEach((element) => {
    const { value, children = [] } = element;
    element.parentKey = parentKey;
    let newParentKey = parentKey.concat(value);
    if (children.length > 0) {
      formatTreeData(children, newParentKey);
      element.isLeaf = false;
    } else {
      element.isLeaf = true;
    }
    pupinTreeData.push(Object.assign({}, element, { children: [] }));
  });
};

formatTreeData(treeData);

console.log("treeData:", treeData);
console.log("pupinTreeData:", pupinTreeData);

const App = () => {
  const [value, setValue] = useState("");
  const [expandedKeys, setExpandedKeys] = useState([]);
  const [open, setOpen] = useState(false);
  const treeSelect = useRef();

  // 根据输入框的值将所有匹配到的节点的key值存到expandedKeys中
  function findAllNodeExpand(val) {
    let allExpand = [];
    pupinTreeData.forEach((item) => {
      if (item.value.indexOf(val) > -1) {
        allExpand.push(item.value);
        allExpand = allExpand.concat(item.parentKey);
      }
    });
    allExpand = [...new Set(allExpand)];
    setExpandedKeys(allExpand);
    return allExpand;
  }
  const debounceTask = debounce(findAllNodeExpand, 1000);
  const onSelect = (value, node, extra) => {
    console.log("value:", value, node);
    console.log("expandedKeys:", expandedKeys);
    if (node.isLeaf) {
      setValue(value);
      // setOpen(false);
      treeSelect.current.blur();
    }
    let copyExpandedKeys = [...expandedKeys];
    let expandedIndex = copyExpandedKeys.indexOf(value);
    if (expandedIndex > -1) {
      copyExpandedKeys.splice(expandedIndex, 1);
      setExpandedKeys(copyExpandedKeys);
    } else {
      copyExpandedKeys.push(value);
      setExpandedKeys(copyExpandedKeys);
    }
  };
  const onTreeExpand = (expandedKeys) => {
    setExpandedKeys(expandedKeys);
  };

  return (
     setOpen(true)}
      // 当select组件失焦时下拉框隐藏
      onBlur={() => setOpen(false)}
      showSearch
      ref={treeSelect}
      onSearch={(value) => {
        debounceTask(value);
      }}
    />
  );
};

export default App;

你可能感兴趣的:(大数据)