Javascript 如何从对象中递归删除子对象?
我正在研究解决方案 我已经创建了基本的树型表,每当用户单击expand data时,与单击的行相关的数据就会根据行数据显示在它下面 我已经实现了扩展/折叠到N个嵌套级别的基本功能 但我只遇到一个问题,所以基本上所有行都有基于数组的条件展开按钮,数组有多个值 假设它是一个拆分数组,有3个条目:县、市、州 默认加载的数据将从api中获取,现在我必须检查数组中是否有可用的拆分!如果是,则显示展开按钮 考虑一下这个场景Javascript 如何从对象中递归删除子对象?,javascript,arrays,reactjs,react-native,Javascript,Arrays,Reactjs,React Native,我正在研究解决方案 我已经创建了基本的树型表,每当用户单击expand data时,与单击的行相关的数据就会根据行数据显示在它下面 我已经实现了扩展/折叠到N个嵌套级别的基本功能 但我只遇到一个问题,所以基本上所有行都有基于数组的条件展开按钮,数组有多个值 假设它是一个拆分数组,有3个条目:县、市、州 默认加载的数据将从api中获取,现在我必须检查数组中是否有可用的拆分!如果是,则显示展开按钮 考虑一下这个场景 const split = ["country","c
const split = ["country","city","state"]
这是Ui的外观
+ Data_1
+ Data_2
点击按钮+新的数据表行将根据下一次分割呈现,在我们的情况下,它是国家,因此视觉表现将如下
- Data_1
Country_1
Country_2
+ Data_2
- Data_1
- Country_1
City_1
City_2
+ Country_2
+ Data_2
这里国家并没有展开按钮,因为用户还并没有添加下一个分割,让我们添加城市,并假设用户点击了国家1,所以数据如下
- Data_1
Country_1
Country_2
+ Data_2
- Data_1
- Country_1
City_1
City_2
+ Country_2
+ Data_2
我的解决方案运行良好,直到这个级别,现在让我们假设用户已经从拆分中删除了国家/地区,国家/地区和城市的所有节点都应该删除,并且数据_1的-图标应该更改为+
这是我的密码
import React, {useState, useEffect, useRef, Fragment} from "react";
import _ from "lodash";
import axios from "axios";
class TableRowData extends React.Component {
state = {
showIcon: false,
selection: [],
data: [],
splitOption: ["campid"]
};
constructor(props) {
super(props);
}
componentDidMount() {
const checkIfSplitExistOnMount = (currentSplit) => {
const i = _.findIndex(this.state.splitOption, function(el) {
return el === currentSplit;
});
if (this.state.splitOption[i + 1]) {
return this.state.splitOption[i + 1];
} else {
return null;
}
}
const getReportData = () => {
axios.get("https://jsonplaceholder.typicode.com/users?_start=0&_limit=1").then((res) => {
const rowData = res.data.map((row) => {
row.name = this.state.splitOption[0];
row.isExpanded = false;
row.currentSplit = this.state.splitOption[0];
row.nextSplit = checkIfSplitExistOnMount(this.state.splitOption[0])
row.parentId = 0;
row.isVisble = true;
//console.log(row)
return row;
});
this.setState({
data: rowData
}, () => { //console.log(this.state.data)
});
});
}
getReportData()
}
render() {
// update state function
const updateState = () => {
this.setState({
data: [...this.state.data],
splitOption: [...this.state.splitOption],
selection: [...this.state.selection],
}, () => {})
}
// recusively update parent and child
const recursion = (obj) => {
let row = obj;
row.isExpanded = row.isExpanded;
row.currentSplit = row.currentSplit;
row.nextSplit = checkIfSplitExist(row.currentSplit)
if (row.children && row.children.length > 0) { // check if has children
row.children.forEach(v => { // if has children do the same recursion for every children
recursion(v);
});
}
return row; // return final new object
}
const recursionDel = (obj,split) => {
var row = obj;
row.currentSplit = row.currentSplit;
row.nextSplit = checkIfSplitExist(row.currentSplit)
if (row.children && row.children.length > 0) { // check if has children
row.children.forEach(v => { // if has children do the same recursion for every children
recursionDel(v);
});
}
return row; // return final new object
}
// function to check if next split is there or not if there than return nextsplit
const checkIfSplitExist = (currentSplit) => {
const i = _.findIndex(this.state.splitOption, function(el) {
return el === currentSplit;
});
if(i !== -1) {
if (this.state.splitOption[i + 1]) {
return this.state.splitOption[i + 1];
} else {
return null;
}
}
}
// recursive update whenever split added
const recursiveUpdate = (data) => {
const prevData = [...data];
return prevData.map((row) => {
const updatedData = recursion(row);
return row;
});
}
// function to delete child and parent node recursively
const recursiveDelete = (data,split) => {
const prevData = [...data];
return prevData.map((row) => {
const data = recursionDel(row,split);
return row;
});
}
const addNewSplit = (split) => {
const i = _.findIndex(this.state.splitOption, function(el) {
return el === split;
});
if(i === -1) {
this.setState(
{
splitOption:[...this.state.splitOption,split]
},
()=>{
var rowData = recursiveUpdate(this.state.data)
this.setState({data:rowData})
}
);
} else {
const prevData = [...this.state.splitOption];
var index = prevData.indexOf(split);
prevData.splice(index,1)
if(index!==-1) {
this.setState(
{
splitOption:prevData
},
()=> {
var rowData = recursiveDelete(this.state.data,split)
this.setState({data:rowData})
}
)
}
}
}
// add lazyload expand data
const ExpandableTableRow = ({rows}) => {
const expandRow = (row) => {
row.children = [
{
id: "_" + Math.random().toString(36).substr(2, 5),
name: row.id + "_" + row.nextSplit,
isExpanded: false,
parentId: row.id,
currentSplit: row.nextSplit,
nextSplit: checkIfSplitExist(row.nextSplit),
isVisble:true
}, {
id: "_" + Math.random().toString(36).substr(2, 5),
name: row.id + "_" + row.nextSplit,
isExpanded: false,
parentId: row.id,
currentSplit: row.nextSplit,
nextSplit: checkIfSplitExist(row.nextSplit),
isVisble:true
}
];
row.isExpanded = true;
updateState();
};
// call whenever - click
const collapseRow = (row) => {
delete row.children;
row.isExpanded = false;
updateState();
};
// toggle
const ExpandCollapsToggle = ({row, expandRow, collapseRow}) => {
// display +/- only if nextsplit is not undefined or null
if (row.nextSplit) {
if (row.isExpanded === true) {
return (<button type="button" onClick={() => collapseRow(row)}>
-
</button>);
} else {
return (<button type="button" onClick={() => expandRow(row)}>
+
</button>);
}
} else {
return null;
}
};
if (rows) {
return rows.map((row) => {
// if(!_.isEmpty(row)) {
return (<Fragment key={row.id}>
<tr key={row.id}>
<td>
<ExpandCollapsToggle row={row} expandRow={expandRow} collapseRow={collapseRow}/>{" "}
{row.split}
- {row.id}
</td>
<td>{row.name}</td>
</tr>
<ExpandableTableRow rows={row.children}/>
</Fragment>);
// }
});
} else {
return null;
}
};
const splitData = this.state.splitOption.map((ob) => {
return (<Fragment key={ob}><span>{ob}</span> > </Fragment>)
})
if (this.state.data) {
return (
<Fragment>
{splitData} <br/>
<button onClick = {()=>addNewSplit("name")}>camp name</button>
<button onClick = {()=>addNewSplit("os")}>os</button>
<button onClick = {()=>addNewSplit("country")}>country</button>
<ExpandableTableRow rows={this.state.data} />
</Fragment>
);
} else {
return null;
}
}
}
export default TableRowData;
import React,{useState,useffect,useRef,Fragment}来自“React”;
从“洛达斯”进口;
从“axios”导入axios;
类TableRowData扩展了React.Component{
状态={
showIcon:false,
选择:[],
数据:[],
拆分选项:[“campid”]
};
建造师(道具){
超级(道具);
}
componentDidMount(){
常量checkIfSplitExistOnMount=(currentSplit)=>{
const i=u.findIndex(this.state.splitOption,函数(el){
返回el==currentSplit;
});
if(this.state.splitOption[i+1]){
返回此.state.splitOption[i+1];
}否则{
返回null;
}
}
const getReportData=()=>{
axios.get(“https://jsonplaceholder.typicode.com/users?_start=0&_limit=1)然后((res)=>{
const rowData=res.data.map((行)=>{
row.name=this.state.splitOption[0];
row.isExpanded=false;
row.currentSplit=此.state.splitOption[0];
row.nextSplit=checkIfSplitExistOnMount(this.state.splitOption[0])
row.parentId=0;
row.isVisble=true;
//console.log(行)
返回行;
});
这是我的国家({
数据:行数据
},()=>{//console.log(this.state.data)
});
});
}
getReportData()
}
render(){
//更新状态函数
const updateState=()=>{
这是我的国家({
数据:[…this.state.data],
splitOption:[…this.state.splitOption],
选择:[…this.state.selection],
}, () => {})
}
//重复更新父级和子级
常量递归=(obj)=>{
设row=obj;
row.isExpanded=row.isExpanded;
row.currentSplit=row.currentSplit;
row.nextSplit=checkIfSplitExist(row.currentSplit)
如果(row.children&&row.children.length>0){//检查是否有子级
forEach(v=>{//if)让子对象对每个子对象执行相同的递归
递归(v);
});
}
返回行;//返回最终的新对象
}
常量递归del=(对象,拆分)=>{
var行=obj;
row.currentSplit=row.currentSplit;
row.nextSplit=checkIfSplitExist(row.currentSplit)
如果(row.children&&row.children.length>0){//检查是否有子级
forEach(v=>{//if)让子对象对每个子对象执行相同的递归
递归del(v);
});
}
返回行;//返回最终的新对象
}
//函数检查是否存在下一次拆分,如果存在下一次拆分,则返回下一次拆分
const checkIfSplitExist=(currentSplit)=>{
const i=u.findIndex(this.state.splitOption,函数(el){
返回el==currentSplit;
});
如果(i!==-1){
if(this.state.splitOption[i+1]){
返回此.state.splitOption[i+1];
}否则{
返回null;
}
}
}
//添加拆分时的递归更新
常量递归更新=(数据)=>{
常量prevData=[…数据];
返回prevData.map((行)=>{
const updatedata=递归(行);
返回行;
});
}
//函数递归删除子节点和父节点
常量递归删除=(数据,拆分)=>{
常量prevData=[…数据];
返回prevData.map((行)=>{
const data=recursionDel(行、拆分);
返回行;
});
}
const addNewSplit=(拆分)=>{
const i=u.findIndex(this.state.splitOption,函数(el){
返回el==拆分;
});
如果(i==-1){
这是我的国家(
{
splitOption:[…this.state.splitOption,split]
},
()=>{
var rowData=recursiveUpdate(this.state.data)
this.setState({data:rowData})
}
);
}否则{
const prevData=[…this.state.splitOption];
var指数=prevData.indexOf(分割);
prevData.拼接(索引,1)
如果(索引!=-1){
这是我的国家(
{
拆分选项:prevData
},
()=> {
var rowData=recursiveDelete(this.state.data,split)
this.setState({data:rowData})
}
)
}
}
}
//添加lazyload扩展数据
const ExpandableTableRow=({rows})=>{
欺骗