搜索效果如下图所示,左图为搜索前树的内容,右图为搜索后树的内容
树形结构数据如下所示,如果根节点只有一个,最外层数组下只存一个Node对象即可:
[
{
id: 1,
name: 'Node1',
children: [
{
id: 3,
name: 'Node1_1',
children: [
{
id: 8,
name: 'Node1_1_1'
}, {
id: 9,
name: 'Node1_1_2'
}, {
id: 10,
name: 'Node1_1_3'
}]
},
{
id: 4,
name: 'Node1_2'
},
{
id: 5,
name: 'Node1_3'
}]
},
{
id: 2,
name: 'Node2',
children: [
{
id: 6,
name: 'Node2_1'
}, {
id: 7,
name: 'Node2_2'
}]
}
]
以下针对上述数据结构的搜索代码实现:
function handleSearch(tree, value){
//不满足搜索条件的待删除元素索引数组
let removeArr = []
// eslint-disable-next-line no-eval
//replace时正则匹配,全局匹配
let regExp = eval('/' + value + '/g')
//满足条件的字符串匹配为以下内容,红色显示,可以根据自己需要调整以下字符串
let replaceStr = `<span class='red'>${value}</span>`
for(let i = 0; i< tree.length; i++){
let node = tree[i]
searchTree(node, i, value, removeArr, replaceStr, regExp)
}
//遍历删除不满足条件的节点
for(let j=removeArr.length-1; j>=0 ;j--){
tree.splice(removeArr[j], 1)
}
//方法执行完成后tree只留下符合搜索条件的节点
}
/*
*递归搜索
* @param {object} node 树的一个节点Node
* @param {nameumber} index 当前节点的数组索引
* @param {string} value 搜索内容
* @param {array} removeArr 待删除的元素的索引数组
* @param {string} replaceStr 搜索到匹配内容后替换项
* @param {object} regExp replace正则匹配表达式,作为参数传入,避免每次执行时重复创建对象
*/
function searchTree(node, index, value, removeArr, replaceStr, regExp){
let children = node.children
//针对非叶子节点,需要递归其children节点
if(children && children.length > 0){
let innderArr = []
for(let i=0;i<children.length;i++){
searchTree(children[i], i, value, innderArr, replaceStr, regExp)
}
//如果当前节点不满足搜索条件,则对其children不满足条件的节点执行删除操作
if(node.name.indexOf(value) === -1){
for(let j=innderArr.length-1; j>=0 ; j--){
children.splice(innderArr[j], 1)
}
/*
*children节点删除结束后,如果children length为0,
*并且当前节点也不满足搜索条件,则当前节点也加入删除数组
*/
if(node.children.length === 0){
removeArr.push(index)
}
}else{
//当前节点非叶子节点,将满足条件内容做标记显示
node.name = node.name.replace(regExp, replaceStr)
}
}else{
//叶子节点,直接进行匹配
if(node.name.indexOf(value) === -1){
removeArr.push(index)
}else{
//将满足条件内容做标记显示
node.name = node.name.replace(regExp, replaceStr)
}
}
}