我正在尝试构建一个能够在点击(或其他内容)时显示/隐藏其TR子项的树表。
我从网上获取了一些代码,可以轻松生成树形结构。问题是尝试与此事件设置父/子关系。我真的不习惯反应所以我很难理解某些事情。
这是数据结构:
var data = [
{
id: 1,
label: 'Order 1',
deep: 0,
children: [{
id: 11,
label: 'Cycle November',
deep: 1,
},
{
id: 12,
label: 'Cycle December',
deep: 1,
}]
},
{
id: 2,
label: 'Order 2',
deep: 0,
children: [{
id: 21,
label: 'Cycle January',
deep: 1
}]
},
];
然后我想点击父母1,看看他们的孩子是谁。
这是绘制表格的代码:
var TR = React.createClass({
childs: [],
hasParent: function() {
if (this.props.parent) {
return true;
}
else {
return false;
}
},
componentDidMount: function(){
if (this.hasParent()) {
parentKey = this.props.parent.props.keyId.split('-')[1];
thisKey = this.props.keyId.split('-')[0];
if (parentKey == thisKey) {
console.log('I set the child');
this.props.parent.props.childs.push(this);
}
}
},
handleClick: function(event) {
if (this.hasParent()) {
parent = this.props.parent;
console.log('My father is: '+parent.props.keyId);
console.log('Me and my brothers are: ');
parent.props.childs.map(function(child) {
console.log(child.props.keyId);
});
}
else {
console.log('I am: '+this.props.keyId);
console.log('My children are:');
this.props.childs.map(function(child) {
console.log(child.props.keyId);
});
}
},
isShown: function() {
return false;
},
getDefaultProps: function() {
return {
childs: new Array(),
};
},
render: function() {
var iparent = this.props.data.deep*20;
return (
<tr>
<td style={{paddingLeft: iparent+'px'}}>
<span onClick={this.handleClick} >
+ </span>
{this.props.data.label}
</td>
</tr>
);
}
});
var Tree = React.createClass({
render: function() {
var treeItems = [];
parent = null;
var renderTreeItems = function(items, parent) {
if (!items) {
return;
}
for (var i = 0; i < items.length; i++) {
if (items[i].deep == 0) {
var parent_id = items[i].deep;
}
else {
var parent_id = parent.props.data.id;
}
var key = parent_id+'-'+items[i].id;
tr = (
<TR key={key} keyId={key} data={items[i]} parent={parent} >
</TR>
);
treeItems.push(
tr
);
renderTreeItems(items[i].children, tr);
}
};
renderTreeItems(this.props.data);
return (
<table>
{ treeItems }
</table>
);
}
});
最后使用HTML来附加组件:
<html>
<body>
<div id="tree"></div>
<script type="text/jsx">
React.render(<Tree data={data}/>, document.body);
</script>
</body>
</html>
实际问题是所有TR实例之间似乎共享了孩子(我知道写得很糟糕......)。 有人可以指出我做错了什么,处理这个问题的最佳方法是什么? 简单地说:我想隐藏/显示孩子们点击作为父母“行动”的TR-First TD。
这是jsfiddle http://jsfiddle.net/69z2wepo/2731/
答案 0 :(得分:1)
我在每个TR上使用parent_key
从新角度处理问题并查询所有数组以搜索具有parent_key
的对象,从而更改其属性。现在我开始使用功能齐全的表树。
//Won't work below IE9, but totally safe otherwise
!function() {
function _dynamicSortMultiple(attr) {
/*
* save the arguments object as it will be overwritten
* note that arguments object is an array-like object
* consisting of the names of the properties to sort by
*/
var props = arguments;
return function (obj1, obj2) {
var i = 0, result = 0, numberOfProperties = props.length;
/* try getting a different result from 0 (equal)
* as long as we have extra properties to compare
*/
while(result === 0 && i < numberOfProperties) {
result = _dynamicSort(props[i])(obj1, obj2);
i++;
}
return result;
};
}
function _dynamicSort(property) {
var sortOrder = 1;
if(property[0] === "-") {
sortOrder = -1;
property = property.substr(1);
}
return function (a,b) {
var result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
return result * sortOrder;
}
}
Object.defineProperty(Array.prototype, "sortBy", {
enumerable: false,
writable: true,
value: function() {
return this.sort(_dynamicSortMultiple.apply(null, arguments));
}
});
}();
var TD = React.createClass({
onHandleClick: function(event) {
this.props.onHandleClick(this.props.data.key);
},
render: function() {
var iparent = this.props.data.deep*20;
var icon = "fa-chevron-down";
return (
<td style={{paddingLeft: iparent+'px'}}>
<span onClick={this.onHandleClick} className={"fa "+icon}>
</span>
{this.props.data.label}
</td>
);
}
})
var TR = React.createClass({
onHandleClick: function(TD) {
this.props.onHandleClick(TD);
},
render: function() {
if (this.props.data.isShown) {
return (
<tr>
<TD data={this.props.data} onHandleClick={this.onHandleClick}/>
</tr>
);
}
else {
return (
<tr>
</tr>
);
}
}
});
var List = React.createClass({
render: function() {
var self = this;
var trs = this.props.data.map(function(row) {
var key = row.deep+'-'+row.id;
return (<TR key={key} keyId={key} parentKey={row.parent_key} data={row} onHandleClick={self.props.onHandleClick} />);
});
return (
<table>
{trs}
</table>
);
}
});
var Tree = React.createClass({
handleClick: function(key) {
newState = this.state.data.slice();
for (var i = newState.length - 1; i >= 0; i--) {
var item = newState[i];
if (item.parent_key == key) {
item.isShown = (item.isShown)?false:true;
newState[i] = item;
}
};
this.setState({data: newState});
},
loadFromServer: function() {
var data = [
{
id: 1,
label: 'Order 1',
deep: 0,
key: '0-1',
parent_key: '0',
},
{
id: 11,
label: 'Cycle November',
deep: 1,
key: '0-1-11',
parent_key: '0-1',
},
{
id: 12,
label: 'Cycle December',
deep: 1,
key: '0-1-12',
parent_key: '0-1',
},
{
id: 2,
label: 'Order 2',
deep: 0,
key: '0-2',
parent_key: '0'
},
{
id: 21,
label: 'Cycle January',
deep: 1,
key: '0-2-21',
parent_key: '0-2',
}
];
newState = [];
data.map(function(item) {
item.isShown = (item.deep != 0)?false:true;
newState.push(item);
});
newState.sortBy("key");
this.setState({data:newState});
},
getInitialState: function() {
return {data: []};
},
componentDidMount: function() {
this.loadFromServer();
},
render: function() {
return (
<div className="Box">
<table className="table table-striped table-hover dataTables-orders" >
<thead>
</thead>
<List data={this.state.data} onHandleClick={this.handleClick} />
</table>
</div>
);
}
});
React.render(<Tree data={data}/>, document.getElementById('tree'));