一 数据源
以下所有操作,都使用本数据做测试。
const oraData = [
{
id: "1",
name: "动物",
children: [
{
id: "1-1",
name: "哺乳类",
children: [
{
id: "1-1-1",
name: "小猫",
children: []
},
{
id: "1-1-2",
name: "小狗",
children: []
},
{
id: "1-1-3",
name: "小猪",
children: []
}
]
},
{
id: "1-2",
name: "鸟类",
children: [
{
id: "1-2-1",
name: "燕子",
children: []
},
{
id: "1-2-2",
name: "喜鹊",
children: []
},
{
id: "1-2-3",
name: "鹦鹉",
children: []
}
]
}
]
},
{
id: "2",
name: "水果",
children: [
{
id: "2-1",
name: "苹果",
children: []
},
{
id: "2-2",
name: "香蕉",
children: []
}
]
},
{
id: "3",
name: "蔬菜",
children: []
}
];
二 遍历tree,生成序号(像文章的一级标题、二级标题)
先看结果:每个name后面的文字都生成了序号,二级标题前面也有一级标题序号。
实现源码
const createSerialNumber = (tree, parentNo = '') => {
const result = [];
tree.forEach((node, index) => {
// 如果当前没有父序号,则当前序号不加点。
let currentNo = `${index + 1}`;
// 如果有父序号,则父序号后面加点。
if (parentNo) {
currentNo = `${parentNo}.${index + 1}`;
}
// 创建新对象
const newNode = {
id: node.id,
name: `${currentNo} ${node.name}`,
};
// 将新节点添加到结果数组中
result.push(newNode);
// 如果节点有子节点,递归遍历子节点
if (node.children && node.children.length > 0) {
const childResult = createSerialNumber(node.children, currentNo);
result.push(...childResult); // 将子节点的结果合并到主结果中
}
});
return result;
};
console.log(createSerialNumber(oraData));
三 删除tree 节点,如果是父节点,同时需要删除子节点。
先看结果,删除了第一个节点(id=“1”)。
实现源码
const deleteTreeNodes = (data, deleteNode) => {
var newTree = data.filter((item) => item.id !== deleteNode)
newTree.forEach((item) => item.children && (item.children = deleteTreeNodes(item.children, deleteNode)))
return newTree
}
console.log(JSON.stringify(deleteTreeNodes(oraData, "1"), null, 2));
四 更新节点内容
先看结果,替换了节点id为“2-2”的内容。
实现源码:
const updateTreeNode = (tree, keyToUpdate, newValue) => {
// 遍历树的每个节点
for (let i = 0; i < tree.length; i++) {
const node = tree[i];
// 检查是否找到匹配的节点
if (node.id === keyToUpdate) {
// 更新节点的 designItem
node.name = newValue;
// 如果不需要继续搜索,可以直接返回
return tree;
}
// 如果节点有子节点,递归调用函数
if (node.children && node.children.length > 0) {
updateTreeNode(node.children, keyToUpdate, newValue);
}
}
// 如果没有找到匹配的节点,返回原树
return tree;
}
console.log(JSON.stringify(updateTreeNode(oraData, "2-2", "火龙果"), null, 2));
五 新增选择节点的同级节点
先看结果,在节点id为“3”后面新增了一个id为“4”的交通工具的节点。
实现代码:
const addSameLevelNode = (tree, newNode, targetKey) => {
// 递归遍历树结构
const traverse = (nodes) => {
for (let i = 0; i < nodes.length; i++) {
const node = nodes[i];
// 检查当前节点是否是要添加同级节点的目标节点
if (node.id === targetKey) {
// 在目标节点之后添加新节点
nodes.splice(i + 1, 0, newNode);
// 添加完成,停止遍历
return;
}
// 如果有子节点,则递归遍历子节点
if (node.children && node.children.length > 0) {
traverse(node.children);
}
}
}
// 开始遍历树的根节点
traverse(tree);
}
const getNewTreeData = () => {
const treeData = JSON.parse(JSON.stringify(oraData));
const newNode = {id: "4", name: "交通工具", children: []}
addSameLevelNode(treeData, newNode, "3");
return treeData;
};
console.log(JSON.stringify(getNewTreeData(), null, 2));
六 新增选择节点的子节点
先看结果,在【蔬菜】节点里面添加一个【番茄】的子节点。
实现源码:
const addChildNode = (tree, parentId, newNode) => {
// 遍历树的递归函数
function traverse(node) {
// 检查当前节点是否为目标节点
if (node.id === parentId) {
debugger
// 如果目标节点有children数组,则直接添加新节点
// 如果没有,则先创建一个children数组
if (!Array.isArray(node.children)) {
node.children = [];
}
node.children.push(newNode); // 添加新节点
return; // 找到后退出递归
}
// 如果没有找到目标节点,则继续遍历子节点(如果存在)
if (Array.isArray(node.children)) {
for (let i = 0; i < node.children.length; i++) {
traverse(node.children[i]);
}
}
}
// 注意:这里假设tree是一个数组,所以需要一个一个元素的遍历
tree.map((item, index) => {
traverse(item);
})
}
const getChildNodes = () => {
const treeData = JSON.parse(JSON.stringify(oraData));
const newNode = {id: "3-1", name: "番茄", children: []};
addChildNode(treeData, "3", newNode);
return treeData;
};
console.log(JSON.stringify(getChildNodes(), null, 2));