Remove/Add 单击父节点时,数组中树的所有子节点
Remove/Add all childrenNode of a tree from an array when clicking on a parentNode
我有这个嵌套对象:
export interface RenderTree {
id: string;
name: string;
children?: readonly RenderTree[];
}
export const UserLoginRoleV2Tree: RenderTree = {
id: "root",
name: "APP",
children: [
{
id: "1",
name: UserLoginRoleV2.DASHBOARD
},
{
id: "2",
name: UserLoginRoleV2.REPORTING,
children: [
{
id: "2.1",
name: UserLoginRoleV2.REPORTS
},
{
id: "2.2",
name: UserLoginRoleV2.SALES_DETAILS
},
{
id: "2.3",
name: UserLoginRoleV2.LEADS_DETAILS
}
]
},
{
id: "3",
name: UserLoginRoleV2.SALES_DATA,
children: [
{
id: "3.1",
name: UserLoginRoleV2.SALES
},
{
id: "3.2",
name: UserLoginRoleV2.LEADS
},
{
id: "3.3",
name: UserLoginRoleV2.CALLS
},
{
id: "3.4",
name: UserLoginRoleV2.PHONE_CLOSING
}
]
},
{
id: "4",
name: UserLoginRoleV2.TRACKING,
children: [
{
id: "4.1",
name: UserLoginRoleV2.UNIVERSAL_SCRIPT
},
{
id: "4.2",
name: UserLoginRoleV2.SOURCE_LINKS
},
{
id: "4.3",
name: UserLoginRoleV2.URL_RULES
},
{
id: "4.4",
name: UserLoginRoleV2.PRODUCTS
},
{
id: "4.4",
name: UserLoginRoleV2.TAGS
}
]
},
{
id: "5",
name: UserLoginRoleV2.SETTINGS,
children: [
{
id: "5.1",
name: UserLoginRoleV2.PROFILE
},
{
id: "5.2",
name: UserLoginRoleV2.BILLING
},
{
id: "5.3",
name: UserLoginRoleV2.SUB_USERS
},
{
id: "5.4",
name: UserLoginRoleV2.CONNECTED_ACCOUNTS
},
{
id: "5.5",
name: UserLoginRoleV2.INTEGRATIONS
},
{
id: "5.6",
name: UserLoginRoleV2.TRACKING_SETTINGS
},
{
id: "5.7",
name: UserLoginRoleV2.TRACKING_DOMAINS
}
]
}
]
}
从这个对象,我可以构建一个 Tree。树的每个节点都有一个复选框。要知道复选框是否被选中,当我保留所有被选中的节点时,我有一个状态数组:
interface State {
roles: Array<string>;
}
<TreeItem key={nodes.id} nodeId={nodes.id} label={<Checkbox checked={this.state.roles.includes(nodes.name)} onClick={...}>
{Array.isArray(nodes.children)
? nodes.children.map((node) => this.renderTree(node))
: null}
</TreeItem>
我正在寻找一种方法,在单击某个节点时从数组中删除该节点的所有子节点,因为我知道一个子节点也可以有子节点。
我觉得我们可以用递归函数来实现它,但我现在还没有成功。你能帮帮我吗?
好的,我用 Depth-first search
解决了它
/**
* Get all children of a node.
* @param branch The node whose children you want to know
* @param callback Function to apply on each node.
*/
const breadthFirstSearch = (branch: TreeBranch): TreeBranch[] => {
let queue = new Array(branch);
let explored = new Array(branch);
let res = new Array();
let b: TreeBranch;
while (queue.length !== 0) {
b = queue.shift();
res.push(b);
b.children?.forEach(child => {
if (!explored.includes(child)) {
queue.push(child);
explored.push(child);
}
})
}
return res;
}
我有这个嵌套对象:
export interface RenderTree {
id: string;
name: string;
children?: readonly RenderTree[];
}
export const UserLoginRoleV2Tree: RenderTree = {
id: "root",
name: "APP",
children: [
{
id: "1",
name: UserLoginRoleV2.DASHBOARD
},
{
id: "2",
name: UserLoginRoleV2.REPORTING,
children: [
{
id: "2.1",
name: UserLoginRoleV2.REPORTS
},
{
id: "2.2",
name: UserLoginRoleV2.SALES_DETAILS
},
{
id: "2.3",
name: UserLoginRoleV2.LEADS_DETAILS
}
]
},
{
id: "3",
name: UserLoginRoleV2.SALES_DATA,
children: [
{
id: "3.1",
name: UserLoginRoleV2.SALES
},
{
id: "3.2",
name: UserLoginRoleV2.LEADS
},
{
id: "3.3",
name: UserLoginRoleV2.CALLS
},
{
id: "3.4",
name: UserLoginRoleV2.PHONE_CLOSING
}
]
},
{
id: "4",
name: UserLoginRoleV2.TRACKING,
children: [
{
id: "4.1",
name: UserLoginRoleV2.UNIVERSAL_SCRIPT
},
{
id: "4.2",
name: UserLoginRoleV2.SOURCE_LINKS
},
{
id: "4.3",
name: UserLoginRoleV2.URL_RULES
},
{
id: "4.4",
name: UserLoginRoleV2.PRODUCTS
},
{
id: "4.4",
name: UserLoginRoleV2.TAGS
}
]
},
{
id: "5",
name: UserLoginRoleV2.SETTINGS,
children: [
{
id: "5.1",
name: UserLoginRoleV2.PROFILE
},
{
id: "5.2",
name: UserLoginRoleV2.BILLING
},
{
id: "5.3",
name: UserLoginRoleV2.SUB_USERS
},
{
id: "5.4",
name: UserLoginRoleV2.CONNECTED_ACCOUNTS
},
{
id: "5.5",
name: UserLoginRoleV2.INTEGRATIONS
},
{
id: "5.6",
name: UserLoginRoleV2.TRACKING_SETTINGS
},
{
id: "5.7",
name: UserLoginRoleV2.TRACKING_DOMAINS
}
]
}
]
}
从这个对象,我可以构建一个 Tree。树的每个节点都有一个复选框。要知道复选框是否被选中,当我保留所有被选中的节点时,我有一个状态数组:
interface State {
roles: Array<string>;
}
<TreeItem key={nodes.id} nodeId={nodes.id} label={<Checkbox checked={this.state.roles.includes(nodes.name)} onClick={...}>
{Array.isArray(nodes.children)
? nodes.children.map((node) => this.renderTree(node))
: null}
</TreeItem>
我正在寻找一种方法,在单击某个节点时从数组中删除该节点的所有子节点,因为我知道一个子节点也可以有子节点。
我觉得我们可以用递归函数来实现它,但我现在还没有成功。你能帮帮我吗?
好的,我用 Depth-first search
解决了它/**
* Get all children of a node.
* @param branch The node whose children you want to know
* @param callback Function to apply on each node.
*/
const breadthFirstSearch = (branch: TreeBranch): TreeBranch[] => {
let queue = new Array(branch);
let explored = new Array(branch);
let res = new Array();
let b: TreeBranch;
while (queue.length !== 0) {
b = queue.shift();
res.push(b);
b.children?.forEach(child => {
if (!explored.includes(child)) {
queue.push(child);
explored.push(child);
}
})
}
return res;
}