SOURCE

/**
 * 
1. 找到所有pid为0的节点,这些节点为根节点
2. 对于每个根节点,从数组中找到其所有的子节点
3. 对于每个子节点,再递归寻找其子节点
4. 重复步骤3,直到所有的节点构造完成
 * 
*/

function buildTree(data) {
    const result = []
    // 找到所有的根节点
    const roots = data.filter(d => d.pid == 0)
    console.log(roots);
    for (const root of roots) {
        // 构造根节点
        const node = Object.assign({}, { ...root, children: [] })
        result.push(node)
        // 递归寻找子节点
        findChildren(data, node)
    }
    return result
}

function findChildren(data, node) {
    // 过滤出当前节点的所有子节点
    const children = data.filter(d => d.pid === node.id)

    for (const child of children) {
        // 构造子节点
        const newNode = Object.assign({}, { ...child, children: [] })
        node.children.push(newNode)
        // 递归寻找子节点的子节点
        findChildren(data, newNode)
    }
}

const testData  = [
{ 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 },
];

console.log(buildTree(testData))
console 命令行工具 X clear

                    
>
console