React.js的組合 VS 繼承(八)

React 擁有一個強大的組合模型,我們建議使用組合而不是繼承以實現(xiàn)代碼的重用。

在本節(jié)中,我們將考慮幾個問題,即 React 新手經(jīng)常會使用繼承,并展示我們?nèi)绾瓮ㄟ^組合來解決它們。

包含

一些組件在設計前無法獲知自己要使用什么子組件,尤其在 Sidebar 和 Dialog 等通用 “容器” 中比較常見。

我們建議這種組件使用特別的 children prop 來直接傳遞 子元素到他們的輸出中:

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

在 <FancyBorder> JSX 標簽中的任何內(nèi)容被傳遞到 FancyBorder 組件中,作為一個 children prop(屬性)。由于 FancyBorder 渲染 {props.children} 到一個 <div> 中,傳遞的元素會呈現(xiàn)在最終的輸出中。

然而這并不常見,有時候,在一個組件中你可能需要多個 “占位符” 。在這種情況下,你可以使用自定義的 prop(屬性),而不是使用 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 />
      } />
  );
}

如 <Contacts /> 和 <Chat /> 等 React 元素本質(zhì)上也是對象,所以可以將其像其他數(shù)據(jù)一樣作為 props(屬性) 傳遞使用。

特例

有時候,我們考慮組件作為其它組件的“特殊情況”。例如,我們可能說一個 WelcomeDialog 是 Dialog 的一個特殊用例。

在React中,也可以使用組合來實現(xiàn),一個偏“特殊”的組件渲染出一個偏“通用”的組件,通過 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!" />

  );
}

對于用類定義的組件組合也同樣適用:

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,我們還沒有發(fā)現(xiàn)任何用例,值得我們建議你用繼承層次結構來創(chuàng)建組件。

使用 props(屬性) 和 組合已經(jīng)足夠靈活來明確、安全的定制一個組件的外觀和行為。

切記,組件可以接受任意的 props(屬性) ,包括原始值、React 元素,或者函數(shù)。

如果要在組件之間重用非 UI 功能,我們建議將其提取到單獨的JavaScript 模塊中。組件可以導入它并使用該函數(shù),對象或類,而不擴展它。

參考:

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

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

  • 學習如何在Flow中使用React 將Flow類型添加到React組件后,F(xiàn)low將靜態(tài)地確保你按照組件被設計的方...
    vincent_z閱讀 6,560評論 4 21
  • It's a common pattern in React to wrap a component in an ...
    jplyue閱讀 3,411評論 0 2
  • 3. JSX JSX是對JavaScript語言的一個擴展語法, 用于生產(chǎn)React“元素”,建議在描述UI的時候...
    pixels閱讀 2,983評論 0 24
  • 最近看了一本關于學習方法論的書,強調(diào)了記筆記和堅持的重要性。這幾天也剛好在學習React,所以我打算每天堅持一篇R...
    gaoer1938閱讀 1,819評論 0 5
  • GUIDS 第一章 為什么使用React? React 一個提供了用戶接口的JavaScript庫。 誕生于Fac...
    jplyue閱讀 3,723評論 1 11

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