js树形数组遍历练习,扁平化、格式化、获取节点父级

1.树形数组扁平化

数组扁平化的方式很多,这里主要是用递归处理,除此之外还有正则、扩展运算符等等

    const list = [
        {name:'1',id:'1',children:[
            {name:'11',id:'11',children:[{name:'111',id:'111'}]},
            {name:'12'},
        ]},
        {name:'2',id:'2',children:[
            {name:'21',id:'21',children:[{name:'221',id:'221'}]},
            {name:'22',id:'22'},
        ]},
    ]
    // 树形数组扁平化
     const test = (arr)=>{
        const list = []
        if(arr instanceof Array){
           for (let i = 0; i < arr.length; i++) {
                const item = arr[i];
                if(item.children && item.children.length>0){
                  list.push(...test(item.children))//将每一层的结果push到list
                }
                delete item.children//视情况而定是否删除children属性
                list.push(item)
            }
        }
        return list
    }
    console.log(test(list,'扁平化'));

js树形数组遍历练习,扁平化、格式化、获取节点父级_第1张图片

2.树形数组格式化(修改节点key值) 

使用for改变原数组的方式

    // 树形数组递归格式化数组:使用for(改变原数组)
    const format = (arr)=>{
        if(arr instanceof Array){
            for (let i = 0; i < arr.length; i++) {
                const ele = arr[i];
                ele.label = ele.name;
                ele.value = ele.id;
                delete ele.name;
                delete ele.id;
                if(ele.children && ele.children.length>0){
                    format(ele.children);
                }
            }
            return arr
        }
    }

使用能生成新数组的方式:

    // 树形数组递归格式化数组:使用forEach(不改变原数组)
    const format2 = (arr)=>{
        if(arr instanceof Array){
           return  arr.map(item => {
                item.label = item.name;
                item.value = item.id;
                delete item.name;
                delete item.id;
                if(item.children && item.children.length>0){
                    format2(item.children);
                }
                return item
            });
        }
    }

 3.获取树形数组中某个节点的所有父级节点

 这个方式需要熟悉函数在堆栈中的调用顺序才好理解否则理解起来有点绕

    const list = [
        {name:'1',id:'1',children:[
            {name:'11',id:'11',children:[{name:'111',id:'111'}]},
            {name:'12'},
        ]},
        {name:'2',id:'2',children:[
            {name:'21',id:'21',children:[{name:'221',id:'221'}]},
            {name:'22',id:'22'},
        ]},
    ]
const getParentId = (arr,id)=>{
        for (let i = 0; i < arr.length; i++) {
            const item = arr[i]
            if(item.id==id){
                return [item]
            }
            if(item.children && item.children.length>0){
                let node = getParentId(item.children,id);
                //当当前item的有返回数组时则表示已经找到目标(id)节点item二级,node三级
                // node表示目标节点,而当前item则是第二次执行getParentId函数的item,因为第三次调用的getParentId函数在堆栈中被(return)去除掉了
                if(node!==undefined){
                    return node.concat(item);//这里每return一次堆栈就会去除一次最顶层函数
                }
            }
        }
    }
    // js函数调用堆栈:js每执行一个函数就会往堆栈放一个函数,如果函数执行完或者return之后就会从堆栈剔除,堆栈遵循先进后出的顺序
    // 执行顺序:(每执行一次函数,往堆栈里面放一个函数)
    // 执行函数getParentId(),往堆栈里面放一个函数,
    // 第一遍代码执行到let node = getParentId(item.children,id)的时候,执行递归于是跳到函数getParentId的开头执行第二遍,再放一个函数在堆栈
    // 第二次执行到let node = getParentId(item.children,id)时候跟第一次一样继续执行递归函数getParentId,再放一个函数在堆栈
    // 第三次执行的时候item.id==id,于是return掉当前的函数,
    // 而当前是第三次执行的函数,return之后当前函数就从堆栈中去除了,堆栈只剩两个函数了(第一次执行的getParentId函数跟第二次执行getParentId函数)
    //  于是继续执行第二个getParentId,它不会从头开始而是从第二次递归后面那里(因为之前在这结束调转到函数开头的,所以继续从这里执行)开始执行,
    // 发现node!==undefined成立于是将第二个getParentId函数return掉,从堆栈中去除
    // 去除之后堆栈中只剩第一次执行的getParentId函数,此时不会从头开始执行,而是继续在第一次递归调用那里往后执行(因为之前在这结束调转到函数开头的,所以继续从这里执行),最终返回函数的结果
    
    

js树形数组遍历练习,扁平化、格式化、获取节点父级_第2张图片

 

你可能感兴趣的:(javascript,开发语言,ecmascript)