js树形结构如何从最深层往上匹配

JavaScript016

js树形结构如何从最深层往上匹配,第1张

一、树结构

定义一颗树,JS中常见的树形数据结构如下,children属性对应的是子树

let tree = [

{

id: '1',

name: '节点1',

children: [

{

id: '1-1',

name: '节点1-1'

}

]

},

{

id: '2',

name: '节点2',

children: [

{

id: '2-1',

name: '节点2-1'

},

{

id: '2-2',

name: '节点2-2',

children: [

{

id: '2-2-1',

name: '节点2-2-1'

}

]

}

]

},

{

id: '3',

name: '节点3'

}

]

二、深度优先遍历(DFS)

1、递归实现

function treeIterator(tree, func) {

tree.forEach((node) =>{

func(node)

node.children &&treeIterator(node.children, func)

})

}

实现逻辑简述:定义treeIterator函数,传入tree(树)和func(回调函数)两个参数,遍历tree数组,执行回调函数,如果当前节点存在children,则递归调用。

函数调用验证:调用treeIterator函数,传入上文定义好的树结构数组,打印出每个节点的name值。

treeIterator(tree, (node) =>{

console.log(node.name)

})

控制台打印结果如下:

2、循环实现

function treeIterator(tree, func) {

let node, curTree = [...tree]

while ((node = curTree.shift())) {

func(node)

node.children &&curTree.unshift(...node.children)

}

}

实现逻辑简述:

(1)定义node作为当前节点,curTree为传入的树(不影响原数组tree);

(2)执行while循环,curTree数组第一个元素从其中删除,并返回第一个元素赋值给node;

(3)①执行回调函数;②如果当前节点存在子树,则追加到curTree数组的开头,继续执行循环,直到curTree没有元素为止。

函数调用验证:参考上述递归实现验证,方式和结果一致。

三、广度优先遍历(BFS)

function treeIterator(tree, func) {

let node, curTree = [...tree]

while ((node = curTree.shift())) {

func(node)

node.children &&curTree.push(...node.children)

}

}

实现逻辑简述:和上述深度优先遍历的循环实现差不多。区别在于如果当前节点存在子树,则追加到list数组的末尾。

其实很简单,就是在你

if (document.getElementById('node' + no).style.display == 'none') {

document.getElementById('node' + no).style.display = 'block'}// 如果此层是隐藏的

这段里面在加一句所有子层隐藏就可以了

if (document.getElementById('node' + no).style.display == 'none') {

(要加在这里哦~要是加在document.getElementById('node' + no).style.display = 'block'这句下面就永远不会有子项显示)

document.getElementById('node' + no).style.display = 'block'}

public object ListMenu(DataTable _list)

{

StringBuilder sb = new StringBuilder()

DataRow[] rows = _list.Select("PID=0")

sb.Append("[")

bool isFist = false

foreach (DataRow dr in rows)

{

if (isFist)

sb.Append(",")

isFist = true

string id = dr["ID"].ToString()

sb.Append("{")

sb.AppendFormat("\"id\":\"{0}\",", dr["ID"])

sb.AppendFormat("\"text\":\"{0}\",", dr["Name"])

sb.AppendFormat("\"pid\":\"{0}\",", dr["PID"])

string submenu = GetSubMenu(id, _list)

if (submenu == "")

{

sb.AppendFormat("\"leaf\":\"{0}\",", "true")

sb.Append("\"children\":[")

}

else

{

sb.AppendFormat("\"expanded\":\"{0}\",", "true")

sb.Append("\"children\":[")

sb.Append(submenu)

}

sb.Append("]")

sb.Append("}")

}

sb.Append("]")

_menu = sb.ToString()

return _menu

}

private string GetSubMenu(string pid, DataTable dt)

{

StringBuilder sb = new StringBuilder()

DataRow[] rows = dt.Select("PID=" + pid)

if (rows.Length >0)

{

bool isFist = false

foreach (DataRow dr in rows)

{

if (isFist)

sb.Append(",")

isFist = true

string id = dr["ID"].ToString()

sb.Append("{")

sb.AppendFormat("\"id\":\"{0}\",", dr["ID"])

sb.AppendFormat("\"text\":\"{0}\",", dr["Name"])

sb.AppendFormat("\"pid\":\"{0}\",", dr["PID"])

string submenu = GetSubMenu(id,dt)

if (submenu == "")

{

sb.AppendFormat("\"leaf\":\"{0}\",", "true")

sb.Append("\"children\":[")

}

else

{

sb.AppendFormat("\"expanded\":\"{0}\",", "true")

sb.Append("\"children\":[")

sb.Append(submenu)

}

sb.Append("]")

sb.Append("}")

}

}

return sb.ToString()

}

可根据实际情况修改相应的值:如children可能是nodes