高阶组件Higher Order Component

高阶组件(HOC)是React开发中的特有名词,一个函数返回一个React组件,指的就是一个React组包裹着另一个React组件。可以理解为一个生产React组件的工厂。

有两种类型的HOC:

  1. Props Proxy(pp) HOC对被包裹组件WrappedComponent的props进行操作。
  2. Inherbitance Inversion(ii)HOC继承被包裹组件WrappedComponent

Props Proxy

一种最简单的Props Proxy实现

function ppHOC(WrappedComponent) {  
  return class PP extends React.Component {    
    render() {      
      return <WrappedComponent {...this.props}/>    
    }  
  } 
}

这里的HOC是一个方法,接受一个WrappedComponent作为方法的参数,返回一个PP class,renderWrappedComponent。使用的时候:

const ListHOCInstance = ppHOC(List)
<ListHOCInstance name='instance' type='hoc' />

这个例子中,我们将本应该传给List的props,传给了ppHoc返回的ListHOCInstance(PP)上,在HOC内部我们将PP的参数直接传给ListWrappedComponent)。这样的就相当于在List外面加了一层代理,这个代理用于处理即将传给WrappedComponent的props,这也是这种HOC为什么叫Props Proxy。

在pp中,我们可以对WrappedComponent进行以下操作:

  1. 操作props(增删改)
  2. 通过refs访问到组件实例
  3. 提取state
  4. 用其他元素包裹WrappedComponent

操作props

比如添加新的props给WrappedComponent

const isLogin = false;

function ppHOC(WrappedComponent) {
  return class PP extends React.Component {
    render() {
      const newProps = {
        isNew: true,login: isLogin
      }
      return <WrappedComponent {...this.props} {...newProps}/>
    }
  }
}

WrappedComponent组件新增了两个props:isNew和login。

通过refs访问到组件实例

function refsHOC(WrappedComponent) {
  return class RefsHOC extends React.Component {
    proc(wrappedComponentInstance) {
      wrappedComponentInstance.method()
    }

    render() {
      const props = Object.assign({},this.props,{ref: this.proc.bind(this)})
      return <WrappedComponent {...props}/>
    }
  }
}

Ref 的回调函数会在 WrappedComponent 渲染时执行,你就可以得到WrappedComponent的引用。这可以用来读取/添加实例的 props ,调用实例的方法

不过这里有个问题,如果WrappedComponent是个无状态组件,则在proc中的wrappedComponentInstance是null,因为无状态组件没有this,不支持ref。

提取state

你可以通过传入 props 和回调函数把 state 提取出来,

function ppHOC(WrappedComponent) {
  return class PP extends React.Component {
    constructor(props) {
      super(props)
      this.state = {
        name: ''
      }

      this.onNameChange = this.onNameChange.bind(this)
    }
    onNameChange(event) {
      this.setState({
        name: event.target.value
      })
    }
    render() {
      const newProps = {
        name: {
          value: this.state.name,onChange: this.onNameChange
        }
      }
      return <WrappedComponent {...this.props} {...newProps}/>
    }
  }
}

使用的时候:

class Test extends React.Component {
    render () {
        return (
            <input name="name" {...this.props.name}/>
        );
    }
}

export default ppHOC(Test);

这样的话,就可以实现将input转化成受控组件。

用其他元素包裹 WrappedComponent

这个比较好理解,就是将WrappedComponent组件外面包一层需要的嵌套结构

function ppHOC(WrappedComponent) {
  return class PP extends React.Component {
    render() {
      return (
        <div style={{display: 'block'}}>
          <WrappedComponent {...this.props}/>
        </div>
      )
    }
  }
}

Inheritance Inversion(反向继承)

先看一个反向继承(ii)的

相关文章

一、前言 在组件方面react和Vue一样的,核心思想玩的就是组件...
前言: 前段时间学习完react后,刚好就接到公司一个react项目...
前言: 最近收到组长通知我们项目组后面新开的项目准备统一技...
react 中的高阶组件主要是对于 hooks 之前的类组件来说的,如...
我们上一节了解了组件的更新机制,但是只是停留在表层上,例...
我们上一节了解了 react 的虚拟 dom 的格式,如何把虚拟 dom...