React 具有強大的 composition 模型,我們建議你在 component 之間使用 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 ,在元件標籤之間放入要加入元件的其他屬性或元件,去進行「包含」其他的元件。例如:
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')
);
如果有學過其他框架,可能可以對比 「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