树结构(有id和pid字段)数组,生成多层嵌套的json对象

本文介绍了一种将具有父子关系的节点数组转换成树状数据结构的方法。通过使用JavaScript实现的createTreeData函数,可以有效地处理节点之间的层级关系,并生成易于操作的树形结构。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/*
 * 传入的数组有id和父节点pid字段,通过它们的关联构造成一棵或多棵树结构
 * @param nodes 集合
 * @param treeRootId 根节点的id
 */
function createTreeData(nodes, treeRootId) {
    var groups = {};
    // 按父节点将节点分组
    for (var i in nodes) {
        if (!groups[nodes[i].pid]) {
            groups[nodes[i].pid] = [];
        }
        groups[nodes[i].pid].push(nodes[i]);
        if (treeRootPid && treeRootPid === nodes[i].id) { // 发现传入的根节点id作为节点id时,将根节点设置为该节点的父节点
            treeRootPid = nodes[i].pid;
        }
    }

    var rootNodes = groups[treeRootPid];
    groups[treeRootPid] = null; // [SAFEGUARD]防止自为父节点或互为父节点(有环图结构)导致的死循环
    function traverseTreeNodeGroup(treeNodeGroup) {
        for (var i in treeNodeGroup) {
            var node = treeNodeGroup[i];
            if (groups[node.id]) {
                node.children = groups[node.id];
                groups[node.id] = null; // [SAFEGUARD]防止自为父节点或互为父节点(有环图结构)导致的死循环
                traverseTreeNodeGroup(node.children);
            }
        }
    }
    traverseTreeNodeGroup(rootNodes);
    return rootNodes;
}

// 测试数组
var nodes = [
    {id: '01', pid: '0'},
    {id: '02', pid: '0'},
    {id: '011', pid: '01'},
    {id: '012', pid: '01'},
    {id: '021', pid: '02'},
    {id: '022', pid: '02'},
    {id: '0221', pid: '022'},
    {id: '0222', pid: '022'}
];
// 调用
createTreeData(nodes, '0');
/* 返回如下结构
[
    {
        "id": "01",
        "pid": "0",
        "children": [
            {
                "id": "011",
                "pid": "01"
            },
            {
                "id": "012",
                "pid": "01"
            }
        ]
    },
    {
        "id": "02",
        "pid": "0",
        "children": [
            {
                "id": "021",
                "pid": "02"
            },
            {
                "id": "022",
                "pid": "02",
                "children": [
                    {
                        "id": "0221",
                        "pid": "022"
                    },
                    {
                        "id": "0222",
                        "pid": "022"
                    }
                ]
            }
        ]
    }
]
*/
<template> <el-cascader :options="options" v-model="selectedArea" :props="cascaderProps" @change="handleAreaChange" placeholder="请选择省/市/区" ></el-cascader> </template> <script> export default { data() { return { options: [], // 级联选项数据 selectedArea: [], // 绑定选中的值,如 [省ID, 市ID, 区ID] cascaderProps: { value: 'id', // 选项值字段 label: 'name', // 选项标签字段 children: 'children', // 子选项字段 checkStrictly: true // 可单独选择任意一级 } } }, mounted() { this.loadProvinceData() // 初始化加载省级数据 }, methods: { // 加载省份数据 async loadProvinceData() { try { const res = await cityListV2(0) // 假设pid=0获取省份 this.options = res.data.map(province => ({ ...province, children: [] // 初始化空子节点 })) } catch (error) { console.error('加载省份失败', error) } }, // 级联选择变化时加载下级数据 async handleAreaChange(value) { const level = value.length if (level === 0) return // 获取当前选中节点 const currentNode = this.findNode(this.options, value) // 加载市级数据 if (level === 1 && !currentNode.children.length) { const res = await cityListV2(value[0]) currentNode.children = res.data.map(city => ({ ...city, children: [] // 初始化区级空节点 })) } // 加载区级数据 if (level === 2 && !currentNode.children.length) { const res = await cityListV2(value[1]) currentNode.children = res.data.map(district => ({ ...district, leaf: true // 标记叶子节点 })) } }, // 递归查找节点 findNode(nodes, path) { let current = nodes.find(node => node.id === path[0]) for (let i = 1; i < path.length; i++) { current = current.children.find(child => child.id === path[i]) } return current } } } </script> 每级选中
最新发布
06-16
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值