做网站的公司倒闭,微网站开发工具,关于电子商务网站建设的现状,huang色网站ant.design 组件库中的 Tree 组件实现可搜索的树#xff0c;在这里我会详细介绍每个方法#xff0c;以及容易踩坑的点。
效果图#xff1a; 首先是要导入的文件
// React 自带的属性
import React, { useMemo, useState } from react;
// antd 组件库中的#xff0c;输入…ant.design 组件库中的 Tree 组件实现可搜索的树在这里我会详细介绍每个方法以及容易踩坑的点。
效果图 首先是要导入的文件
// 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] useStateReact.Key[]([]);const [searchValue, setSearchValue] useState();const [autoExpandParent, setAutoExpandParent] useState(true);每次树状图变动会更新 expandedKeys 来做接下来的操作 onExpand 展开/收起节点时触发 const onExpand (newExpandedKeys: React.Key[]) {setExpandedKeys(newExpandedKeys);setAutoExpandParent(false);};处理函数onChange
下面这段代码是一个事件处理函数onChange它接收一个React.ChangeEventHTMLInputElement类型的事件对象作为参数。这个事件函数通常用于处理输入框的值变化事件。
在函数内部首先通过解构赋值取出事件对象的value属性即输入框的当前值。
然后通过dataList数组的map方法遍历每个元素并根据元素的title属性是否包含输入框的值来判断是否展开节点。如果包含则调用getParentKey函数获取该节点的父节点的key否则返回null。这个步骤用于更新展开的节点。
接下来使用filter方法对newExpandedKeys数组进行过滤去除其中的null值并且去掉重复的元素得到最终的展开节点数组newExpandedKeys。
调用setExpandedKeys函数将最终的展开节点数组更新到状态中。
接着通过setSearchValue函数将输入框的值更新到状态中。
最后调用setAutoExpandParent函数将autoExpandParent状态设置为true表示父节点也会被自动展开。
这段代码的作用是实现一个用于过滤和展开树节点的搜索功能。当输入框的值发生变化时根据输入的值进行过滤找到匹配的节点并展开它们的父节点同时更新输入框的值和展开节点的状态。
const onChange (e: React.ChangeEventHTMLInputElement) {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在字符串中的位置。
根据索引的结果通过substring和slice方法将字符串分割成前后两部分然后构建一个新的title元素。如果搜索值在标题中存在使用span元素将搜索值高亮显示如果不存在则直接使用原始的标题。
接着判断item是否有子节点item.children如果有则递归调用loop函数处理子节点并将返回的结果作为children属性的值。
最后在每个节点的处理中都会返回一个包含title和key属性的对象。
最外层的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 classNamesite-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 (divSearch style{{ marginBottom: 8 }} placeholderSearch onChange{onChange} /TreeonExpand{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] useStateReact.Key[]([]);const [searchValue, setSearchValue] useState();const [autoExpandParent, setAutoExpandParent] useState(true);const onExpand (newExpandedKeys: React.Key[]) {setExpandedKeys(newExpandedKeys);setAutoExpandParent(false);};const onChange (e: React.ChangeEventHTMLInputElement) {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 classNamesite-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 (divSearch style{{ marginBottom: 8 }} placeholderSearch onChange{onChange} /TreeonExpand{onExpand}expandedKeys{expandedKeys}autoExpandParent{autoExpandParent}treeData{treeData}//div);
};export default App;官网地址 树形控件 Tree - Ant Design