ReactNative进阶篇-高阶组件

1. 概念

很多情况下,需要给多个组件添加或者修改一些特定的props,或者在所有组件基础上加个水印等等。而如果这个功能如果是针对多个组件的,每一个组件都写一套相同的代码,显得不是很明智,所以就可以考虑使用高阶组件。

ReactNative的高阶组件也叫HOC(全称Higher-order component),构建方式主要有属性代理反向继承。主要用于:

  • 组件代码复用,代码模块化
  • 增删改props
  • 渲染劫持
  • ……

所以高阶组件经常作为一个函数,且该函数接受一个组件作为参数,并返回一个新的组件。

2. 使用

2.1 组件代码复用,代码模块化

下面是一个简单的高阶组件,给传进去的组件前面加了一个固定的Text组件。

# 定义
export const HocComponent = (param) => (WrappedComponent) => {
    class NewComponent extends React.Component {
        render() {
            return(
                <View>
                     <Text>我是高阶组件,传进来参数是:{JSON.stringify(param)}</Text>
                    <WrappedComponent {...this.props}/>
                </View>
            )
        }
    }
    return NewComponent
}

HocComponent 是一个函数,param是需要传入组件的参数,WrappedComponent是传入的组件,NewComponent就是传入参数后生成的新的组件。
使用方式推荐用装饰器语法, 如下图就可以给TestComp和TestComp2组件传入参数都加上一个Text组件。

# 装饰器调用
@HocComponent({name:'zhangsan'})
export class TestComp extends React.Component<IProps> {
    ...
}

# 装饰器调用
@HocComponent({name:'lisi'})
export class TestComp2 extends React.Component<IProps> {
    ...
}

# 函数调用 ( HocComponent改成返回<NewComponent/>)
const TestComp = HocComponent({name:'zhangsan'})(TestComp )
2.2 增删改Props

也可以在基础上加入特定props,例如在高阶组件内部自定义一个颜色主题themeType,这样就可以在新返回的组件通过this.props.themeType获取当前的颜色主题。

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

在render方法里控制显示渲染逻辑,下面是一个例子。
当属性this.props.loading为true时显示加载组件,当属性this.props.data数据为空时显示空白组件,正常则直接显示渲染传入的<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>暂无数据</Text></View>
          }
         return super.render();
        }
    }
   return newComp 
}

需要注意的是:

  • 普通组件的 static方法怎么传入高阶组件内部?

当使用高阶组件包装组件,原始组件被容器组件包裹,也就意味着新组件会丢失原始组件的所有静态方法。解决这个问题的方法就是,将原始组件的所有静态方法全部拷贝给新组件:

# 普通组件内部定义了 static 方法
 static ABC(){
        return 'abc'
    }

# 高阶组件内部
NewComponent.ABC = WrappedComponent.ABC

3. 属性代理与反向继承

对于函数内部高阶组件的生成主要由以下两种:

  • 属性代理:高阶组件通过包裹传进来React组件进行操作;
  • 反向继承:高阶组件继承于被包裹的React组件进行操作。
    上面所说的(1)(2)主要是属性代理的使用方式,(3)反向继承的案例,下面是反向继承的详细案例。
const HocComponent = (WrappedComponent)=>{
   newComp extends WrappedComponent {
      // 此处重写了父类的方法父类就不会再执行 componentDidMount()
      componentDidMount() {
           console.log('1')
           // 修改父类的 state
           this.setState({
               result: '通过高阶组件(反向继承方式)创建的组件'
           })
       }
       render(){
           return super.render();
       }
   }
  return newComp 
}

属性代理和反向继承主要的区别是

  • 属性代理:灵活操作组件的props,如上述的增删改props,再把props传给组件。
  • 反向继承:拦截生命周期、state、渲染过程。因为继承了传进来的组件,如果新组件写了componentDidMount等方法,会覆盖掉原方法;也可以在外部组件调用被继承组件的方法,如super.render();

4. 总结

这篇文章主要讲解了HOC的概念和使用思路,需要注意的是,在创建HOC的过程中尽量不要改变原始组件,而是使用组合的方式。HOC的实际使用场景要比现在讲的还要多,例如页面权限管理、数据组装关联、监控日志打印、埋点上报等等,灵活运用好HOC能够对RN的架构逻辑起到很好的帮助与扩展。

参考

React高阶组件中文文档
React Native高阶组件(HOC)模型理论与实践
React-Native 高阶组件

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容