简介
高阶组件的概念应该是来源于JavaScript的高阶函数:高阶函数就是接受函数作为输入或者输出的函数。而高阶组件就仅仅是一个接受组件作为输入并返回组件的函数。通常实现高阶组件的方式有两种
- 属性代理
- 反向继承
属性代理
属性代理是通过包裹原来的组件来操作props
,举个栗子
import React, { Component } from 'React'; //高阶组件定义 const HOC = (WrappedComponent) => class HOC extends Component { render() { return <WrappedComponent {...this.props} />; } } //普通的组件 class WrappedComponent extends Component{ render(){ //.... } } //高阶组件使用 export default HOC(WrappedComponent)
操作props
要传递给WrappedComponent的props先被传递给了HOC,这样HOC就拿到了props的控制权,这也是为什么这种方法叫做属性代理。根据需要,可以对传入的props进行增加,删除,修改。举个栗子
const HOC = (WrappedComponent) => class HOC extends Component { render() { const newProps = { name: 'HOC' } return <WrappedComponent {...this.props} {...newProps} />; } }
抽象state
在属性代理的情况下,我们可以将被包裹组件的状态提升到HOC中,一个用法是可以把非受控组件转变成受控组件
class WrappedComponent extends Component { render() { return <input name="name" {...this.props.name} />; } } const HOC = (WrappedComponent) => class HOC extends 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} />; } }
反向继承
反向继承是指返回的组件去继承之前的组件,即上述的(WrappedComponent)
const HOC = WrappedComponent=>{ class HOC extends WrappedComponent{ render(){ return super.render(); } } }
返回的组件继承自WrappedComponent,那么所有的调用将是反向调用(例如:super.render())
渲染劫持
我们可以有意识地控制WrappedComponent的渲染进程,从而控制渲染的结果。例如可以根据参数去决定是否渲染组件
const HOC = (WrappedComponent) => class extends WrappedComponent { render() { if (this.props.isRender) { return super.render(); } else { return null; } } }