如何为嵌套对象数组添加droppable/draggable属性并保留原结构
保留嵌套层级为对象数组添加属性的解决方案
问题描述
我有如下JavaScript嵌套对象数组:
const arr = [ { "topicId": 1, "topicName": "Topic 1", "topicIcon": { "name": "Caret", "class": "lmnicon lmnicon-caret-right" }, "topicContent": "T1 topic content", "children": [ { "topicId": 4, "topicName": "Topic 4", "topicIcon": { "name": "Caret", "class": "lmnicon lmnicon-caret-right" }, "topicContent": "T4 topic content" }, { "topicId": 5, "topicName": "Topic 5", "topicIcon": { "name": "Caret", "class": "lmnicon lmnicon-caret-right" }, "children": [ { "topicId": 6, "topicName": "Topic 6", "topicIcon": { "name": "Caret", "class": "lmnicon lmnicon-caret-right" } }, { "topicId": 7, "topicName": "Topic 7", "topicIcon": { "name": "Caret", "class": "lmnicon lmnicon-caret-right" } }, { "topicId": 8, "topicName": "Topic 8", "topicIcon": { "name": "Caret", "class": "lmnicon lmnicon-caret-right" } }, ] } ] }, { "topicId": 2, "topicName": "Topic 2", "topicIcon": { "name": "Caret", "class": "lmnicon lmnicon-caret-right" }, "topicContent": "T2 topic content", "children": [ { "topicId": 9, "topicName": "Topic 9", "topicIcon": { "name": "Caret", "class": "lmnicon lmnicon-caret-right" } }, { "topicId": 10, "topicName": "Topic 10", "topicIcon": { "name": "Caret", "class": "lmnicon lmnicon-caret-right" } } ] } ]
我需要为数组中所有对象及其任意层级的嵌套children对象添加droppable: true和draggable: true两个属性。目前尝试的代码虽然能添加属性,但会把原数组的层级结构扁平化,我需要保留原arr的层级结构,请问该如何实现?
之前尝试的代码:
const mapHeirarchy = list => list.flatMap(({ topicId, topicName, topicIcon, children = [] }) => { const obj = { 'topicId': topicId, 'topicName': topicName, 'topicIcon': topicIcon, 'droppable': true, //add this 'draggable': true //add this } return [obj, ...mapHeirarchy(children)] }); console.log(mapHeirarchy(arr))
解决方案
要保留原有的嵌套层级结构,需递归处理每个对象时保留其children属性,并对children数组递归调用处理函数,避免使用flatMap扁平化结构。
实现代码
const addDragDropProps = (list) => { return list.map(item => { // 解构原对象属性,children默认设为空数组 const { children = [], ...rest } = item; // 返回新对象,添加目标属性并递归处理children return { ...rest, droppable: true, draggable: true, // 仅当存在子节点时,添加处理后的children属性 ...(children.length > 0 && { children: addDragDropProps(children) }) }; }); }; // 调用函数处理原数组 const result = addDragDropProps(arr); console.log(result);
代码说明
- 使用
map替代flatMap:map会生成与原数组长度一致的新数组,完全保留原层级结构。 - 递归处理子节点:对每个对象的
children数组递归调用处理函数,确保所有层级的子对象都添加目标属性。 - 保留原属性:通过扩展运算符
...rest保留原对象的所有未显式解构的属性(如topicContent),避免数据丢失。 - 条件添加
children:仅当原对象存在非空children数组时,才添加处理后的children属性,避免生成冗余的空数组。
兼容单个对象的扩展写法
如果需要同时支持单个对象和数组的处理,可以调整函数:
const addDragDropProps = (item) => { // 处理单个对象的情况 if (!Array.isArray(item)) { const { children = [], ...rest } = item; return { ...rest, droppable: true, draggable: true, ...(children.length > 0 && { children: addDragDropProps(children) }) }; } // 处理数组的情况 return item.map(addDragDropProps); }; const result = addDragDropProps(arr); console.log(result);
内容的提问来源于stack exchange,提问作者Mitul Panchal
相关产品推荐
相关产品推荐

