在"链接单击"中,如何展开和折叠所有树节点



我使用react从xml文件生成一个树。我有两个链接"全部展开"one_answers"全部折叠"。当单击"全部展开"链接时,如果树处于折叠模式,如何展开所有树节点?单击"全部折叠"链接时,如果树处于展开模式,如何折叠所有树节点?

App.js
import React, { Component } from 'react';
import { Switch, Route, Link } from "react-router-dom";
import { BrowserRouter } from 'react-router-dom';
import Home from './Home';
export class App extends Component {
constructor(props) {
super(props);
}
render() {
return (
<BrowserRouter>
<Switch>
{/* Otherwise, render the Landing component */}
<Route component={Home} />
</Switch>
</BrowserRouter>
);
}
}
export default App;
-------------------------------
Home.js
import React, { Component } from 'react';
import ProductsTree from './ProductsTreeView';
class Home extends React.Component {
constructor(props) {
super(props);
this.state =
{
currentNode: {},
};
this.setCurrentNode = this.setCurrentNode.bind(this);
}
setCurrentNode(node) {
this.setState({ currentNode: node });
}

render() {
return (
<div>
<table width="100%" border="0" cellSpacing="0" cellPadding="0">
<tbody>
<tr width="100%">
<td align="left" nowrap="true">
<b><a href=’’>Expand All</a></b>
<b><a href=’’>Collapse All</a></b>
</td>
</tr>
</tbody>
</table>
<br />
<ProductsTree setCurrentNode={this.setCurrentNode} />
</div>
);
}
}
export default Home;
-------------------------------
ProductsTreeView.js
import React, { Component } from 'react';
import axios from 'axios';
import XMLParser from 'react-xml-parser';
import tree from './tree.xml'

class ProductsTreeView extends Component {
render() {
return (
<div id="TreeView">
<TreeView setCurrentNode={this.props.setCurrentNode} />
</div>
);
}
}
class Node {
description = 'n/a';
id = -1;
key_id = -1;
linkpagename = '';
isActive = false;
nodes = [];
constructor(description, id, key_id, linkpagename) {
this.description = description;
this.id = id;
this.key_id = key_id;
this.linkpagename = linkpagename;
}
static nodesFromXml(xml) {
const map = (entity, nodes) => {
const id = entity.attributes['id'];
const key_id = entity.attributes['key-id'];
const descriptionText =
entity.children[
entity.children.findIndex((child) => child.name === 'description')
].value;
const entities = entity.children.filter(
(child) => child.name === 'entity'
);
var linkPageName = entity.attributes['link-page-name'];
const node = new Node(descriptionText, id, key_id, linkPageName);
nodes.push(node);
entities.forEach((entity) => map(entity, node.nodes));
};
const parsedData = new XMLParser().parseFromString(xml);
const entities = parsedData.children.filter(
(child) => child.name === 'entity'
);
const nodes = [];
entities.forEach((entity) => map(entity, nodes));
return nodes;
}
}
class TreeView extends React.Component {
constructor(props) {
super(props);
this.state = { nodes: [] };
this.toggleNode = this.toggleNode.bind(this);
}
componentDidMount() {
axios
.get(tree, { 'Content-Type': 'application/xml; charset=utf-8' })
.then((response) =>
this.setState({ nodes: Node.nodesFromXml(response.data) })
);
}
render() {
const nodes = this.state.nodes;
return (
<ul>
{nodes.map((node) => (
<TreeNode
id={node.id}
key={node.key_id}
node={node}
onToggle={this.toggleNode}
setCurrentNode={this.props.setCurrentNode}
/>
))}
</ul>
);
}
toggleNode(node) {
if (node.nodes.length === 0) return;
this.props.setCurrentNode(node);
function _toggleNode(currentNode, node) {
if (currentNode.id === node.id) {
currentNode.isActive = !currentNode.isActive;
} else {
currentNode.nodes.forEach((childNode) => _toggleNode(childNode, node));
}
}
const nodes = this.state.nodes;
nodes.forEach((currentNode) => _toggleNode(currentNode, node));
this.setState((state) => (state.nodes = nodes));
}
}
class TreeNode extends React.Component {
render() {
const node = this.props.node;
const onToggle = this.props.onToggle;
let acitveChildren = null;
if (node.isActive && node.nodes.length > 0) {
acitveChildren = (
<ul>
{node.nodes.map((node) => (
<TreeNode
id={node.id}
key={node.key_id}
node={node}
onToggle={onToggle}
/>
))}
</ul>
);
}
return (
<li
id={node.id} linkpagename={node.linkpagename}
key={node.key_id}
onClick={(event) => {
event.stopPropagation();
onToggle(node);
}}
>
{node.description} - {node.key_id} - {node.linkpagename}
{acitveChildren}
</li>
);
}
}
export default ProductsTreeView;
---------------------------------------
tree.xml
<?xml version="1.0" standalone="yes"?>
<tree>
<entity id="e11" key-id="1" link-page-name="Add_Item">
<description>Service</description>
<image>images/plus.gif</image>
<imageNode>images/de.gif</imageNode>
<imageOpen>images/minus.gif</imageOpen>
<entity id="e248" key-id="48" link-page-name="Add_SubItem">
<description>A_test1_test1</description>
<image>images/plus.gif</image>
<imageNode>images/de.gif</imageNode>
<imageOpen>images/minus.gif</imageOpen>
<entity id="e3717" key-id="717" link-page-name="Edit_SubItem">
<description>A_SubItem1</description>
<image>images/plus.gif</image>
<imageNode>images/de.gif</imageNode>
<imageOpen>images/minus.gif</imageOpen>
<entity id="e45546" key-id="5546" link-page-name="Edit_ItemTemplate">
<description>A_Test_Template</description>
<image>images/paper.gif</image>
<imageOpen>images/paper.gif</imageOpen>
</entity>
</entity>
</entity>
<entity id="e21" key-id="1" link-page-name="Add_SubItem">
<description>Checking</description>
<image>images/plus.gif</image>
<imageNode>images/de.gif</imageNode>
<imageOpen>images/minus.gif</imageOpen>
<entity id="e3606" key-id="606" link-page-name="Edit_SubItem">
<description>Categories</description>
<image>images/plus.gif</image>
<imageNode>images/de.gif</imageNode>
<imageOpen>images/minus.gif</imageOpen>
<entity id="e45112" key-id="5112" link-page-name="Edit_ItemTemplate">
<description>All states</description>
<image>images/paper.gif</image>
<imageOpen>images/paper.gif</imageOpen>
</entity>
</entity>
<entity id="e3382" key-id="382" link-page-name="Edit_SubItem">
<description>Advan</description>
<image>images/plus.gif</image>
<imageNode>images/de.gif</imageNode>
<imageOpen>images/minus.gif</imageOpen>
<entity id="e43157" key-id="3157" link-page-name="Edit_ItemTemplate">
<description>States</description>
<image>images/paper.gif</image>
<imageOpen>images/paper.gif</imageOpen>
</entity>
</entity>
<entity id="e247" key-id="47" link-page-name="Add_SubItem">
<description>A_test6</description>
<image>images/plus.gif</image>
<imageNode>images/de.gif</imageNode>
<imageOpen>images/minus.gif</imageOpen>
<entity id="e3716" key-id="716" link-page-name="Edit_SubItem">
<description>A_Item</description>
<image>images/plus.gif</image>
<imageNode>images/de.gif</imageNode>
<imageOpen>images/minus.gif</imageOpen>
<entity id="e45545" key-id="5545" link-page-name="Edit_ItemTemplate">
<description>temp1</description>
<image>images/paper.gif</image>
<imageOpen>images/paper.gif</imageOpen>
</entity>
</entity>
</entity>
</entity>
</entity>
<entity id="e12" key-id="2" link-page-name="Add_Item">
<description>Sales</description>
<image>images/plus.gif</image>
<imageNode>images/de.gif</imageNode>
<imageOpen>images/minus.gif</imageOpen>
<entity id="e230" key-id="30" link-page-name="Add_SubItem">
<description>Gift Cards</description>
<image>images/plus.gif</image>
<imageNode>images/de.gif</imageNode>
<imageOpen>images/minus.gif</imageOpen>
<entity id="e3421" key-id="421" link-page-name="Edit_SubItem">
<description>Sample Card</description>
<image>images/plus.gif</image>
<imageNode>images/de.gif</imageNode>
<imageOpen>images/minus.gif</imageOpen>
<entity id="e43308" key-id="3308" link-page-name="Edit_ItemTemplate">
<description>greeting temp</description>
<image>images/paper.gif</image>
<imageOpen>images/paper.gif</imageOpen>
</entity>
</entity>
<entity id="e3422" key-id="422" link-page-name="Edit_SubItem">
<description>De Card</description>
<image>images/plus.gif</image>
<imageNode>images/de.gif</imageNode>
<imageOpen>images/minus.gif</imageOpen>
<entity id="e43309" key-id="3309" link-page-name="Edit_ItemTemplate">
<description>NS Temp</description>
<image>images/paper.gif</image>
<imageOpen>images/paper.gif</imageOpen>
</entity>
</entity>

</entity>
<entity id="e215" key-id="15" link-page-name="Add_SubItem">
<description>Chck</description>
<image>images/plus.gif</image>
<imageNode>images/de.gif</imageNode>
<imageOpen>images/minus.gif</imageOpen>
<entity id="e3671" key-id="671" link-page-name="Edit_SubItem">
<description>Add item</description>
<image>images/plus.gif</image>
<imageNode>images/de.gif</imageNode>
<imageOpen>images/minus.gif</imageOpen>
<entity id="e45438" key-id="5438" link-page-name="Edit_ItemTemplate">
<description>Ahhhh</description>
<image>images/paper.gif</image>
<imageOpen>images/paper.gif</imageOpen>
</entity>
</entity>
<entity id="e3450" key-id="450" link-page-name="Edit_SubItem">
<description>Advtttt</description>
<image>images/plus.gif</image>
<imageNode>images/de.gif</imageNode>
<imageOpen>images/minus.gif</imageOpen>
<entity id="e43577" key-id="3577" link-page-name="Edit_ItemTemplate">
<description>gggggg</description>
<image>images/paper.gif</image>
<imageOpen>images/paper.gif</imageOpen>
</entity>
</entity>
</entity>       
</entity>
</tree>

请帮助我如何在React中做到这一点?

试试这个沙箱,它展示了如何open/close allhttps://codesandbox.io/s/react-tree-renerer-forked-f5g46l?file=/src/components/Event.js

以及此处的更多react-tree-renderer示例https://codesandbox.io/s/react-tree-renerer-1zg2w5?file=/src/App.js

如果您在使用react树更新器时遇到任何问题,请在github-reop上提出问题https://github.com/postor/react-tree-renderer

最新更新