树结构对象 Key 替换函数
功能概述
通过递归处理树结构数据,将每个节点的 Key 和字段名称替换为自定义的命名格式,同时保留原始节点数据以便后续调试或扩展。
函数实现
1. 节点处理函数
负责对单个节点的 Key 和字段进行转换。
/**
* @description 替换单个节点的 Key
* @param {Object} node - 单个节点对象
* @returns {Object} 替换后的节点对象
*/
const mapTreeKeys = (node) => {
// 判断是否有子节点
const hasChildren = Array.isArray(node.children) && node.children.length > 0;
return {
id: node.key, // 替换 key 为 id
text: node.text, // 保留 text 字段
data: { ...node }, // 将原始节点完整存入 data 中
children: hasChildren ? node.children.map(mapTreeKeys) : [], // 递归处理子节点
};
};
2. 树处理函数
对树结构数组进行整体处理,调用节点处理函数逐个替换 Key。
/**
* @description 替换树结构中所有节点 Key
* @param {Array} tree - 原始树的数组结构
* @returns {Array} 替换后的树结构
*/
const replaceTreeKeys = (tree) => {
return tree.map(mapTreeKeys);
};
测试代码
输入数据
const originalTree = [
{
key: 1,
text: '节点1',
children: [
{
key: 2,
text: '节点1-1',
children: [],
},
{
key: 3,
text: '节点1-2',
children: [
{ key: 4, text: '节点1-2-1', children: [] },
],
},
],
},
{
key: 5,
text: '节点2',
children: [],
},
];
调用函数
const newTree = replaceTreeKeys(originalTree);
console.log(newTree);
输出结果
[
{
id: 1,
text: "节点1",
data: { key: 1, text: "节点1", children: [...] },
children: [
{
id: 2,
text: "节点1-1",
data: { key: 2, text: "节点1-1", children: [] },
children: [],
},
{
id: 3,
text: "节点1-2",
data: { key: 3, text: "节点1-2", children: [...] },
children: [
{
id: 4,
text: "节点1-2-1",
data: { key: 4, text: "节点1-2-1", children: [] },
children: [],
},
],
},
],
},
{
id: 5,
text: "节点2",
data: { key: 5, text: "节点2", children: [] },
children: [],
},
];
完整代码
/**
* @description 替换树结构对象的 Key,并深度遍历处理子节点
* @param {Object} node 单个节点对象
* @returns {Object} 替换后的节点对象
*/
const mapTreeKeys = (node) => {
// 判断当前节点是否有子节点
const hasChildren = Array.isArray(node.children) && node.children.length > 0;
// 返回替换后的节点
return {
id: node.key, // 替换 key 为 id
text: node.text, // 保留 text 字段
data: { ...node }, // 将原始节点的所有属性存入 data 中
children: hasChildren ? node.children.map(mapTreeKeys) : [], // 递归处理子节点
};
};
/**
* @description 替换树结构中所有节点 Key 的函数
* @param {Array} tree 原始树的数组结构
* @returns {Array} 替换后的树结构
*/
const replaceTreeKeys = (tree) => {
return tree.map(mapTreeKeys);
};
// 测试数据
const originalTree = [
{
key: 1,
text: '节点1',
children: [
{
key: 2,
text: '节点1-1',
children: [],
},
{
key: 3,
text: '节点1-2',
children: [
{ key: 4, text: '节点1-2-1', children: [] },
],
},
],
},
{
key: 5,
text: '节点2',
children: [],
},
];
// 替换 Key
const newTree = replaceTreeKeys(originalTree);
console.log(newTree);
实现细节
核心方法
-
Array.prototype.map
: 用于遍历和转换树节点及其子节点,返回新的树状结构。 -
递归调用: 若节点包含子节点(
children
),递归调用处理子节点,直到最深层级。
优化点
-
解耦逻辑:
- 将单节点处理(
mapTreeKeys
)与整体树处理(replaceTreeKeys
)分离,便于单独测试和复用。
- 将单节点处理(
-
动态扩展性:
- 原始节点数据完整保存在
data
字段中,方便后续调试或扩展功能。
- 原始节点数据完整保存在
-
容错性:
- 使用
Array.isArray
检查子节点的合法性,避免children
为非数组或undefined
时抛出错误。
- 使用
适用场景
- 树状结构数据的字段重命名
- 比如后端返回的树结构字段命名不符合前端需求(如
key
改为id
),需要统一格式化。
- 比如后端返回的树结构字段命名不符合前端需求(如
- 保留原始数据以便追溯
- 例如在需要调试或动态扩展功能时,通过
data
字段可随时获取完整节点信息。
- 例如在需要调试或动态扩展功能时,通过
注意事项
-
确保数据结构一致性:
- 确保输入的树状结构每个节点都包含合法的
children
字段(即使为空数组)。
- 确保输入的树状结构每个节点都包含合法的
-
深度拷贝需求:
- 目前仅将原始节点浅拷贝到
data
中,若有深拷贝需求可使用工具库(如lodash
)。
- 目前仅将原始节点浅拷贝到
-
灵活扩展:
- 根据实际需求,可以在
mapTreeKeys
函数中增加额外的字段映射逻辑。
- 根据实际需求,可以在
总结
该方法逻辑清晰,代码模块化,适用于多种树结构数据的 Key 替换需求,兼顾灵活性和可维护性,能够方便地应用于实际开发项目。