在 reactjs 中引用子项的正确方法 -> 不要引用子项来查询其状态。如果您需要从父级查询该状态,则将该状态放入父级并将该状态作为道具注入子级。
这是您的代码重做:
http://jsfiddle.net/t5fwn/7/
/** @jsx React.DOM */
var initialState = {
"folders": [
{
"name": "folder1",
"open": false,
"files": [{
"text": "content1 1"
}]
},
{
"name": "folder2",
"open": false,
"files": [{
"text": "content2 1"
}, {
"text": "content2 2"
}]
}
]
};
var Folder = React.createClass({
render: function() {
var items = [];
if( this.props.folderData.open ){
this.props.folderData.files.forEach(function(file) {
items.push( <div className="itemBox">{file.text}</div>);
});
}
return (
<div className="items_directory">
<div className="folder_header" onClick={this.props.onFolderClick}>{this.props.folderData.name}</div>
<div className="folder_content">
{items}
</div>
</div>
);
}
});
var FoldersManager = React.createClass({
getInitialState: function() {
return this.props.initialState;
},
render: function(){
var self = this;
var folderComponents = this.state.folders.map(function(folder,folderIndex) {
var onFolderClick = function() {
self.toggleFolder(folderIndex);
};
return <Folder folderData={folder} onFolderClick={onFolderClick}/>;
});
return (
<div>
<button onClick={this.toggleAll}>Toggle All</button>
<div>
{folderComponents}
</div>
</div>
);
},
toggleFolder: function(folderIndex) {
var newState = this.state;
newState.folders[folderIndex].open = !newState.folders[folderIndex].open;
this.setState(newState);
},
toggleAll: function(){
var newState = this.state;
var newOpenToSet = this.isAllFoldersOpen() ? false : true;
newState.folders.forEach(function(folder) {
folder.open = newOpenToSet;
});
this.setState(newState);
},
isAllFoldersOpen: function() {
return this.countFoldersOpen() == this.state.folders.length;
},
countFoldersOpen: function() {
var i = 0;
this.state.folders.forEach(function(folder) {
if ( folder.open ) i++;
});
return i;
}
});
React.renderComponent(<FoldersManager initialState={initialState} />, document.body);
最好有某种管理器组件来处理所有文件夹的打开/关闭状态。 Folder 组件可以简单地用于渲染文件夹,但不能用于管理文件夹的状态,或者在您的全局 toggleAll 操作中,您必须“查询”子组件以了解它们的状态。
PS(额外问题):我认为不渲染未显示的内容更优雅。但出于性能原因,如果隐藏/显示状态频繁变化,使用display : none; 可能会更好:它会产生相同的视觉效果,但 DOM 差异会更轻。除非您发现不渲染隐藏元素存在性能问题,否则不要对此进行优化。