我有一个我自己无法解决的问题。 我有一个名为GROUPS的JavaScript对象。每个组可以具有一个或多个子组,也可以具有所谓的系统。
我现在的任务是以图形方式显示此结构-一种树视图(彩色DIV元素)。 但是我不知道如何读取该对象以图形方式进行构建。
我的对象:
const test = {
grp: [
{
groupID: 'group-1',
grp : [
{
groupID: 'group-2',
grp: [
{
groupID: 'group-3',
sys: ['sys1','sys2','sys3']
},
{
groupID: 'group-4',
grp: [
{
groupID: 'group-5',
sys: ['sys4','sys5','sys6']
},
{
groupID: 'group-6',
grp: [
{
groupID: 'group-7',
sys: ['sys7','sys8','sys9']
}
]
}
]
}
],
sys: ['sys0']
}
]
}
]
};
这是一个图形示例: https://pic-hoster.net/view/69453/grp-sys.jpg.htm
我非常希望这里有人可以帮助我。 您将如何处理这项任务?
JavaScript对象的图形表示(树状视图)
答案 0 :(得分:0)
这里重要的是确定您的数据结构,以便您可以递归地解决问题。
在您的情况下,您的组可以这样定义:
{
groupID: string,
sys?: string[],
grp?: IGroup[]
}
(其中IGroup
定义了上述结构)
所有组都有一个groupID
,一些有sys
,有些有grp
个孩子。
从这里我们可以定义一个函数,其逻辑如下:
sys
子元素(如果存在),将具有sys
值的单元格添加到第一行。grp
子元素(如果存在),调用此函数并将返回的结构附加到第一行的单元格中。grp
groupID
以下是上述几点的粗略实现:
function groupToHTML(grp) {
//Table to append to and return
var container = document.createElement("table");
container.border = "1";
container.style.borderCollapse = "collapse";
//Insert row to children of this node
var childRow = container.appendChild(document.createElement("tr"));
//Append all "sys" elements as cells
if (grp.sys !== void 0) {
for (var sysIndex = 0; sysIndex < grp.sys.length; sysIndex++) {
var sys = grp.sys[sysIndex];
var sysCell = childRow.appendChild(document.createElement("td"));
sysCell.innerHTML = sys;
sysCell.style.backgroundColor = "red";
sysCell.style.verticalAlign = "bottom";
}
}
//Append all "grp" children by calling "groupToHTML" on them and appending the returning table
if (grp.grp !== void 0) {
for (var grpIndex = 0; grpIndex < grp.grp.length; grpIndex++) {
var child = grp.grp[grpIndex];
var grpCell = childRow.appendChild(document.createElement("td"));
grpCell.appendChild(groupToHTML(child));
grpCell.style.verticalAlign = "bottom";
}
}
//Add a row and cell for "this" grp
var thisRow = container.appendChild(document.createElement("tr"));
var thisCell = thisRow.appendChild(document.createElement("th"));
thisCell.innerHTML = grp.groupID;
thisCell.style.textAlign = "center";
//Set cell colspan to number of child elements
thisCell.colSpan = Math.max(1, (grp.grp !== void 0 ? grp.grp.length : 0) + (grp.sys !== void 0 ? grp.sys.length : 0));
//Return table
return container;
}
//TEST
//testdata
var data = {
groupID: 'group-1',
grp: [
{
groupID: 'group-2',
grp: [
{
groupID: 'group-3',
sys: ['sys1', 'sys2', 'sys3']
}, {
groupID: 'group-4',
grp: [
{
groupID: 'group-5',
sys: ['sys4', 'sys5', 'sys6']
}, {
groupID: 'group-6',
grp: [
{
groupID: 'group-7',
sys: ['sys7', 'sys8', 'sys9']
}
]
}
]
}
],
sys: ['sys0']
}
]
};
//Initiate
var node = groupToHTML(data);
//Append
document.body.appendChild(node);
答案 1 :(得分:0)
您可以使用递归函数为每个grp
及其系统创建嵌套级别。因此,每个级别都有名称和子元素。子元素将是嵌套的组和系统。
纯JavaScript解决方案
const test = {"grp":[{"groupID":"group-1","grp":[{"groupID":"group-2","grp":[{"groupID":"group-3","sys":["sys1","sys2","sys3"]},{"groupID":"group-4","grp":[{"groupID":"group-5","sys":["sys4","sys5","sys6"]},{"groupID":"group-6","grp":[{"groupID":"group-7","sys":["sys7","sys8","sys9"]}]}]}],"sys":["sys0"]}]}]}
function tree(data, parent) {
if(data.grp) {
data.grp.forEach(obj => {
const child = document.createElement('div')
child.className = 'child'
const children = document.createElement('div')
children.className = 'children'
if(obj.groupID) {
const name = document.createElement('div');
name.className = 'name'
name.textContent = obj.groupID
child.appendChild(name)
}
if(obj.sys) {
const system = document.createElement('div')
system.className = 'system';
obj.sys.forEach(s => {
const sys = document.createElement('div')
sys.className = 'item'
sys.textContent = s
system.appendChild(sys)
})
children.appendChild(system)
}
child.appendChild(children)
parent.appendChild(child)
tree(obj, children)
})
}
}
const root = document.body.querySelector('#root')
tree(test, root)
#root * {
color: white;
}
.system {
background: #E00022;
display: flex;
flex-direction: column-reverse;
padding: 10px;
}
.name {
background: #595959;
padding: 10px;
}
.child {
display: flex;
flex-direction: column-reverse;
}
.children {
display: flex;
align-items: flex-end;
}
.children > div {
flex: 1;
border-bottom: 1px solid white;
}
<div id="root"></div>
反应解决方案
const {Component} = React;
const data = {"grp":[{"groupID":"group-1","grp":[{"groupID":"group-2","grp":[{"groupID":"group-3","sys":["sys1","sys2","sys3"]},{"groupID":"group-4","grp":[{"groupID":"group-5","sys":["sys4","sys5","sys6"]},{"groupID":"group-6","grp":[{"groupID":"group-7","sys":["sys7","sys8","sys9"]}]}]}],"sys":["sys0"]}]}]}
class Systems extends Component {
render() {
const { data } = this.props;
return <div className="systems">
{data.map((sys, i) => (
<div key={i} className="system">{sys}</div>
))}
</div>
}
}
class Group extends Component {
render() {
const { data } = this.props;
return data.map((group, i) => (
<div key={i} className="group">
{group.groupID && <div className="group-name">{group.groupID}</div>}
<div className="children">
{group.sys && <Systems data={group.sys} />}
{group.grp && <Group data={group.grp} />}
</div>
</div>
))
}
}
class App extends Component {
state = {
data: {}
}
componentWillMount = () => {
this.setState({ data: this.props.data })
}
render() {
console.log(this.state)
return <div className="root">
<Group data={this.state.data.grp} />
</div>
}
}
ReactDOM.render(
<App data={data} />,
document.getElementById('container')
);
#root * {
color: white;
}
.group {
display: flex;
flex-direction: column-reverse;
}
.group-name {
background: rgb(89, 89, 89);
padding: 10px;
color: white;
border-top: 1px solid white;
}
.group-name {
opacity: 0.85;
transition: all 0.25s;
}
.children {
display: flex;
}
.children > * {
flex: 1;
}
.systems {
display: flex;
flex-direction: column-reverse;
}
.system {
background: red;
color: white;
padding: 10px;
opacity: 0.6;
transition: all 0.25s;
border-top: 1px solid white;
}
.system:hover,
.group-name:hover{
opacity: 1;
}
.as-console-wrapper {
display: none !important;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="container"></div>