原文連接:reactjs.org/docs/compos…html
React擁有功能強大的組合模式,咱們推薦使用組合而非繼承來實現代碼的複用。react
在本章中,咱們將要討論幾個React新手常常會遇到的關於繼承的問題並展現咱們如何使用組合解決它們。安全
某些組件不能預先知道它的子元素是怎樣的,這對於相似於SideBar或Dialog這類容器組件來講是十分常見的。bash
咱們推薦在使用這類組件時使用特殊的children
prop直接將子元素渲染到輸出。框架
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>
);
}
複製代碼
在JSX標籤<FancyBorder>
的任意值都會經過children
prop傳遞給FancyBorder
組件。因此因爲FancyBorder
在<div>
中渲染了{props.children}
,因此被傳遞進來的元素最終都被渲染到頁面上。ui
固然這種狀況不太常見,但有時候組件中咱們須要幾個「洞」來傳入對應prop。在這種狀況下咱們就須要自定義prop名而不是使用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 />
} />
);
}
複製代碼
React元素<Contacts />
和<Chat />
只是對象,因此你能夠像傳遞其餘數據同樣經過prop傳遞它們。這種方法可能會讓你決定很想其餘框架的「插槽」,可是在React中經過props傳遞的參數是沒有限制的。spa
有些時候咱們須要某個組件稱爲區別於其餘組件的特例,好比WelcomeDialog
就是Dialog
的一個特例。code
在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!" />
);
}
複製代碼
組合也適用於class組件:
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,但咱們沒有發現使用繼承能有更好實現效果的例子。
props和組合讓你自由,顯式且安全地定義你的組件。請記得能夠接收任意的props(基本類型數據,React元素或者方法)。
若是你想要在組件間複用非UI行的方法,那咱們推薦把它提取成JavaScript模塊,這樣組件就能夠import(引入)它而不是繼承它。