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 模塊中。這樣能夠在不對組件進行擴展的前提下導入並使用該函數、對象或類。