如何使用Lodash的cloneDeepWith更新嵌套对象的指定path值?
问题描述
我有如下嵌套对象:
let obj = { id: "XXX", children: [ { id: "YYY", children: [], path: ["XXX", "YYY"], type: "text" }, { id: "ZZZ", children: [], path: ["XXX", "ZZZ"], type: "button" } ], path: ["XXX"], type: "row" };
需要遍历所有含id的节点,将数组const newPath = ["A", "B", "C"];追加到每个节点的path属性前,最终目标对象如下:
let obj = { id: "XXX", children: [ { id: "YYY", children: [], path: ["A", "B", "C", "XXX", "YYY"], type: "text" }, { id: "ZZZ", children: [], path: ["A", "B", "C", "XXX", "ZZZ"], type: "button" } ], path: ["A", "B", "C", "XXX"], type: "row" };
我尝试使用Lodash的cloneDeepWith函数实现:
let updatedObj = cloneDeepWith(obj, (node) => { if (node.id) { node = { ...node, path: [...newPath, ...node.path] }; console.log("updated : ", node) } });
控制台能打印出正确更新后的节点,但updatedObj未正确返回更新后的对象,请问该如何解决?
解决方法
问题根源
cloneDeepWith的自定义迭代函数必须返回修改后的节点,否则Lodash会沿用默认的克隆结果。你当前代码只是修改了局部变量node,但没有将其返回,所以最终的克隆对象并未应用修改。
修正后的cloneDeepWith代码
只需在修改节点后将其返回即可:
const newPath = ["A", "B", "C"]; const updatedObj = cloneDeepWith(obj, (node) => { if (node.id) { // 返回修改后的节点,替换默认克隆结果 return { ...node, path: [...newPath, ...node.path] }; } // 无id的节点返回undefined,让Lodash按默认逻辑处理 });
无依赖替代方案:手动递归遍历
如果不想使用Lodash,也可以自己实现递归遍历修改:
const newPath = ["A", "B", "C"]; function updateNodePaths(node) { // 克隆节点避免修改原对象 const cloned = { ...node }; if (cloned.id) { cloned.path = [...newPath, ...cloned.path]; } // 递归处理子节点数组 if (cloned.children?.length) { cloned.children = cloned.children.map(updateNodePaths); } return cloned; } const updatedObj = updateNodePaths(obj);
内容的提问来源于stack exchange,提问作者Thidasa Pankaja
相关产品推荐
相关产品推荐

