During development, but the search in antd will bring out the redundancy as well
For example, in the following figure, we would like to search for 1 but he will bring out its children nodes, in fact, our intention is to search for 2 or in the middle of the interval layer processing
But how do we solve such a problem? How to do the following two situations
(1) Search filters out mismatches leaving only matches
This is before the search
This is after the search, when we go to search for 5 we'll just filter out 213
(2) When a child node is not searched for but there is content to be searched for in the grandchild and grandparent nodes in the search, the child node is retained.
This is before the search
This is the result we want to keep after the search
Then the main method is as follows, antd-treeselect in the filterTreeNode property, whether to filter according to the input items, the default treeNodeFilterProp value as the value of the TreeNode property to be filtered
The method is used as follows
// The toLowerCase() method is mainly for case-insensitive use.
const filterTreeNode = (inputValue: string, treeNode: any) => {
return ().indexOf(()) > -1
}
The next step is the implementation of the search function
// This is mainly used on the front-end when processing the search tree to filter out other children of the searched parent node that are not relevant to the search.
if (searchValue) {
const fileData = [... .oldfileTree]// Mainly used to record the tree nodes used oldfileTree is the node function of the tree.
// The user tree search function
const searchResult = getSearchList([... .fileData], searchValue)
// Make the tree list a collection of all the parents of the searched content and the ids of the searched content.
let parentKeys
if (name === 'apiManage') {
parentKeys = contents
.map((item: any) => {
if (().indexOf(()) > -1) {
return getParentName(, contents)
}
return null
})
.filter((item: any, i: any, self: any) => item && (item) === i)
} else {
parentKeys = contents
.map((item: any) => {
if (().indexOf(()) > -1) {
return getParentKey(, contents)
}
return null
})
.filter((item: any, i: any, self: any) => item && (item) === i)
}
// All the id flattening that is needed
const parentIdsList: any = parentKeys
.flat(2)
.filter((item: any, i: any, self: any) => item && (item) === i)
// Get the set of ids that need to be expanded. Since there may be a loss of hierarchy in the process, you need to use traverseParent to look up all the parent id sequences
const getExpendKeys = parentIdsList
.map((item: string) => {
return traverseParent(searchResult, item)
})
.flat(2)
.filter((item: any, i: any, self: any) => item && (item) === i)
// Set the flipped node
setTreeExpandedKeys(getExpendKeys)
// Convert the searched collection into a list
generateList(searchResult)
// Convert the collection into a Map structure
const listMap = ((map, item: any) => {
(, item)
return map
}, new Map())
// Quickly match all the expanded keys to the collection using Map and mark as true those that exist in the Map
((item: string) => {
if ((item)) {
(item, { ... (item), hasSearch: true })
}
})
// Match the result of the search with the Map, and if the match is successful, replace the node with the contents of the node in the Map
const result = hasTree(searchResult, listMap)
// Remove all false nodes from the fused hasSearch tree (if it is a searched node)
const filterTree = removeFalseNodes(result)
// Form the results of all searches
setFileTree([... .filterTree] as treeDataNode[])
}
getSearchList is used for search highlighting, hasSearch searched for the value of true, the value of the search is not for the value of false
const getSearchList = (data: treeDataNode[], searchValue: string) => {
const result: treeDataNode[] = (item => {
const strTitle = as string
const index = ().indexOf(())
const beforeStr = (0, index)
const afterStr = (index + )
const regExp = new RegExp(searchValue, 'gi')
const matches = (regExp)
let value = ''
if (matches) {
(regExp, (match: any) => {
value = match
return match
})
}
const alias =
index > -1 ? (
<span>
{beforeStr}
<span className='site-tree-search-value'>{value}</span> //site-tree-search-valueset upcsstype,set up你需要的高亮的颜色什么颜色都可以
{afterStr}
</span>
) : (
<span>{strTitle}</span>
)
if () {
return {
...item,
alias,
value: ,
hasSearch: index > -1 ? true : false, //Flag all search results as truetrueor elsefalse
children: getSearchList(, searchValue)
}
}
return {
...item,
value: ,
hasSearch: index > -1 ? true : false, //Flag all search results as truetrueor elsefalse
alias
}
})
return result
}
The purpose of getParentKey is to find the direct parent of the node corresponding to the given key and return the id and parentId of that parent.
The getParentKey function does not explicitly handle the case where the parent is not found, and may return unexpected results or undefined or empty arrays. Therefore, it is important to use the.flat(2).filter((item: any, i: any, self: any) => item && (item) === i)
filter
const getParentKey = (key: , tree: any): => {
let parentKey: any
for (let i = 0; i < ; i++) {
const node = tree[i]
if () {
if (((item: any) => === key)) {
parentKey = [, ]
} else if (getParentKey(key, )) {
parentKey = [getParentKey(key, ), ]
}
}
}
return parentKey
}
The purpose of traverseParent is to recursively find all ancestor nodes for a given parentId and collect their ids into an array.
traverseParent returns an empty array if the specified parentId is not found. Therefore, you should use the.flat(2).filter((item: any, i: any, self: any) => item && (item) === i)
filter
const traverseParent = (treeData: treeDataNode[], parentId?: string) => {
let result: string[] = []
function traverse(nodes: treeDataNode[], parentId: string) {
for (let i = 0; i < ; i++) {
const node = nodes[i]
if ( === parentId) {
result = [...result, ]
if () {
traverse(treeData, )
}
break
} else if () {
traverse(, parentId)
}
}
}
if (parentId) traverse(treeData, parentId)
return result
}
The purpose of generateList is to flatten the tree data structure and transform the format of each node.
const dataList: { key: ; title: string; name: string }[] = []
const generateList = (data: treeDataNode[]) => {
for (let i = 0; i < ; i++) {
const node = data[i]
({ ...node, name: })
if () {
generateList()
}
}
}
hasTree is to reconstruct the tree by replacing the values present in the tree that are the same as those in the Map structure with information from the Map structure.
const hasTree = (tree: treeDataNode[], map: any) => {
return (node => {
if (()) {
node = ()
}
// If the node has children, recursively process the children
if ( && > 0) {
= hasTree(, map)
}
return node
})
}
removeFalseNodes is to remove hasSearch for false and replace it with undefined, then filter it out and finally what's left is the result of the search.
const removeFalseNodes = (data: treeDataNode[]) => {
return data
.map(item => {
// recursive processingchildrenarrays
= && (child => )
if ( && > 0) {
removeFalseNodes()
}
// If the current object'shasSearchbecause offalseboth (... and...)childrenbecause of空arrays,then it returnsundefinedto exclude from the results
return || ( && > 0) ? item : undefined
})
.filter(item => item !== undefined)
}
In short, at some point the search has to be done in order to cater to the needs of the operation, then the operation is combined with the official antd search operation, before you need to keep a clear head!
First of all, we searched for this operation antd TreeSelect can be achieved, but the search we found that the realization of the search filter, but to solve this problem, want to try to use the array method will not be part of the deletion, can only be solved when the node is the case, when there is a difference layer, what is the difference layer is when the child node is not the search content but the grandchildren nodes and grandchildren nodes in the existence of the content to be searched for. search content to be retained when the child node found that the data can not be retained, do not know how to solve the problem, looked through the ES6 found that the use of Map to do a layer of data storage, and combined with the search of all the searched for the parent node upward traversal of its hasSearch set to true, so that in the re-construction of the tree can be all the nodes need to be turned into true, and then finally the All the nodes that are false are deleted and only the nodes with true hasSearch are retained. In short, the operation uses an array of methods, as well as ES6 Map structure, when done out of the feeling of the rain, but I personally feel that these are still too redundant, after that will be more into the method, if there is a better way to please teach more (´・Д・)".
The last thing is that if this kind of problem can be put in the back-end at the time of the search to request to reduce the front-end traversal and reorganization process to reduce the number of times the rendering will be better!