組合還是繼承?

React具有強(qiáng)大的組合模型,我們推薦使用組合來代替繼承,這樣可以在組件間重用代碼。
在本節(jié)中,我們將考慮幾個問題,遇到這些問題時,剛接觸React的開發(fā)者一般會考慮使用繼承,而我們將展示如何用組合來解決他們。

包含

一些組件提前不知道它的孩子。在諸如側(cè)欄和對話框這些通用“框”中尤為常見。
我們建議這種組件使用專門的childrenprop來直接傳遞子元素到他們的輸出:

function FancyBorder(props) {
  return (
    <div className={'FancyBorder FancyBorder-' + props.color}>
      {props.children}
    </div>
  );
}

這使得其他組件可以通過嵌套JSX傳遞任意子元素給他們:

function WelcomeDialog() {
  return (
    <FancyBorder color="blue">
      <h1 className="Dialog-title">
        Welcome
      </h1>
      <p className="Dialog-message">
        Thank you for visiting our spacecraft!
      </p>
    </FancyBorder>
  );
}

在CodePen上試一試
<FancyBorder>JSX標(biāo)簽中的所有東西都會作為childrenprop傳遞給FancyBorder組件。FancyBorder<div>中渲染{props.children},因此傳入的元素將出現(xiàn)在最終輸出中。
雖然這比較少見,但有時你還是會需要在組件中放置多個“槽位”。在這種情況下,你可以使用自己習(xí)慣來,來代替children

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 />
      } />
  );
}

在CodePen上試一試
諸如<Contacts /><Chat />的React元素也是對象,所以你可以像其他數(shù)據(jù)一樣作為props傳遞。

特殊化

有時你我們認(rèn)為一些組件是其他組件的“特殊情況”。比如,我們說WelcomeDialogDialog的特例。
在React中,這也可以通過組合來完成:通過props配置一個相對“通用的”組件,來渲染出一個相對“特殊的”組件:

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!" />
  );
}

在CodePen上試一試
組合對于定義成類的組件同樣好使:

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}!`);
  }
}

在CodePen上試一試

那繼承咋樣?

在Facebook,我們在數(shù)千個組件中使用React,尚未發(fā)現(xiàn)有什么組件,需要我們推薦你使用繼承去實現(xiàn)。
Props和組合提供了足夠的靈活度,使得你能夠以明確且安全的方法來自定義組件的外觀和行為。
如果你想在組件間復(fù)用非界面功能,我們建議將它抽取到單獨的JavaScript模塊。組件可以導(dǎo)入它,然后使用需要的函數(shù),對象或類,而不必擴(kuò)展(繼承)它。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 本筆記基于React官方文檔,當(dāng)前React版本號為15.4.0。 1. 安裝 1.1 嘗試 開始之前可以先去co...
    Awey閱讀 7,915評論 14 128
  • 最近看了一本關(guān)于學(xué)習(xí)方法論的書,強(qiáng)調(diào)了記筆記和堅持的重要性。這幾天也剛好在學(xué)習(xí)React,所以我打算每天堅持一篇R...
    gaoer1938閱讀 1,808評論 0 5
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,872評論 25 709
  • 撰文/風(fēng)云 1 最近參加了一個寫作培訓(xùn)班,老師每天都講寫作技巧,文章分析;學(xué)員們一篇又一篇文章在群里面的發(fā)布??墒?..
    風(fēng)云A閱讀 364評論 3 5
  • 前幾天我嬸嬸給我介紹了個對象,說是和我在同一個城市-深圳工作,離的近。 老家的一套三層的房子,但是還沒有裝修,因為...
    鄒小芝閱讀 742評論 0 0

友情鏈接更多精彩內(nèi)容