React高阶组件

React高阶组件概述

  • 高阶组件是React中一个很重要且比较复杂的概念,高阶组件在很多第三方库(如Redux)中都被经常使用,在项目中用好高阶组件,可以显著提高代码质量。

高阶函数的基本概念

  • 函数可以作为参数被传递
setTimeout(() => {
    console.log('1')
  }, 1000)

  • 函数可以作为返回值输出
   foo = (x) => {
    return function () {
      return x
    }
  }

高阶组件的基本概念

  • 高阶组件就是接受一个组件作为参数并返回一个新组件的函数。
  • 高阶组件是一个函数,并不是组件。

为什么需要高阶组件?

  • 多个组件都需要某个相同功能,使用高阶组件减少重复实现。
  • 重复是优秀系统设计的大敌
  • 高阶组件示例: react-redux 中的connect
export default connect(maoStateToProps, mapDispatchToProps)(Header)

高阶组件的实现

编写高阶组件

使用方法一:

  • 实现一个普通组件
import React from 'react'

export default class Start extends React.Component {
  render () {
    return (
      <div>组件A</div>
    )
  }
}
  • 将普通组件使用函数包裹起来
import React from 'react'

function A (WrappedComponent) {
  return class Start extends React.Component {
    render () {
      return (
        <div>
          <div>这是组件A</div>
          <WrappedComponent />
        </div>
      )
    }
  }
}

export default A
  • 使用高阶组件
import React from 'react'
import a from './A'

class B extends React.Component {
  render () {
    return (
      <div>这是组件B</div>
    )
  }
}

export default a(B)

使用方法二:类装饰器

import React from 'react'
import a from './A'
@a
class B extends React.Component {
  render () {
    return (
      <div>这是组件B-</div>
    )
  }
}

export default B

高阶组件应用

代理方式的高阶组件

返回的新组件类直接继承React.Component 类,新组件扮演的角色传入参数组件的一个代理,在新组件的render函数中,被包裹组件渲染出来,除了高阶组件自己要做得工作,其余功能全都转手给了被包裹的组件。

  • 操作props
    高阶组件能改变包裹组件的props,可以做任何的读取、编辑、删除props的一系列操作,甚至可以在高阶组件中自定义事件,然后通过props传递下去。
// A.js
import React from 'react'

function A (WrappedComponent) {
  return class Start extends React.Component {
    render () {
      return (
        <div>
          <div>这是组件A</div>
          {this.props.name}
          <WrappedComponent {...this.props} age="18" />
        </div>
      )
    }
  }
}

export default A

// B.js
import React from 'react'
import a from './A'

@a
class B extends React.Component {
  render () {
    return (
      <div>
        <div>这是组件B:</div>
        <p>我的名字叫:{this.props.name}</p>
        <p>我的年龄是:{this.props.age}</p>
      </div>
    )
  }
}

export default B

// C.js
import React from 'react'

class C extends React.Component {
  render () {
    return (
      <div>组件C</div>
    )
  }
}

export default C

// D.js
import React from 'react'
import A from './A'
import B from './B'
import C from './C'

class D extends React.Component {
  render () {
    return (
      <div>
        <A />
        <B name='张三' />
        <C />
        <div>这是组件D</div>
      </div>
    )
  }
}

export default D
  • 访问ref
    ref可以自由的操作被包裹组件的元素
    注意:(ref属性非常容易出问题,不推荐使用)
// A.js
import React from 'react'

function A (WrappedComponent) {
  return class Start extends React.Component {
    refTest (instance) {
      instance.getName && alert(instance.getName())
    }
    render () {
      const { age, ...otherProps } = this.props
      return (
        <div>
          <div>这是组件A:</div>
          {this.props.name}
          <WrappedComponent {...otherProps} sex='A组件' ref={this.refTest.bind(this)} />
        </div>
      )
    }
  }
}

export default A
// C.js
import React from 'react'
import a from './A'

@a
class C extends React.Component {
  getName () {
    return '我是C组件'
  }
  render () {
    return (
      <div>组件C</div>
    )
  }
}

export default C
  • 抽取状态
// A.js
import React from 'react'

function A (WrappedComponent) {
  return class Start extends React.Component {
    state = { value: '' }
    inputHandle = (e) => {
      let value = e.target.value
      this.setState({ value })
    }
    render () {
      const newProps = {
        value: this.state.value,
        onInput: this.inputHandle
      }
      return (
        <div>
          <div>这是组件A:{this.state.value}</div>
          <WrappedComponent  {...newProps} />
        </div>
      )
    }
  }
}

export default A
// B.js
import React from 'react'
import a from './A'

@a
class B extends React.Component {

  render () {
    return (
      <div>
        <div>这是组件B:{this.props.value}</div>
        <input  {...this.props} />
      </div>
    )
  }
}

export default B
  • 包装组件

继承方式的高阶组件

  • 采用继承关联作为参数的组件和返回的组件,假如传入的组件参数是WrappedComponent,那么返回的组件就直接继承自WrappedComponent
export default () => WrappedComponent => class A extends WrappedComponent {
  render () {
    const { user, otherProps } = this.props
    this.props = otherProps
    return super.render()
  }
}
  • 操纵porps

  • 操纵 生命周期函数

高阶组件显示名

原文地址:https://www.cnblogs.com/liea/p/11823740.html