ReactNative进阶篇-高阶组件

作者: Fat_L | 来源:发表于2021-04-11 19:45 被阅读0次

    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 高阶组件

    相关文章

      网友评论

        本文标题:ReactNative进阶篇-高阶组件

        本文链接:https://www.haomeiwen.com/subject/lvzauctx.html