iT邦幫忙

2021 iThome 鐵人賽

DAY 13
0
自我挑戰組

React 學習之路系列 第 13

Composition vs 繼承( Day13 )

  • 分享至 

  • xImage
  •  

React 具有強大的 composition 模型,我們建議你在 component 之間使用 composition 來複用你的程式碼,而不是使用繼承。

什麼是 composition 模型? 為什麼跟繼承去比較?

理解 composition 之前我先去找了我知道的繼承的概念,以下 wiki

繼承(英語:inheritance)是物件導向軟體技術當中的一個概念。如果一個類別B「繼承自」另一個類別A,就把這個B稱為「A的子類」,而把A稱為「B的父類別別」也可以稱「A是B的超類」。繼承可以使得子類具有父類別別的各種屬性和方法,而不需要再次編寫相同的代碼。

那 composition 呢? 參考 Eric Elliott 在 Master the JavaScript Interview: What is Function Composition? 裡面有提到的,

Function composition is the process of combining two or more functions to produce a new function. Composing functions together is like snapping together a series of pipes for our data to flow through.

所以如果是元件的 composition 是移植同樣的概念,那意思就是通常元件可以是由兩到更多個元件組合而成的新元件。或藉由小的元件拼湊而成,具有彈性的大元件。而繼承反倒是從某一個大元件中承接需要的功能,需要時再加以修改新增需要的部分。繼承跟composition 兩種模型間理解起來有種微妙但巨大的差異。

(示意圖)

props.children 與 props[特定元件]

我們可以使用 props.children ,在元件標籤之間放入要加入元件的其他屬性或元件,去進行「包含」其他的元件。例如:

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

但 props.children 只有單一個挖空可以塞入,當你需要多個挖空的時候可以回到使用 props 的方法,將需要的元件向下傳入進行組合。以下示範塞入多個元件,一間教室老師跟學生分別不同位置。

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

function Student() {
  const studentList = ['小明', '小王', '小美']
  return (
    <ul>
      { studentList.map((student)=>{
        return <li key={student} >{ student }</li>
      })
      }
    </ul>
  )
}

function Teacher() {
  return <h1>我是老師</h1>
}

function WelcomeDialog() {
  return (
    <Classroom teacher={<Teacher />} color="blue">
      <Student />
    </Classroom>
  );
}

ReactDOM.render(
  <WelcomeDialog />,
  document.getElementById('root')
);

codepen

包含與特別化

如果有學過其他框架,可能可以對比 「slot」的概念,但差別是塞入多元件的作法不同。React 並沒有限制 props 傳遞的內容,所以有像是 props function 或 component 的作法。

另,在實現 composition 的做法中,如果要將「通用」的元件,加入客製的功能 (有點繼承的感覺),一樣可以使用 prop 對其進行設定。

function Classroom(props) {
  return (
    <div className={'Classroom Classroom-' + props.color}>
      {props.classroomName ? <h2>{props.classroomName}</h2> : ''}
      {props.teacher}
      {props.children}
    </div>
  );
}

function Student(props) {
  //略
}

function Teacher() {
  //略
}

function WelcomeDialog() {
  return (
      //例如課程名稱可以設定,如有增加就可以顯示
    <Classroom classroomName="[[ 電腦課 ]]" teacher={<Teacher />} color="blue">
      //略
    </Classroom>
  );
}

ReactDOM.render(
  //略
);

注意:
如果想要在 component 間複用非 UI 的功能,通常會再抽出一個 JavaScript 模組(.js 檔)。元件可以 import 後使用 function、object,或者是 class。

以上今天

參考資料:
https://zh-hant.reactjs.org/docs/composition-vs-inheritance.html
https://medium.com/javascript-scene/master-the-javascript-interview-what-is-function-composition-20dfb109a1a0


上一篇
提升 State ( Day12 )
下一篇
學習 Hook( Day14 )
系列文
React 學習之路30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言