js递归遍历dom树、数组扁平化

js递归遍历dom树、数组扁平化

1. 遍历dom树

//数据
var data = [{id: 1,name: "办公管理",pid: 0},
		{id: 2,name: "请假申请",pid: 1},
		{id: 3,name: "出差申请",pid: 1},
		{id: 4,name: "请假记录",pid: 2},
		{id: 5,name: "系统设置",pid: 0},
		{id: 6,name: "权限管理",pid: 5},
		{id: 7,name: "用户角色",pid: 6},
		{id: 8,name: "菜单设置",pid: 6},
	];
//第一种方法
function getTree1(data) {
		const root = data.filter(item => {
			return item.pid === 0
		})
		root.forEach(root => {
			root.children = data.filter(item => {
				return item.pid === root.id
			})
			if (root.children && root.children.length) {
				root.children.forEach(item => {
					const subChildren = data.filter(subItem => {
						return subItem.pid === item.id
					})
					item.children = subChildren
				})
			}
		})
		return root
	}
	console.log(getTree1(data))
//第二种
function getTree2(data, id) {
    // 判断传入的数据是否是数组
    if (Object.prototype.toString.call(data) !== '[object Array]') return
    const root = data.filter(item => item.pid === id)
    const list = []
        // 遍历跟节点
    root.forEach(item => {
        const obj = {...item,children: getTree2(data, item.id) } // 递归方法,自己调用自己
        list.push(obj)
    })
    return list
}
console.log(getTree2(data, 0))
//结果
[
    {
        "id":1,
        "name":"办公管理",
        "pid":0,
        "children":[
            {
                "id":2,
                "name":"请假申请",
                "pid":1,
                "children":[
                    {
                        "id":4,
                        "name":"请假记录",
                        "pid":2,
                        "children":[]
                    }
                ]
            },
            {
                "id":3,
                "name":"出差申请",
                "pid":1,
                "children":[]
            }
        ]
    },
    {
        "id":5,
        "name":"系统设置",
        "pid":0,
        "children":[
            {
                "id":6,
                "name":"权限管理",
                "pid":5,
                "children":[
                    {
                        "id":7,
                        "name":"用户角色",
                        "pid":6,
                        "children":[]
                    },
                    {
                        "id":8,
                        "name":"菜单设置",
                        "pid":6,
                        "children":[]
                    }
                ]
            }
        ]
    }
]
  1. 扁平化数组

[1, [2, 3, [4, 5]]] ------> [1, 2, 3, 4, 5]

递归

//递归的遍历每一项,若为数组则继续遍历,否则concat
function flatten(arr) {
    var res = [];
    arr.map(item => {
        if(Array.isArray(item)) {
            res = res.concat(flatten(item));
        } else {
            res.push(item);
        }
    });
    return res;
}

reduce

//遍历数组每一项,若值为数组则递归遍历,否则concat。
function flatten(arr) {  
    return arr.reduce((result, item)=> {
        return result.concat(Array.isArray(item) ? flatten(item) : item);
    }, []);
}
//reduce是数组的一种方法,它接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。
//reduce包含两个参数:回调函数,传给total的初始值

// 求数组的各项值相加的和: 
arr.reduce((total, item)=> {  // total为之前的计算结果,item为数组的各项值
    return total + item;
}, 0);

toString & split

//调用数组的toString方法,将数组变为字符串然后再用split分割还原为数组
function flatten(arr) {
    return arr.toString().split(',').map(function(item) {
        return Number(item);
    })
} 
//因为split分割后形成的数组的每一项值为字符串,所以需要用一个map方法遍历数组将其每一项转换为数值型

join & split

function flatten(arr) {
    return arr.join(',').split(',').map(function(item) {
        return parseInt(item);
    })
}

扩展运算符

//es6的扩展运算符能将二维数组变为一维
[].concat(…[1, 2, 3, [4, 5]]); [1, 2, 3,4, 5]

//根据这个结果我们可以做一个遍历,若arr中含有数组则使用一次扩展运算符,直至没有为止。

function flatten(arr) {
    while(arr.some(item=>Array.isArray(item))) {
        arr = [].concat(...arr);
    }
    return arr;
}

小结
写了五种但核心也只有一个:
遍历数组arr,若arr[i]为数组则递归遍历,直至arr[i]不为数组然后与之前的结果concat。


版权声明:本文为LRuiXin原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。