扁平数组转树形结构

565 阅读2分钟

为什么要用数组转树

在我们渲染后台数据时并不是所有的数据都是平铺直叙的,最典型的就是在后台管理平台上,一定会有的员工和部门的上下级管理关系,这是时候我们就需要使用数组树形结构

数组转树形结构的两种方法:

1. 递归 (性能不好但实现简单)

/** 
 * 递归 
 * @param { Array } list 数组 
 * @param { String } parentId 父级 id 
 * @param { Object } param2 可配置参数 
*/

const generateTree = ( 
    list, 
    parentId = 0, 
    { idName = "id", parentIdName = "parentId", childName = "children" } = {} 
) => { 
    if (!Array.isArray(list)) { 
        throw new Error("type only Array"); 
        // new Error("type only Array"); 
        return list; 
    } 
    return list.reduce((pre, cur) => { 
        // 找到parentId 的子节点之后,递归找子节点的下一级节点 
        if (cur[parentIdName] === parentId) { 
            const children = generateTree(list, cur[idName]); 
            if (children.length) { 
                cur[childName] = children; 
            } 
            return [...pre, cur]; 
        } 
        return pre; 
    }, []); 
};

2. 非递归方式(性能好)

应用了对象保存的是引用的特点,每次将当前节点的 id 作为 key,保存对应节点的引用信息,遍历数组时,每次更新 objMap 的 children 信息,这样 objMap中保留了所有节点极其子节点,最重要的是,我们只需要遍历一遍数组

/** 
 * 非递归 (映射 + 引用) 
 * 前提:每一项都有parentId,根元素 
 * @param { Array } list 数组 
 * @param { String } rootId 根元素Id 
 * @param { Object } param2 可配置参数 
*/ 

const generateTree2 = ( 
    list, 
    rootId = 0, 
    { idName = "id", parentIdName = "parentId", childName = "childern" } = {} 
) => { 
    if (!Array.isArray(list)) { 
        new Error("type only Array"); 
        return list; 
    } 
    const objMap = {}; //暂存数组以 id 为 key的映射关系 
    const result = []; // 结果 
    
    for (const item of list) { 
        const id = item[idName]; 
        const parentId = item[parentIdName]; 
        // 该元素有可能已经放入map中,(找不到该项的parentId时 会先放入map 
        objMap[id] = !objMap[id] ? item : { ...item, ...objMap[id] }; 
        const treeItem = objMap[id]; // 找到映射关系那一项(注意这里是引用) 
        if (parentId === rootId) { 
            // 已经到根元素则将映射结果放进结果集 
            result.push(treeItem); 
        } else { 
            // 若父元素不存在,初始化父元素 
            if (!objMap[parentId]) { 
                objMap[parentId] = []; 
            } 
        
            // 若无该根元素则放入map中 
            if (!objMap[parentId][childName]) { 
                objMap[parentId][childName] = []; 
            } 
            objMap[parentId][childName].push(treeItem); 
        }
    } 
    return result; 
}; 

const res = generateTree2(array); 
console.log("res", res);

参考:# 1w条数据,平铺数组转树形结构