ReactNative進(jìn)階篇-高階組件

1. 概念

很多情況下冰木,需要給多個(gè)組件添加或者修改一些特定的props柬甥,或者在所有組件基礎(chǔ)上加個(gè)水印等等灶轰。而如果這個(gè)功能如果是針對(duì)多個(gè)組件的噪奄,每一個(gè)組件都寫(xiě)一套相同的代碼死姚,顯得不是很明智,所以就可以考慮使用高階組件勤篮。

ReactNative的高階組件也叫HOC(全稱Higher-order component)都毒,構(gòu)建方式主要有屬性代理反向繼承。主要用于:

  • 組件代碼復(fù)用碰缔,代碼模塊化
  • 增刪改props
  • 渲染劫持
  • ……

所以高階組件經(jīng)常作為一個(gè)函數(shù)账劲,且該函數(shù)接受一個(gè)組件作為參數(shù),并返回一個(gè)新的組件。

2. 使用

2.1 組件代碼復(fù)用涤垫,代碼模塊化

下面是一個(gè)簡(jiǎn)單的高階組件姑尺,給傳進(jìn)去的組件前面加了一個(gè)固定的Text組件。

# 定義
export const HocComponent = (param) => (WrappedComponent) => {
    class NewComponent extends React.Component {
        render() {
            return(
                <View>
                     <Text>我是高階組件,傳進(jìn)來(lái)參數(shù)是:{JSON.stringify(param)}</Text>
                    <WrappedComponent {...this.props}/>
                </View>
            )
        }
    }
    return NewComponent
}

HocComponent 是一個(gè)函數(shù)蝠猬,param是需要傳入組件的參數(shù)切蟋,WrappedComponent是傳入的組件,NewComponent就是傳入?yún)?shù)后生成的新的組件榆芦。
使用方式推薦用裝飾器語(yǔ)法柄粹, 如下圖就可以給TestComp和TestComp2組件傳入?yún)?shù)都加上一個(gè)Text組件。

# 裝飾器調(diào)用
@HocComponent({name:'zhangsan'})
export class TestComp extends React.Component<IProps> {
    ...
}

# 裝飾器調(diào)用
@HocComponent({name:'lisi'})
export class TestComp2 extends React.Component<IProps> {
    ...
}

# 函數(shù)調(diào)用 ( HocComponent改成返回<NewComponent/>)
const TestComp = HocComponent({name:'zhangsan'})(TestComp )
2.2 增刪改Props

也可以在基礎(chǔ)上加入特定props匆绣,例如在高階組件內(nèi)部自定義一個(gè)顏色主題themeType,這樣就可以在新返回的組件通過(guò)this.props.themeType獲取當(dāng)前的顏色主題驻右。

export default (Comp)=>{
    class newCom extends React.Component{
        const newProps = {
          ...this.props,
          themeType:'dark'
        }
        render() {
            return <Comp {...newProps}/>
        }
    }
    return newCom
}
2.3 渲染劫持

在render方法里控制顯示渲染邏輯,下面是一個(gè)例子崎淳。
當(dāng)屬性this.props.loading為true時(shí)顯示加載組件堪夭,當(dāng)屬性this.props.data數(shù)據(jù)為空時(shí)顯示空白組件,正常則直接顯示渲染傳入的<Comp/>組件拣凹。

const HocComponent = (WrappedComponent)=>{
    newComp extends WrappedComponent {
        render(){
          if(this.props.loading){
            return <View><Text>加載中</Text></View>
          }
          if(this.props.data.length>0){
            return <View><Text>暫無(wú)數(shù)據(jù)</Text></View>
          }
         return super.render();
        }
    }
   return newComp 
}

需要注意的是:

  • 普通組件的 static方法怎么傳入高階組件內(nèi)部?

當(dāng)使用高階組件包裝組件森爽,原始組件被容器組件包裹,也就意味著新組件會(huì)丟失原始組件的所有靜態(tài)方法嚣镜。解決這個(gè)問(wèn)題的方法就是爬迟,將原始組件的所有靜態(tài)方法全部拷貝給新組件:

# 普通組件內(nèi)部定義了 static 方法
 static ABC(){
        return 'abc'
    }

# 高階組件內(nèi)部
NewComponent.ABC = WrappedComponent.ABC

3. 屬性代理與反向繼承

對(duì)于函數(shù)內(nèi)部高階組件的生成主要由以下兩種:

  • 屬性代理:高階組件通過(guò)包裹傳進(jìn)來(lái)React組件進(jìn)行操作;
  • 反向繼承:高階組件繼承于被包裹的React組件進(jìn)行操作菊匿。
    上面所說(shuō)的(1)(2)主要是屬性代理的使用方式付呕,(3)反向繼承的案例,下面是反向繼承的詳細(xì)案例跌捆。
const HocComponent = (WrappedComponent)=>{
   newComp extends WrappedComponent {
      // 此處重寫(xiě)了父類的方法父類就不會(huì)再執(zhí)行 componentDidMount()
      componentDidMount() {
           console.log('1')
           // 修改父類的 state
           this.setState({
               result: '通過(guò)高階組件(反向繼承方式)創(chuàng)建的組件'
           })
       }
       render(){
           return super.render();
       }
   }
  return newComp 
}

屬性代理和反向繼承主要的區(qū)別是

  • 屬性代理:靈活操作組件的props徽职,如上述的增刪改props,再把props傳給組件。
  • 反向繼承:攔截生命周期佩厚、state活箕、渲染過(guò)程。因?yàn)槔^承了傳進(jìn)來(lái)的組件可款,如果新組件寫(xiě)了componentDidMount等方法,會(huì)覆蓋掉原方法;也可以在外部組件調(diào)用被繼承組件的方法克蚂,如super.render();

4. 總結(jié)

這篇文章主要講解了HOC的概念和使用思路闺鲸,需要注意的是,在創(chuàng)建HOC的過(guò)程中盡量不要改變?cè)冀M件埃叭,而是使用組合的方式摸恍。HOC的實(shí)際使用場(chǎng)景要比現(xiàn)在講的還要多,例如頁(yè)面權(quán)限管理、數(shù)據(jù)組裝關(guān)聯(lián)立镶、監(jiān)控日志打印壁袄、埋點(diǎn)上報(bào)等等,靈活運(yùn)用好HOC能夠?qū)N的架構(gòu)邏輯起到很好的幫助與擴(kuò)展媚媒。

參考

React高階組件中文文檔
React Native高階組件(HOC)模型理論與實(shí)踐
React-Native 高階組件

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末嗜逻,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子缭召,更是在濱河造成了極大的恐慌栈顷,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,602評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嵌巷,死亡現(xiàn)場(chǎng)離奇詭異萄凤,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)搪哪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)靡努,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人晓折,你說(shuō)我怎么就攤上這事惑朦。” “怎么了已维?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,878評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵行嗤,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我垛耳,道長(zhǎng)栅屏,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,306評(píng)論 1 279
  • 正文 為了忘掉前任堂鲜,我火速辦了婚禮栈雳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘缔莲。我一直安慰自己哥纫,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,330評(píng)論 5 373
  • 文/花漫 我一把揭開(kāi)白布痴奏。 她就那樣靜靜地躺著蛀骇,像睡著了一般。 火紅的嫁衣襯著肌膚如雪读拆。 梳的紋絲不亂的頭發(fā)上擅憔,一...
    開(kāi)封第一講書(shū)人閱讀 49,071評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音檐晕,去河邊找鬼暑诸。 笑死蚌讼,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的个榕。 我是一名探鬼主播篡石,決...
    沈念sama閱讀 38,382評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼西采!你這毒婦竟也來(lái)了凰萨?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,006評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤苛让,失蹤者是張志新(化名)和其女友劉穎沟蔑,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體狱杰,經(jīng)...
    沈念sama閱讀 43,512評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡瘦材,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,965評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了仿畸。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片食棕。...
    茶點(diǎn)故事閱讀 38,094評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖错沽,靈堂內(nèi)的尸體忽然破棺而出簿晓,到底是詐尸還是另有隱情,我是刑警寧澤千埃,帶...
    沈念sama閱讀 33,732評(píng)論 4 323
  • 正文 年R本政府宣布憔儿,位于F島的核電站,受9級(jí)特大地震影響放可,放射性物質(zhì)發(fā)生泄漏谒臼。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,283評(píng)論 3 307
  • 文/蒙蒙 一耀里、第九天 我趴在偏房一處隱蔽的房頂上張望蜈缤。 院中可真熱鬧,春花似錦冯挎、人聲如沸底哥。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,286評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)趾徽。三九已至,卻和暖如春翰守,著一層夾襖步出監(jiān)牢的瞬間孵奶,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,512評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工潦俺, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,536評(píng)論 2 354
  • 正文 我出身青樓事示,卻偏偏與公主長(zhǎng)得像早像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子肖爵,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,828評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容