ant.design 组件库中的 Tree 组件实现可搜索的树: React+and+ts

这篇具有很好参考价值的文章主要介绍了ant.design 组件库中的 Tree 组件实现可搜索的树: React+and+ts。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

ant.design 组件库中的 Tree 组件实现可搜索的树,在这里我会详细介绍每个方法,以及容易踩坑的点。

效果图:

ant.design 组件库中的 Tree 组件实现可搜索的树: React+and+ts,react.js,javascript,前端

首先是要导入的文件

// React 自带的属性
import React, { useMemo, useState } from 'react'; 
// antd 组件库中的,输入框和树形控件
import { Input, Tree } from 'antd'; 
// ts
import type { DataNode } from 'antd/es/tree';

下面是要渲染在 Tree 上的的数据,这是一个伪数据,如果你在开发时使用,直接修改给对应的变量名,赋值即可

const { Search } = Input;

const x = 3;
const y = 2;
const z = 1;
const defaultData: DataNode[] = [];

const generateData = (_level: number, _preKey?: React.Key, _tns?: DataNode[]) => {
  const preKey = _preKey || '0';
  const tns = _tns || defaultData;

  const children: React.Key[] = [];
  for (let i = 0; i < x; i++) {
    const key = `${preKey}-${i}`;
    tns.push({ title: key, key });
    if (i < y) {
      children.push(key);
    }
  }
  if (_level < 0) {
    return tns;
  }
  const level = _level - 1;
  children.forEach((key, index) => {
    tns[index].children = [];
    return generateData(level, key, tns[index].children);
  });
};
generateData(z);

这个方法是 Tree 组件提供的,用来筛选出要渲染的数据,筛选应该是优化一些性能的,因为在拿到接口数据时,每一项都可能会有很多的数据,而这一步是筛选出有用的值,过滤到其他,dataList 就是用来接收这个筛选后的数据的。

// 得到筛选后的值,根据当前要渲染的内容来筛选
const dataList: { key: React.Key; title: string }[] = [];

// 将筛选后的值,赋给 dataList
const generateList = (data: DataNode[]) => {
  for (let i = 0; i < data.length; i++) {
    const node = data[i];
    const { key } = node;
    dataList.push({ key, title: key as string });
    if (node.children) {
      generateList(node.children);
    }
  }
};
generateList(defaultData);

触发了搜索后

触发了搜索后,会使用这个方法来对比两个参数key 和 tree,得到符合条件的值

key:当前搜索的值

tree:所有渲染的数据

const getParentKey = (key: React.Key, tree: DataNode[]): React.Key => {
  let parentKey: React.Key;
  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!;
};

现在进入进入组件内,处理逻辑,以下内容都包裹在 App组件中

const App: React.FC = () => {}

export default App;

要使用到的可修改状态的值

expandedKeys :(受控)展开指定的树节点

searchValue : 在触发搜索时,存储当期输入的字段

autoExpandParent :是否自动展开父节点,所以它的默认值是布尔值

  const [expandedKeys, setExpandedKeys] = useState<React.Key[]>([]);
  const [searchValue, setSearchValue] = useState('');
  const [autoExpandParent, setAutoExpandParent] = useState(true);

每次树状图变动,会更新 expandedKeys ,来做接下来的操作

onExpand :展开/收起节点时触发

const onExpand = (newExpandedKeys: React.Key[]) => {
    setExpandedKeys(newExpandedKeys);
    setAutoExpandParent(false);
  };

处理函数`onChange

下面这段代码是一个事件处理函数onChange,它接收一个React.ChangeEvent<HTMLInputElement>类型的事件对象作为参数。这个事件函数通常用于处理输入框的值变化事件。

在函数内部,首先通过解构赋值取出事件对象的value属性,即输入框的当前值。

然后,通过dataList数组的map方法遍历每个元素,并根据元素的title属性是否包含输入框的值来判断是否展开节点。如果包含,则调用getParentKey函数获取该节点的父节点的key,否则返回null。这个步骤用于更新展开的节点。

接下来,使用filter方法对newExpandedKeys数组进行过滤,去除其中的null值,并且去掉重复的元素,得到最终的展开节点数组newExpandedKeys

调用setExpandedKeys函数将最终的展开节点数组更新到状态中。

接着,通过setSearchValue函数将输入框的值更新到状态中。

最后,调用setAutoExpandParent函数将autoExpandParent状态设置为true,表示父节点也会被自动展开。

这段代码的作用是实现一个用于过滤和展开树节点的搜索功能。当输入框的值发生变化时,根据输入的值进行过滤,找到匹配的节点,并展开它们的父节点,同时更新输入框的值和展开节点的状态。

const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const { value } = e.target;
    const newExpandedKeys = dataList
      .map((item) => {
        if (item.title.indexOf(value) > -1) {
          return getParentKey(item.key, defaultData);
        }
        return null;
      })
      .filter((item, i, self) => item && self.indexOf(item) === i);
    setExpandedKeys(newExpandedKeys as React.Key[]);
    setSearchValue(value);
    setAutoExpandParent(true);
  };

下面这段代码使用了useMemo钩子来创建一个名为treeData的变量。useMemo的作用是在依赖项(这里是searchValue)发生变化时执行内部的函数,并将函数的返回值作为treeData的值。

函数内部定义了一个名为loop的递归函数,用于遍历树形结构的数据data

loop函数中,首先将item.title转换为字符串类型,并使用indexOf方法查找searchValue在字符串中的位置。

根据索引的结果,通过substringslice方法将字符串分割成前后两部分,然后构建一个新的title元素。如果搜索值在标题中存在,使用<span>元素将搜索值高亮显示;如果不存在,则直接使用原始的标题。

接着,判断item是否有子节点(item.children),如果有,则递归调用loop函数处理子节点,并将返回的结果作为children属性的值。

最后,在每个节点的处理中,都会返回一个包含titlekey属性的对象。

最外层的useMemo的返回值就是使用loop函数处理defaultData得到的结果,它代表了树形结构数据经过搜索值过滤和处理后的新数据。

总而言之,这段代码的作用是根据搜索值searchValue对树形结构数据进行过滤,并对匹配的节点标题进行处理,添加搜索值的高亮显示。最后返回经过处理后的新的树形结构数据treeData

const treeData = useMemo(() => {
    const loop = (data: DataNode[]): DataNode[] =>
      data.map((item) => {
        const strTitle = item.title as string;
        const index = strTitle.indexOf(searchValue);
        const beforeStr = strTitle.substring(0, index);
        const afterStr = strTitle.slice(index + searchValue.length);
        const title =
          index > -1 ? (
            <span>
              {beforeStr}
              <span className="site-tree-search-value">{searchValue}</span>
              {afterStr}
            </span>
          ) : (
            <span>{strTitle}</span>
          );
        if (item.children) {
          return { title, key: item.key, children: loop(item.children) };
        }

        return {
          title,
          key: item.key,
        };
      });

    return loop(defaultData);
  }, [searchValue]);

组件的结构

最后就是组件的结构了,这段代码中使用了 Search 组件,通过 placeholder 属性设置了一个提示文本 Search ,并通过 onChange 属性指定了一个事件处理函数 onChange 来处理搜索框的值变化事件。这个 onChange 函数通常用于更新状态或执行其他逻辑,以响应搜索框中输入的值的变化。

总而言之,这段代码创建了一个包含搜索框和树形结构的组件,并将搜索框的值变化和树节点的展开或折叠事件与相应的事件处理函数关联起来。

  return (
    <div>
      <Search style={{ marginBottom: 8 }} placeholder="Search" onChange={onChange} />
      <Tree
        onExpand={onExpand}
        expandedKeys={expandedKeys}
        autoExpandParent={autoExpandParent}
        treeData={treeData}
      />
    </div>
  );
};

完整代码:


import React, { useMemo, useState } from 'react';
import { Input, Tree } from 'antd';
import type { DataNode } from 'antd/es/tree';

const { Search } = Input;

const x = 3;
const y = 2;
const z = 1;
const defaultData: DataNode[] = [];

const generateData = (_level: number, _preKey?: React.Key, _tns?: DataNode[]) => {
  const preKey = _preKey || '0';
  const tns = _tns || defaultData;

  const children: React.Key[] = [];
  for (let i = 0; i < x; i++) {
    const key = `${preKey}-${i}`;
    tns.push({ title: key, key });
    if (i < y) {
      children.push(key);
    }
  }
  if (_level < 0) {
    return tns;
  }
  const level = _level - 1;
  children.forEach((key, index) => {
    tns[index].children = [];
    return generateData(level, key, tns[index].children);
  });
};
generateData(z);

const dataList: { key: React.Key; title: string }[] = [];
const generateList = (data: DataNode[]) => {
  for (let i = 0; i < data.length; i++) {
    const node = data[i];
    const { key } = node;
    dataList.push({ key, title: key as string });
    if (node.children) {
      generateList(node.children);
    }
  }
};
generateList(defaultData);

const getParentKey = (key: React.Key, tree: DataNode[]): React.Key => {
  let parentKey: React.Key;
  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 App: React.FC = () => {
  const [expandedKeys, setExpandedKeys] = useState<React.Key[]>([]);
  const [searchValue, setSearchValue] = useState('');
  const [autoExpandParent, setAutoExpandParent] = useState(true);

  const onExpand = (newExpandedKeys: React.Key[]) => {
    setExpandedKeys(newExpandedKeys);
    setAutoExpandParent(false);
  };

  const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const { value } = e.target;
    const newExpandedKeys = dataList
      .map((item) => {
        if (item.title.indexOf(value) > -1) {
          return getParentKey(item.key, defaultData);
        }
        return null;
      })
      .filter((item, i, self) => item && self.indexOf(item) === i);
    setExpandedKeys(newExpandedKeys as React.Key[]);
    setSearchValue(value);
    setAutoExpandParent(true);
  };

  const treeData = useMemo(() => {
    const loop = (data: DataNode[]): DataNode[] =>
      data.map((item) => {
        const strTitle = item.title as string;
        const index = strTitle.indexOf(searchValue);
        const beforeStr = strTitle.substring(0, index);
        const afterStr = strTitle.slice(index + searchValue.length);
        const title =
          index > -1 ? (
            <span>
              {beforeStr}
              <span className="site-tree-search-value">{searchValue}</span>
              {afterStr}
            </span>
          ) : (
            <span>{strTitle}</span>
          );
        if (item.children) {
          return { title, key: item.key, children: loop(item.children) };
        }

        return {
          title,
          key: item.key,
        };
      });

    return loop(defaultData);
  }, [searchValue]);

  return (
    <div>
      <Search style={{ marginBottom: 8 }} placeholder="Search" onChange={onChange} />
      <Tree
        onExpand={onExpand}
        expandedKeys={expandedKeys}
        autoExpandParent={autoExpandParent}
        treeData={treeData}
      />
    </div>
  );
};

export default App;

官网地址: 树形控件 Tree - Ant Design文章来源地址https://www.toymoban.com/news/detail-629740.html

到了这里,关于ant.design 组件库中的 Tree 组件实现可搜索的树: React+and+ts的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 第九篇【传奇开心果系列】Ant Design Mobile of React 开发移动应用:使用内置组件实现响应式设计

    第一篇【传奇开心果系列】Ant Design Mobile of React 开发移动应用:从helloworld开始 第二篇【传奇开心果系列】Ant Design Mobile of React 开发移动应用:天气应用 第三篇【传奇开心果系列】Ant Design Mobile of React 开发移动应用:健身追踪 第四篇【传奇开心果系列】Ant Design Mobile of React 开发移

    2024年01月21日
    浏览(49)
  • vue3+ts实现element Plus Tree组件单选和取消单选的功能(取消已经选中的树节点),及vue3的proxy对象转换

     具体效果和代码如下: 点击了\\\"节点1\\\"并高亮显示 打印结果如下  vue3的打印对象是proxy,如需变成单纯的数组对象可以使用 JSON.parse(JSON.stringify(list))进行转换。  再次点击\\\"节点1\\\"则取消当前选中   如果对您有帮助点个赞,关注收藏一下吧 。

    2024年02月12日
    浏览(34)
  • 第十二篇【传奇开心果系列】Ant Design Mobile of React开发移动应用:内置组件实现酷炫CSS 动画

    第一篇【传奇开心果系列】Ant Design Mobile of React 开发移动应用:从helloworld开始 第二篇【传奇开心果系列】Ant Design Mobile of React 开发移动应用:天气应用 第三篇【传奇开心果系列】Ant Design Mobile of React 开发移动应用:健身追踪 第四篇【传奇开心果系列】Ant Design Mobile of React 开发移

    2024年01月20日
    浏览(48)
  • vue3+ant design vue+ts实战【ant-design-vue组件库引入】

    🔥🔥更多内容见Ant Design Vue官方文档 🔥点击复习vue3【watch检测/监听】相关内容 👏👏👏一个好项目的编写不仅需要完美的逻辑,以及相应的技术,同时也需要一个 设计规范的高质量UI组件库 。👏👏👏本期文章将会详细讲解 Ant Design of Vue 组件库的 安装、使用、引入 。

    2024年02月02日
    浏览(40)
  • React安装ant design组件库,并使用

    ant design是一个很棒的组件库,官方地址:快速上手 - Ant Design 但是如何在React里面用起来,好像并不是很顺畅,没有像Vue里面那么友好,因为我踩过这个坑,虽然安装很简单,但是想要出样式,还是有点步骤的。 npm命令: yarn命令: pnpm命令: 千万不要简单的只看官方的文档

    2024年02月14日
    浏览(37)
  • 按需引入ant-design-vue组件

    一、首先创建一个新的Vue项目 选择default含有babel和eslint。或者自定义Manually select features。 babel是一个转码器,主要用于ES2015+ 代码转换为 JavaScript 向后兼容版本的代码 eslint是一个代码检测工具。用来规范编码规范用。 自定义可选的插件有,Babel,TypeScript,Progressive Web App (P

    2024年02月13日
    浏览(44)
  • React——Ant Design组件库Message全局提示的使用

    官网推荐使用Hook调用的方法         这种方法只能在本页显示,如果显示后跳转页面就不会显示。因为{contextHolder}是写在本页面的。如果需要跳转页面可以用promise调用 传递的参数依次为,提示信息、显示时间、关闭后触发的回调

    2024年02月11日
    浏览(31)
  • Ant Design Vue的table组件高度自适应问题

    今天在编写公司项目的时候碰到ant design vue的table组件高度没办法自适应的问题,会出现如下页面情况。  最终尝试的解决方案只能通过监听浏览器窗口变化实现自适应 (1)给表格的srcoll定义一个动态接收参数,方便后面数据增加动态改变滚动高度。  (2)vue3项目中就直接

    2024年02月16日
    浏览(38)
  • 【Blazor之关于组件库Ant Design of Blazor组件样式的修改】

    例如:我们在使用Blazor框架时为了节省时间提升效率会使用到Ant Design of Blazor组件库。在使用过程中我们会根据需求去修改样式,但是由于组件库里面的样式基本上都是封装好的,要想达到自己所需的效果,这时候就需要我们去修改样式。本文就介绍一下我在使用Ant Design of

    2024年02月14日
    浏览(32)
  • 26、react UI 组件库 Ant-design 蚂蚁金服UI组件库

    material-ui (国外) 官网:https://mui.com/zh/material-ui/getting-started/installation/ 这是国外非常流行的 react UI 组件库,但是在国内并不是很常用。 Ant-design UI组件库 官网:https://ant.design/index-cn 这是国内比较流行 react UI 组件库,又蚂蚁金服团队开发。这一篇博客主要来讲解在 react 项目中

    2024年02月08日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包