Antd-React-TreeSelect前端搜索过滤

news/2024/11/15 16:35:08/文章来源:https://www.cnblogs.com/Evisu47/p/18368117

在开发过程中,但是antd中的搜索会把多余的也会带出来
就例如下图,我们本想去搜索1但是他会把其子节点都带出来,其实我们的本意是像搜2一样或者当中间隔层处理

但是我们该如何解决这样的问题呢如何做到下面两种情况
(1)搜索过滤掉不匹配的内容只留下匹配的内容
这是没有搜索之前

这是搜索之后,当我们去搜索5的时候我们就会直接把213过滤掉

(2)搜索中当子节点不是搜索内容但是孙节点和祖孙节点中存在要搜索的内容要把该子节点进行保留
这是没有搜索之前

这是搜索之后,我们要保留的结果

那么主要方法如下,antd-treeselect中的filterTreeNode属性,是否根据输入项进行筛选,默认用 treeNodeFilterProp 的值作为要筛选的 TreeNode 的属性值

方法如下使用

//toLowerCase()的方法主要是为了使用不区分大小写使用const filterTreeNode = (inputValue: string, treeNode: any) => {return treeNode.title.toLowerCase().indexOf(inputValue.toLowerCase()) > -1}

接下来就是搜索功能的具体实现方法

 // 此处操作主要用于前端处理搜索树时过滤掉搜索出的父节点下与搜索内容无关的其他子节点if (searchValue) {const fileData = [...oldfileTree]//主要用于记录tree节点使用的 oldfileTree就是树的节点功能// 用户树搜索的功能const searchResult = getSearchList([...fileData], searchValue)// 将树的列表更具搜索的内容的所有父级节点和搜索到内容id的合集let parentKeysif (name === 'apiManage') {parentKeys = contents.map((item: any) => {if (item.searchTitle.toLowerCase().indexOf(searchValue.toLowerCase()) > -1) {return getParentName(item.id, contents)}return null}).filter((item: any, i: any, self: any) => item && self.indexOf(item) === i)} else {parentKeys = contents.map((item: any) => {if (item.searchTitle.toLowerCase().indexOf(searchValue.toLowerCase()) > -1) {return getParentKey(item.id, contents)}return null}).filter((item: any, i: any, self: any) => item && self.indexOf(item) === i)}//所有需要的id扁平化处理const parentIdsList: any = parentKeys.flat(2).filter((item: any, i: any, self: any) => item && self.indexOf(item) === i)// 获取需要展开的id集合由于过程中可能存在层级丢失,需要使用traverseParent向上寻找所有父级的id序列const getExpendKeys = parentIdsList.map((item: string) => {return traverseParent(searchResult, item)}).flat(2).filter((item: any, i: any, self: any) => item && self.indexOf(item) === i)//设置翻开节点setTreeExpandedKeys(getExpendKeys)// 将搜索的集合转换成列表形式generateList(searchResult)// 把集合做转换成Map结构const listMap = dataList.reduce((map, item: any) => {map.set(item.id, item)return map}, new Map())//将所有展开的key与集合使用Map快速匹配对应值并将Map中存在的标记为truegetExpendKeys.map((item: string) => {if (listMap.has(item)) {listMap.set(item, { ...listMap.get(item), hasSearch: true })}})// 将搜索的结果和Map进行匹配,如果匹配成功则将该节点换成Map中该节点的内容const result = hasTree(searchResult, listMap)// 将融合好的hasSearch tree(是否是搜索的节点)进行去除所有false的节点const filterTree = removeFalseNodes(result)// 形成所有搜索的结果setFileTree([...filterTree] as treeDataNode[])} 

getSearchList 就是用于搜索高亮使用的,hasSearch搜索到的值为true,搜索不到的值则为false

  const getSearchList = (data: treeDataNode[], searchValue: string) => {const result: treeDataNode[] = data.map(item => {const strTitle = item.searchTitle as stringconst index = strTitle.toLowerCase().indexOf(searchValue.toLowerCase())const beforeStr = strTitle.substring(0, index)const afterStr = strTitle.slice(index + searchValue.length)const regExp = new RegExp(searchValue, 'gi')const matches = strTitle.match(regExp)let value = ''if (matches) {strTitle.replace(regExp, (match: any) => {value = matchreturn match})}const alias =index > -1 ? (<span>{beforeStr}<span className='site-tree-search-value'>{value}</span> //site-tree-search-value设置css样式,设置你需要的高亮的颜色什么颜色都可以{afterStr}</span>) : (<span>{strTitle}</span>)if (item.children) {return {...item,alias,value: item.id,hasSearch: index > -1 ? true : false, //将所有搜索结果是真的标记为true否则为falsechildren: getSearchList(item.children, searchValue)}}return {...item,value: item.id,hasSearch: index > -1 ? true : false, //将所有搜索结果是真的标记为true否则为falsealias}})return result}

getParentKey 的目的是找到给定 key 所对应的节点的直接父节点,并返回该父节点的 id 和 parentId。
getParentKey 函数没有明确处理未找到父节点的情况,可能会返回意外的结果或 undefined或者空数组。因而要使用.flat(2).filter((item: any, i: any, self: any) => item && self.indexOf(item) === i)来过滤

  const getParentKey = (key: React.Key, tree: any): React.Key => {let parentKey: anyfor (let i = 0; i < tree.length; i++) {const node = tree[i]if (node.children) {if (node.children.some((item: any) => item.id === key)) {parentKey = [node.id, node.parentId]} else if (getParentKey(key, node.children)) {parentKey = [getParentKey(key, node.children), node.parentId]}}}return parentKey}

traverseParent 的目的是递归地查找给定 parentId 的所有祖先节点,并将它们的 id 收集到一个数组中。
traverseParent 在未找到指定 parentId 的情况下会返回一个空数组。因而要使用.flat(2).filter((item: any, i: any, self: any) => item && self.indexOf(item) === i)来过滤

  const traverseParent = (treeData: treeDataNode[], parentId?: string) => {let result: string[] = []function traverse(nodes: treeDataNode[], parentId: string) {for (let i = 0; i < nodes.length; i++) {const node = nodes[i]if (node.id === parentId) {result = [...result, node.id]if (node.parentId) {traverse(treeData, node.parentId)}break} else if (node.children) {traverse(node.children, parentId)}}}if (parentId) traverse(treeData, parentId)return result}

generateList 的目的是用于扁平化树形数据结构并转换每个节点的格式

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

hasTree 就是将树重新构建,将树中存在的与Map结构中同样内容的值换成Map结构的信息

  const hasTree = (tree: treeDataNode[], map: any) => {return tree.map(node => {if (map.has(node.id)) {node = map.get(node.id)}// 如果节点有子节点,递归处理子节点if (node.children && node.children.length > 0) {node.children = hasTree(node.children, map)}return node})}

removeFalseNodes 是删除hasSearch 为false的置换成undefined在将其过滤掉最后剩下的就是搜索出的结果

const removeFalseNodes = (data: treeDataNode[]) => {return data.map(item => {// 递归处理children数组item.children = item.children && item.children.filter(child => child.hasSearch)if (item.children && item.children.length > 0) {removeFalseNodes(item.children)}// 如果当前对象的hasSearch为false且children为空数组,则返回undefined以从结果中排除return item.hasSearch || (item.children && item.children.length > 0) ? item : undefined}).filter(item => item !== undefined)}

总之,在一些时候搜索为了迎合需要不得不这么操作,那么该操作结合了antd官方的搜索操作,在此之前需要保持清醒的头脑

首先我们搜索出来高亮这个操作antd TreeSelect的是可以实现,但是搜索中我们发现实现不了搜索过滤,但是又要解决这个问题,想尝试使用数组方法将不是的部分删除,只能解决节点是的情况,当出现差层,何为差层就是当子节点不是搜索内容但是孙节点和祖孙节点中存在要搜索的内容要把该子节点进行保留的时候发现数据保留不住,不知道该如何解决,翻阅了ES6后发现使用Map做一层数据存储,并结合搜索情况将所有搜索的父节点向上遍历将其hasSearch设置为true,这样在重新构建树的时候可以将所有需要的节点变成true,再最后将所有节点是false的节点进行删除,只保留hasSearch为true的节点。总之该操作中使用了数组的方法,以及ES6的Map结构,当做出来的时候感觉雨过天晴,但是个人觉得这些还是太冗余了,之后会更进方法,如果大家有什么更好的方法请多指教 (´・Д・)」

最后就是如果这种问题可以放在后端在搜索的时候进行请求来减少前端遍历和重组的过程减少渲染次数会更好

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/784122.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

方法的三种调用形式

在《可以调用Null的实例方法吗?》一文中,我谈到.NET方法的三种调用形式,现在我们就来着重聊聊这个话题。具体来说,这里所谓的三种方法调用形式对应着三种IL指令:Call、CallVirt和Calli。在《可以调用Null的实例方法吗?》一文中,我谈到.NET方法的三种调用形式,现在我们就…

关于隐藏Selenium绕过检测

. 浏览器指纹识别:网站通常通过浏览器指纹识别来检测访问者的身份。浏览器指纹是浏览器在访问网站时提供的一组信息,包括浏览器类型、版本、插件、用户代理字符串、屏幕分辨率、语言设置、操作系统等。 当你使用 Selenium 或其他自动化工具时,某些指纹信息可能会暴露自动化工…

依赖倒置原则

一、前言 依赖倒置原则也称依赖倒转原则(Dependence Inversion Principle) 看官方定义 高层模块不应该依赖底层模块,二者都应该依赖其抽象 抽象不应该依赖细节,细节应该依赖抽象 依赖倒置的中心思想是面向接口编程 如果你了解点设计模式,应该理解上面的话,但是如果不了解…

常见温升测试方法

常见温升测试方法 温升测试是电器产品安规测试项目之一,是为了检测电器产品及部件的温度变化情况,判断是否符合要求。在设备运行过程中会释放一定的热量,如果内部温度过高会影响产品的性能和稳定性,导致绝缘性能下降,因此温升测试是确保产品稳定运行的重要步骤。那么如何进…

当代码遇上诈骗,开发者该何去何从?

大家好,我是晓凡。 不知道大家最近有没有刷到这样一则消息:知名开源工具 Aria 的开发者删库跑路。 是的,你没听错,这不是段子,这是真事儿! 一言不合就删库? 这事儿得从一条令人震惊的提交记录说起。开发者留下的话,简直比冬天的北风还要刺骨:“因为自己的开源项目被诈…

5 个有趣的 Python 开源项目「GitHub 热点速览」

本期,我从上周的开源热搜项目中精心挑选了 5 个有趣、好玩的 Python 开源项目。 首先是 PyScript,它可以让你直接在浏览器中运行 Python 代码,不仅支持在 HTML 中嵌入,还能安装第三方库。然后是用 Python 写的“魔法虫洞” magic-wormhole,这是一个无需服务器、通过一条命…

耗时9个月,1.34万行代码,这套分布式微服务架构项目,完结啦!

作者:小傅哥 博客:https://bugstack.cn沉淀、分享、成长,让自己和他人都能有所收获!😄大家好,我是技术UP主小傅哥。 耗时9个月,1.34万行代码,55节课程,全程视频手把手。这套微服务、分布式、DDD架构,涵盖了;抽奖、活动、积分、兑换,运用了分库分表、binlog同步数据…

JetBrains PhpStorm 2024.2 (macOS, Linux, Windows) - 高效智能的 PHP IDE

JetBrains PhpStorm 2024.2 (macOS, Linux, Windows) - 高效智能的 PHP IDEJetBrains PhpStorm 2024.2 (macOS, Linux, Windows) - 高效智能的 PHP IDE JetBrains 跨平台开发者工具 请访问原文链接:https://sysin.org/blog/jetbrains-phpstorm/,查看最新版。原创作品,转载请…

Viper:强大的Go配置解析库

1 介绍 Viper是适用于Go应用程序的完整配置解决方案。它被设计用于在应用程序中工作,并且可以处理所有类型的配置需求和格式。目前Star 26.6k, 它支持以下特性:设置默认值 从JSON、TOML、YAML、HCL、envfile和Java properties格式的配置文件读取配置信息 实时监控和重新读取配…

JetBrains GoLand 2024.2 (macOS, Linux, Windows) - 为 Go 开发者打造的完整 IDE

JetBrains GoLand 2024.2 (macOS, Linux, Windows) - 为 Go 开发者打造的完整 IDEJetBrains GoLand 2024.2 (macOS, Linux, Windows) - 为 Go 开发者打造的完整 IDE JetBrains 跨平台开发者工具 请访问原文链接:https://sysin.org/blog/jetbrains-goland/,查看最新版。原创作…

流媒体服务器如何让WebRTC支持H.265,同时又能支持Web Chrome硬解码、软解码:DataChannel+MSE+WASM解码H.265

为了这一整套的解决方案,调研+研发整整花费了差不多半年多的时间,需达成的目标:流媒体服务器端不需要将H.265转码成H.264,就能让Chrome解码播放H.265;注意:现在很多市面上的软硬件通过转码H.265成H.264的方式来支持WebRTC,个人理解,这既费硬件又是技术的倒退!Web JS解…

Avalonia 后台代码简单播放动画示例

本文将演示如何在 Avalonia 的后台代码里面创建 Animation 执行播放本文演示的内容是将界面里面的一个 TextBlock 控件,通过修改控件的 RenderTransform 的 TranslateTransform 执行平移 为了方便演示,先在 MainView.axaml 里面添加一个 TextBlock 控件,如下面代码。大家可以…