如何将三个扁平数组合并构建嵌套树形数据结构
发布时间 - 2026-01-21 00:00:00 点击率:次本文介绍如何将通过多次 ajax 请求获取的三层扁平员工数据(根节点、一级子节点、二级子节点)按 `employeeid` 和父子关系动态组装为符合 treegrid 要求的嵌套树形结构,并提供可复用的递归挂载与扁平化工具函数。
在实际开发中(如使用 jqxTreeGrid、Ant Design Tree 或自定义树组件),常需将分层拉取的扁平数据构建成具有 children 属性的嵌套树结构。典型场景是:
- 第一次请求获取顶级员工(如 EmployeeID: 2);
- 第二次请求获取其直属下属(EmployeeID: [1,3,4,5,8]);
- 第三次请求获取下级下属(如 EmployeeID: [6,7,9],隶属于 EmployeeID: 5)。
关键挑战在于:如何根据业务逻辑(如 ReportsTo 字段或预定义层级映射)将子数组精准挂载到对应父节点的 children 属性中? 原始数据中并未显式包含 ReportsTo 字段,因此需依赖外部约定(例如:第二层数组中的所有项均属于第一层中 EmployeeID: 2 的子节点;第三层数组中的项均属于第二层中 EmployeeID: 5 的子节点)。以下提供两种主流实现方式:
✅ 方案一:基于层级顺序 + 显式挂载(推荐用于可控数据源)
假设你已知层级归属关系(如后端返回时附带 parentId 字段),最健壮的方式是统一建模后递归挂载:
// 模拟三组异步获取的数据
const level0 = [{ EmployeeID: 2, FirstName: "Andrew", ... }]; // 根节点
const level1 = [
{ EmployeeID: 8, FirstName: "Laura", ReportsTo: 2 },
{ EmployeeID: 1, FirstName: "Nancy", ReportsTo: 2 },
{ EmployeeID: 5, FirstName: "Steven", ReportsTo: 2 }
];
const level2 = [
{ EmployeeID: 6, FirstName: "Michael", ReportsTo: 5 },
{ EmployeeID: 7, FirstName: "Robert", ReportsTo: 5 },
{ EmployeeID: 9, FirstName: "Anne", ReportsTo: 5 }
];
// 合并为单层扁平数组(含 parentId)
const allNodes = [...level0, ...level1, ...level2];
// 构建树:O(n) 时间复杂度
function buildTree(nodes, idKey = 'EmployeeID', parentKey = 'ReportsTo') {
const nodeMap = new Map();
const roots = [];
// 第一
遍:建立 ID → 节点映射
nodes.forEach(node => {
nodeMap.set(node[idKey], { ...node, children: [] });
});
// 第二遍:挂载子节点
nodes.forEach(node => {
const parentId = node[parentKey];
const currentNode = nodeMap.get(node[idKey]);
if (parentId == null || !nodeMap.has(parentId)) {
roots.push(currentNode);
} else {
nodeMap.get(parentId).children.push(currentNode);
}
});
return roots;
}
const treeData = buildTree(allNodes);
console.log(treeData); // 输出符合要求的嵌套结构⚠️ 注意:若原始数据无 ReportsTo,需在请求时明确传递上下文(如 /api/employees?parent=2),或由前端维护映射表(如 parentMap = {2: [1,3,4,5,8], 5: [6,7,9]})。
✅ 方案二:按预设层级顺序手动组装(适用于固定结构)
若层级关系严格固定(如“第二组一定属于第一组首个元素”),可用简洁方式手动挂载:
// 假设 level0 仅含一个根节点
if (level0.length > 0) {
level0[0].children = level1;
// 手动查找 level1 中 EmployeeID === 5 的节点,并挂载 level2
const managerNode = level1.find(emp => emp.EmployeeID === 5);
if (managerNode) {
managerNode.children = level2;
managerNode.expanded = "true"; // 可选:控制默认展开
}
}
// level0 即为最终树根
const finalTree = level0;? 辅助函数:嵌套结构 ↔ 扁平数组互转
开发调试时,常需将嵌套树转为扁平列表(如用于搜索、导出):
// 嵌套 → 扁平(广度优先)
function nestedToLinear(data) {
const result = [];
const queue = [...data];
while (queue.length > 0) {
const node = queue.shift();
result.push({ ...node, children: undefined }); // 移除 children 避免循环引用
if (Array.isArray(node.children) && node.children.length > 0) {
queue.push(...node.children);
}
}
return result;
}
// 使用示例
console.log(nestedToLinear(treeData)); // 输出单层数组,含全部节点✅ 总结
- 核心原则:树结构构建 = “建立节点索引 + 按关系挂载”,而非硬编码 children: [...];
- 生产建议:后端应返回 id + parentId 字段,前端用 buildTree() 统一处理,避免耦合层级逻辑;
- 性能注意:Map 查找为 O(1),整套构建为 O(n),远优于嵌套循环;
- 扩展性:该模式天然支持 N 层嵌套,无需修改逻辑。
通过以上方法,你可灵活将任意数量的扁平数组组合为标准树形数据,无缝对接各类 TreeGrid 组件。
# 前端
# ajax
# node
# 编码
# 工具
# 后端
# 递归
# 循环
# 数据结构
# map
# 均属
# 组中
# 层数
# 层中
# 原始数据
# 两种
# 适用于
# 你可
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
Android实现代码画虚线边框背景效果
在线制作视频网站免费,都有哪些好的动漫网站?
如何在云服务器上快速搭建个人网站?
文字头像制作网站推荐软件,醒图能自动配文字吗?
详解MySQL数据库的安装与密码配置
如何自定义safari浏览器工具栏?个性化设置safari浏览器界面教程【技巧】
头像制作网站在线观看,除了站酷,还有哪些比较好的设计网站?
公司网站制作需要多少钱,找人做公司网站需要多少钱?
Win11怎么设置默认图片查看器_Windows11照片应用关联设置
浏览器如何快速切换搜索引擎_在地址栏使用不同搜索引擎【搜索】
Laravel怎么实现模型属性转换Casting_Laravel自动将JSON字段转为数组【技巧】
网站制作软件免费下载安装,有哪些免费下载的软件网站?
如何在阿里云通过域名搭建网站?
Laravel如何实现文件上传和存储?(本地与S3配置)
LinuxCD持续部署教程_自动发布与回滚机制
Linux系统命令中tree命令详解
Laravel怎么使用Collection集合方法_Laravel数组操作高级函数pluck与map【手册】
Swift中swift中的switch 语句
PythonWeb开发入门教程_Flask快速构建Web应用
PHP正则匹配日期和时间(时间戳转换)的实例代码
专业商城网站制作公司有哪些,pi商城官网是哪个?
Laravel如何使用Service Provider注册服务_Laravel服务提供者配置与加载
laravel怎么为应用开启和关闭维护模式_laravel应用维护模式开启与关闭方法
Laravel事件和监听器如何实现_Laravel Events & Listeners解耦应用的实战教程
Laravel怎么定时执行任务_Laravel任务调度器Schedule配置与Cron设置【教程】
大连 网站制作,大连天途有线官网?
网站建设要注意的标准 促进网站用户好感度!
Laravel队列由Redis驱动怎么配置_Laravel Redis队列使用教程
Laravel如何处理文件下载请求?(Response示例)
Laravel如何为API编写文档_Laravel API文档生成与维护方法
HTML5空格和margin有啥区别_空格与外边距的使用场景【说明】
php json中文编码为null的解决办法
百度浏览器ai对话怎么关 百度浏览器ai聊天窗口隐藏
Linux虚拟化技术教程_KVMQEMU虚拟机安装与调优
制作公司内部网站有哪些,内网如何建网站?
Java遍历集合的三种方式
香港服务器网站搭建教程-电商部署、配置优化与安全稳定指南
如何在服务器上配置二级域名建站?
Laravel如何生成PDF或Excel文件_Laravel文档导出工具与使用教程
如何快速搭建支持数据库操作的智能建站平台?
如何用西部建站助手快速创建专业网站?
高防服务器:AI智能防御DDoS攻击与数据安全保障
CSS3怎么给轮播图加过渡动画_transition加transform实现【技巧】
Windows家庭版如何开启组策略(gpedit.msc)?(安装方法)
香港服务器网站卡顿?如何解决网络延迟与负载问题?
Python文件操作最佳实践_稳定性说明【指导】
无锡营销型网站制作公司,无锡网选车牌流程?
Laravel如何创建自定义中间件?(Middleware代码示例)
详解Nginx + Tomcat 反向代理 负载均衡 集群 部署指南
Laravel如何监控和管理失败的队列任务_Laravel失败任务处理与监控


