在用 React 的時(shí)候,很容易遇到兩個(gè)不同的組件之間有很多的共用代碼。目前的項(xiàng)目是當(dāng)時(shí)趕鴨子上架用的 React,很多的做法是復(fù)制組件 A 的代碼為組件 B,然后全局搜索替換。這樣的做法非常 low,可維護(hù)性非常差,也是非常不負(fù)責(zé)任的。。。
所幸這段時(shí)間比較有空,所以想趕緊把之前挖的坑給填上。由于目前整個(gè)項(xiàng)目都是用 ES6,第一步很自然的想到用繼承的方式來復(fù)用代碼。然而事實(shí)是嚴(yán)峻的,項(xiàng)目中多半的組件是像下面這樣
// A.jsx
class A extends React.Component {
handleAdd () {
// 共用代碼
....
// 特定代碼
addXXA()
}
}
// B.jsx
class B extends React.Component {
handleAdd () {
// 共用代碼
....
// 特定代碼
addXXB()
}
}
最開始提到的搜索替換,大部分就是在改這些特定代碼。也是因?yàn)檫@樣的代碼,在項(xiàng)目最先開始的時(shí)候,想不到比較好的復(fù)用方式。當(dāng)然這個(gè)問題在 React 社區(qū)也是比較常見的,所以搜了下谷歌,很快就能發(fā)現(xiàn)一個(gè)叫 mixin 的方案。
然而上天在給你開了一扇窗時(shí),會(huì)把門給你關(guān)上!React 已經(jīng)宣布 ES6 不支持 mixin ,而且官方還說了目前這種情況沒有其它替代方案。。。
沒有替代方案,你還鼓勵(lì)大家用 ES6,而且我特么還信了!劇情到了這個(gè)時(shí)候,一般都會(huì)有個(gè)救世主出現(xiàn)。一個(gè) React 核心團(tuán)隊(duì)的成員在 gist 上面放出了一段代碼 ,取名為 Higher Order Component,嗯,挺帥氣的。
為了表示這個(gè)并不是 React 官方的意見,你直接復(fù)制粘貼這段代碼就會(huì)發(fā)現(xiàn),根本就運(yùn)行不了。
運(yùn)行不了,你放上去干嘛。。。不過仔細(xì)看這段代碼,你就會(huì)發(fā)現(xiàn)都是小問題。那段 gist 下面有很多網(wǎng)友的評(píng)論,四六級(jí)沒過的可以當(dāng)做練練閱讀理解。怕有些人真的沒辦法改這段代碼,React 社區(qū)的一個(gè)大神 Dan 也給出了解決方法。當(dāng)然別問我為什么知道真的能解決!
Higher Order Component 的中文名稱叫高階組件(怎么有股濃濃的高數(shù)味)。后來才發(fā)現(xiàn),這個(gè)是借鑒于 Higher Order Function (高階函數(shù)),還以為外國(guó)銀都這么會(huì)取名字。
看下維基百科上面對(duì)于 Higher Order Function 的定義
A higher-order function is a function that does at least one of the following:
- takes one or more functions as arguments
- returns a function as its result
所以對(duì)應(yīng)的,Higher Order Component 的定義就是
一個(gè)函數(shù),接收一個(gè)或多個(gè)組件作為參數(shù),返回新的組件。
現(xiàn)在就用 Higher Order Component 來改下文章最開始的代碼。
// Enhance.js
export const Enhance = (ComposedComponent, handleAdd) => class extends Component {
handleAdd () {
// 共用代碼
...
// 特定代碼
handleAdd()
}
render () {
return (
<ComposedComponent
{...this.props}
handleAdd={this.handleAdd}
/>
)
}
}
// A.jsx
class A extends React.Component {
}
export default Enhance(A, addXXA)
// B.jsx
class B extends React.Component {
}
export default Enhance(B, addXXB)
嗯,看起來還不錯(cuò),可以比較優(yōu)雅地解決代碼復(fù)用的問題。用 Higher Order Component 還可以解決 React 生命周期的問題,更詳細(xì)的用法可以參考
英文好的可以看下這篇
這篇文章原本打算好好寫下 Higher Order Component 的用法,沒想到寫了一半畫風(fēng)突變。好吧,只能寫成科普文,順便給大家娛樂娛樂,不過還是希望能給遇到這個(gè)問題的人帶來幫助。