前言:本来准备把这个项目写完了再来一点点写总结的,但是昨天刷到视频看到好多这里没太搞明白的,所以先写一点这一集的总结吧!
一、需求:
遍历节点树,把三级菜单全部设置成默认选中模式。
如图:要让三级菜单为设置为选中
の树状图:
数据结构如下:
二、分析业务流程:
1、我们需要先拿到整个节点树,设置为row。
2、找到当前row下面的一级菜单。由数据可见,一级菜单为row.children
3、二级菜单为一级菜单的children。则为:row.children.children
3、三级菜单为二级菜单的children。则为:row.children.children.children
(请把这几个children嵌套几次是指什么记好噢)
4、因为一个row,有好多个一级菜单二级菜单,所以我们需要循环拿到每一个一级菜单,再拿到每一个一级菜单里面的二级菜单,再拿到二级菜单里面的三级菜单。
三、实现业务:
我们先采用最直观最简单理解的3层for循环吧。
1、第一次循环:我们先拿到每一个1级菜单。
2、第二次循环,我们拿到每个1级菜单下面的2级菜单。
3、第三次循环,我们拿到每个2级菜单下面的3级菜单。
4、最终把3级菜单的id,加到数组里面。
getNode(row){
for(let i=0;i<row.children.length;i++){
for(let j=0;j<row.children[i].children.length;j++){
for(let k=0;k<row.children[i].children[j].children.length;k++){
// console.log(row.children[i].children[j].children[k].authName)
this.defKeys.push(row.children[i].children[j].children[k].id)
}
}
}
}
除了3层for循环,视频里面讲的是递归,下面我们再来理解一下递归吧。
getTreeKeys(node,arr){
//console.log('我执行了====',node)
//如果当前节点没有children属性,就是3级节点(已知只有3级是没有children属性的)
//第一步:
if(!node.children){
return arr.push(node.id)
}
//第二步:
node.children.forEach(item => {
//console.log('=====item',item)
this.getTreeKeys(item,arr)
});
}
其实很多小伙伴,是不太理解下面forEach里面的再次调用当前函数吧?
没关系,我们一步一步来理解吧。
先理解这个函数:这里的node,指的就是row,只是形参可以随便命名而已。arr,就是我们需要把3级菜单id添加进的那个数组。
函数第一次执行
1、:进入第一步if循环,发现row身上有一级菜单,不满足终止条件,继续执行。
2、进入第二步,forEach。注意这里循环的就是node.children,就是一级菜单喔。大家知道,forEach是可以把自身也传进去的,所以,这里的item,在这个时候,指向的就是node.children,也就是一级菜单喔(这里请自行去补充ES 6的forEach吧。)
这个时候可以记住,item,就是循环的对象本身。
3、一级菜单进入forEach内部,发现内部再次调用了当前的这个函数,并且,把自己本身,当成实参传递进去了。
函数第二次执行:
现在就等于重新看这个函数,这个时候的node,指的是一级菜单噢!
1、进入第一步:(注意,现在是一级菜单来执行这个函数拉,)进入if循环,发现自己身上有二级菜单,不满足终止条件,继续执行。
2、进入第二步forEach。这个时候,node.children,就是一级菜单的孩子,二级菜单拉。
3、把二级菜单当成item传递出去进入第三次执行。
函数第三次执行
这个时候node是指二级菜单了喔
1、进入第一步,二级菜单下面还有3级菜单呢,不满足终止条件,继续执行。
2、进入第二步forEach。这个时候的node.children,就是二级菜单的孩子,三级菜单了!
3、把三级菜单当初item传递出去,进行第4次循环。
函数第四次执行
这个时候node是指三级菜单了喔
1、进入第一步,啊,3级菜单下面没有孩子了!可以终止运行了!
把三级菜单的id,加到arr里面。
结束拉!
至此,我们就拿到所有3级菜单的id拉。