React 具备强大的组合模型,咱们建议使用组合而不是继承来复用组件之间的代码。javascript
在本节中,咱们将围绕几个 React 新手常常使用继承解决的问题,咱们将展现若是用组合来解决它们。css
一些组件不能提早知道它们的子组件是什么。这对于 Sidebar
或 Dialog
这类通用容器尤为常见。java
咱们建议这些组件使用 children
属性将子元素直接传递到输出。安全
function FancyBorder(props) { return ( <div className={'FancyBorder FancyBorder-' + props.color}> {props.children} </div> ); }
这样作还容许其余组件经过嵌套 JSX 来传递子组件。ide
function WelcomeDialog() { return ( <FancyBorder color="blue"> <h1 className="Dialog-title"> Welcome </h1> <p className="Dialog-message"> Thank you for visiting our spacecraft! </p> </FancyBorder> ); }
<FancyBorder>
JSX 标签内的任何内容都将经过 children
属性传入 FancyBorder
。因为 FancyBorder
在一个 <div>
内渲染了 {props.children}
,因此被传递的全部元素都会出如今最终输出中。网站
虽然不太常见,但有时你可能须要在组件中有多个入口,这种状况下你可使用本身约定的属性而不是 children
:this
function SplitPane(props) { return ( <div className="SplitPane"> <div className="SplitPane-left"> {props.left} </div> <div className="SplitPane-right"> {props.right} </div> </div> ); } function App() { return ( <SplitPane left={ <Contacts /> } right={ <Chat /> } /> ); }
相似 <Contacts />
和 <Chat />
这样的 React 元素都是对象,因此你能够像任何其余元素同样传递它们。code
有时咱们认为组件是其余组件的特殊实例。例如,咱们会说 WelcomeDialog
是 Dialog
的特殊实例。
在 React 中,这也是经过组合来实现的,经过配置属性用较特殊的组件来渲染较通用的组件。
function Dialog(props) { return ( <FancyBorder color="blue"> <h1 className="Dialog-title"> {props.title} </h1> <p className="Dialog-message"> {props.message} </p> </FancyBorder> ); } function WelcomeDialog() { return ( <Dialog title="Welcome" message="Thank you for visiting our spacecraft!" /> ); }
组合对于定义为类的组件一样适用:
function Dialog(props) { return ( <FancyBorder color="blue"> <h1 className="Dialog-title"> {props.title} </h1> <p className="Dialog-message"> {props.message} </p> {props.children} </FancyBorder> ); } class SignUpDialog extends React.Component { constructor(props) { super(props); this.handleChange = this.handleChange.bind(this); this.handleSignUp = this.handleSignUp.bind(this); this.state = {login: ''}; } render() { return ( <Dialog title="Mars Exploration Program" message="How should we refer to you?"> <input value={this.state.login} onChange={this.handleChange} /> <button onClick={this.handleSignUp}> Sign Me Up! </button> </Dialog> ); } handleChange(e) { this.setState({login: e.target.value}); } handleSignUp() { alert(`Welcome aboard, ${this.state.login}!`); } }
在 Facebook 网站上,咱们的 React 使用了数以千计的组件,然而却还未发现任何须要推荐你使用继承的状况。
属性和组合为你提供了以清晰和安全的方式自定义组件的样式和行为所需的全部灵活性。请记住,组件能够接受任意元素,包括基本数据类型、React 元素或函数。
若是要在组件之间复用 UI 无关的功能,咱们建议将其提取到单独的 JavaScript 模块中。这样能够在不对组件进行扩展的前提下导入并使用该函数、对象或类。