大話 Higher Order Component

在用 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è)問題的人帶來幫助。

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

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

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