React.js:组合组件以创建选项卡
我正在尝试制作一个标签组件.TabsSwitcher 和 TabsPanel 必须是单独的组件,以便它们可以在 DOM 中的任何地方使用,例如TabsSwitcher 后面不一定要跟 TabsPanel.
为了让它工作,我需要以某种方式连接这些组件.此外,TabsSwitcher 必须能够告诉 TabsPanel 何时单击了选项卡.
/** @jsx React.DOM */var TabsExample = React.createClass({渲染:函数(){变量标签 = [{标题:'第一',内容:'内容1'},{标题:'第二',内容:'内容2'}];返回 <TabsSwitcher items={tabs}/><TabsContent items={tabs}/></div>;}});var TabsSwitcher = React.createClass({渲染:函数(){var items = this.props.items.map(function(item) {return <a onClick={this.onClick}>{item.title}</a>;}.bind(this));返回 <div>{items}</div>;},点击:函数(e){//通知 TabsContent 点击}});var TabsContent = React.createClass({渲染:函数(){var items = this.props.items.map(function(item) {返回 <div>{item.content}</div>;});返回 <div>{items}</div>;}});React.renderComponent(<TabsExample/>,文档.body);
最好的方法是什么?
<小时>解决方案:http://jsfiddle.net/NV/5YRG9/
解决方案React 文档在组件间通信" 和 "多个组件".要点是父母应该将一个函数作为道具传递给孩子,孩子应该在需要时将该函数作为回调调用:
var TabsExample = React.createClass({handleTabClick:功能(项目){//对项目做一些事情,也许将其设置为活动.},渲染:函数(){变量标签 = [{标题:'第一',内容:'内容1'},{标题:'第二',内容:'内容2'}];返回 <TabsSwitcher items={tabs} onTabClick={this.handleTabClick}/><TabsContent items={tabs}/></div>;}});var TabsSwitcher = React.createClass({渲染:函数(){var items = this.props.items.map(function(item) {return <a onClick={this.onClick.bind(this, item)}>{item.title}</a>;}.bind(this));返回 <div>{items}</div>;},onClick:功能(项目){this.props.onTabClick(item);}});
对于 TabsContent
组件,您应该将 tabs
移动到 TabsExample
状态,以便 React 可以在它们更改时自动为您重新渲染.由于 TabsSwitcher
和 TabsContent
在 render 方法中传递了选项卡,React 知道它们依赖于选项卡,并且会在状态更改时重新渲染:
var TabsExample = React.createClass({获取初始状态:函数(){返回 {activeTabId: 1,标签:[{title: 'first', content: '内容 1', id: 1},{标题:'第二',内容:'内容2',id:2}]};};handleTabClick:功能(项目){//调用 `setState` 以便 React 知道更新的选项卡项.this.setState({activeTabId: item.id});},渲染:函数(){返回 (<TabsSwitcher 项目={this.state.tabs}activeItemId={this.state.activeTabId}onTabClick={this.handleTabClick}/><TabsContent 项={this.state.tabs}activeItemId={this.state.activeTabId}/></div>);}});
I’m trying to make a tabs component. TabsSwitcher and TabsPanel must be separate components so they could be used anywhere in DOM, e.g. TabsSwitcher doesn’t have to be followed by TabsPanel.
To make it work, I need to somehow connect these components. Furthermore, TabsSwitcher must be able to tell TabsPanel when a tab was clicked.
/** @jsx React.DOM */
var TabsExample = React.createClass({
render: function() {
var tabs = [
{title: 'first', content: 'Content 1'},
{title: 'second', content: 'Content 2'}
];
return <div>
<TabsSwitcher items={tabs}/>
<TabsContent items={tabs}/>
</div>;
}
});
var TabsSwitcher = React.createClass({
render: function() {
var items = this.props.items.map(function(item) {
return <a onClick={this.onClick}>{item.title}</a>;
}.bind(this));
return <div>{items}</div>;
},
onClick: function(e) {
// notify TabsContent about the click
}
});
var TabsContent = React.createClass({
render: function() {
var items = this.props.items.map(function(item) {
return <div>{item.content}</div>;
});
return <div>{items}</div>;
}
});
React.renderComponent(
<TabsExample/>,
document.body
);
What’s the best way to do it?
Solution: http://jsfiddle.net/NV/5YRG9/
解决方案The React docs cover this in detail in "Communicate Between Components" and "Multiple Components". The gist is that the parent should pass a function as a prop to the child, and the child should call that function as a callback when it needs to:
var TabsExample = React.createClass({
handleTabClick: function(item) {
// Do something with item, maybe set it as active.
},
render: function() {
var tabs = [
{title: 'first', content: 'Content 1'},
{title: 'second', content: 'Content 2'}
];
return <div>
<TabsSwitcher items={tabs} onTabClick={this.handleTabClick}/>
<TabsContent items={tabs}/>
</div>;
}
});
var TabsSwitcher = React.createClass({
render: function() {
var items = this.props.items.map(function(item) {
return <a onClick={this.onClick.bind(this, item)}>{item.title}</a>;
}.bind(this));
return <div>{items}</div>;
},
onClick: function(item) {
this.props.onTabClick(item);
}
});
For the TabsContent
component, you should move the tabs
into the TabsExample
state so React can automatically re-render for you when they change. Since TabsSwitcher
and TabsContent
are passed the tabs in the render method, React knows they are dependent on the tabs and will re-render when the state changes:
var TabsExample = React.createClass({
getInitialState: function() {
return {
activeTabId: 1,
tabs: [
{title: 'first', content: 'Content 1', id: 1},
{title: 'second', content: 'Content 2', id: 2}
]
};
};
handleTabClick: function(item) {
// Call `setState` so React knows about the updated tab item.
this.setState({activeTabId: item.id});
},
render: function() {
return (
<div>
<TabsSwitcher items={this.state.tabs}
activeItemId={this.state.activeTabId}
onTabClick={this.handleTabClick}/>
<TabsContent items={this.state.tabs}
activeItemId={this.state.activeTabId}/>
</div>
);
}
});
相关文章