JavaScript实现数据转树形结构的两种方法详解
本文详细介绍JavaScript中将平面数据转换为树形结构的两种常用方法:递归法与直接遍历法。递归法适用于多层嵌套数据,需注意React中key的唯一性及搜索配置;遍历法逻辑简单,仅支持单层嵌套。文章结合具体代码示例,解析如何通过id与pid关系构建层级,并提供完整实现思路供参考。
JavaScript将数据处理成树形结构
第一种实现方式采用递归策略
该方案能够处理多层嵌套的数据结构。
需要注意的是,在React环境中,若value与key不一致会触发报错,且key值必须保持唯一。如果数据集合需要支持搜索功能,还需通过treeNodeFilterProp属性指定用于搜索的字段。
若传入的数据已确保包含必要字段,可省略部分校验步骤。此外,递归方法可与第二种方式结合使用,使代码更加简洁。
function toTree(data) {
for (let i = 0; i < data.length; i++) {
data[i].value = data[i].id || '';
data[i].title = data[i].name || '';
data[i].key = data[i].id || '';
data[i].children = data[i].list || [];
if (data[i].children && data[i].children.length > 0) {
toTree(data[i].children);
}
}
return data;
}第二种实现方式为直接遍历
此方法仅能处理单层嵌套,但逻辑比递归更为简单。鉴于React允许仅设置value或key其中之一,该方法中无需额外增加key属性。
function toTree(data) {
return data.map((item) => {
return {
title: item.name,
value: item.id,
children: item.list.map((item1) => {
return {
title: item1.name,
value: item1.id,
};
}),
};
});
}根据id将平级数据转换成树形结构数据
从数据库查询得到的每条记录均包含id和pid字段,需将这些数据转换为树形结构。
id与pid的关系如下:pid为0的数据位于最外层;若某条数据的pid等于最外层数据的id,则该数据置于第二层。
由于层级数量不确定,理论上可存在无限层,需通过循环将数据转换为树形结构:

// 数据循环
levelLoop(arr) {
const returnArr = []; // 返回的数组
let levelArr = []; // 当前层级的数组
let lastLevelArr = []; // 上一层数组
let idLevleArr = []; // 当前层级id的数组
let lastIdLevleArr = []; // 上一层级id的数组
let indexLevelArr = []; // 当前层级索引的数组
return curLoop(arr);
function curLoop(curArr) {
curArr.forEach((curItem, curIndex) => {
if (curItem.pid === 0) {
// 最外层
returnArr.push(curItem);
levelArr.push(curItem);
idLevleArr.push(curItem.id);
indexLevelArr.unshift(curIndex); // 添加到最前面,遍历删除元素时从后面开始删除,不会影响index的位置
} else {
const lastIndex = lastIdLevleArr.indexOf(curItem.pid);
if (lastIndex > -1) {
// 属于上一层级的子级
// 如果上一层级没有child则添加该属性,此时添加是保证有子元素指向上一层级才添加child
if (!lastLevelArr[lastIndex].children) {
lastLevelArr[lastIndex].children = [];
}
levelArr.push(curItem);
lastLevelArr[lastIndex].children.push(curItem);
idLevleArr.push(curItem.id);
indexLevelArr.unshift(curIndex);
}
}
});
lastLevelArr = levelArr;
levelArr = [];
lastIdLevleArr = idLevleArr;
idLevleArr = [];
indexLevelArr.forEach(index => {
curArr.splice(index, 1); // 删除当前层级的元素,使总数量不断减少
});
indexLevelArr = [];
if (curArr.length) {
return curLoop(curArr);
} else {
return returnArr;
}
}
}
},

总结
以上内容为个人经验总结,旨在提供参考,感谢大家的支持。
JS语法错误会阻止加载吗?区分SyntaxError与资源加载失败
2026-11-05 16:08:46
JavaScript常见SyntaxError语法错误排查与修复方法
2026-11-05 13:58:44
JS中slice、substring和substr截取字符串的区别
2026-11-05 13:43:47
JS 转 TS 手动迁移最佳实践:从配置 tsconfig 到消除 any 类型
2026-11-05 11:53:32
为什么JS数组push后得到的是数字而不是数组?
2026-11-05 09:59:18
