React 高阶组件

                                               React  高阶组件

一.  高阶组件的意义

     1.  代码复用 : 高阶组件的基本功能,提取多个组件相似度高的部分,在通过高阶组件扩展。

     2.  条件渲染: 控制组件的渲染逻辑, 常见case:  鉴权

     3.  生命周期捕获/劫持: 借助父子组件生命周期规则捕获子组件的生命周期;

二. 高阶组件遵循的一些原则

     1.  不要修改原始组件

     2.  props保持一致

     3.  保持可组合性

     4.  displayName  为了方便调试,最常见的高阶组件命名方式是将子组件名字包裹起来。

     5.  不要render 方法内部使用高阶组件 (render中的高阶组件会在每次render时重新mount, 之前组件内部的state也会丢失) 

三. 使用方法对比

     高阶组件使用有几种不同的方式,可以从如下几个方面来分析他们之间的差异。

     一个React组件包含以下几个重要部分:

     · props    · state  · ref  ·生命周方法  ·static 方法  · React元素树

     注: 目前官方推荐ref属性接收一个回调函数,这个函数执行的时机为:

             1.  组件被挂载后,回调函数被立即执行,回调函数的参数为该组件的具体实例;

             2.  组件被卸载或者原有的ref属性本身发生变化时,回调也会被立即执行,此时回调函数参数为null, 以确保内存不泄露。

     所以不同方式的对比可以从以下几个方面进行(元组件即传入组件):

      1. 原组件所在位置: 如能否被包裹或包裹其它组件;

      2. 能否读取到或操作员组件的props;

      3. 能否读取,操作(编辑,删除)元组件的state;

      4. 能否通过ref访问到原组件中的dom元素;

      5. 是否影响原组件某些生命周期等方法;

      6. 是否取到原组件static方法;

       7. 能否劫持原组件生命周期方法;

       8. 能否渲染劫持;

四.  HOC  Demo举例

  如下代码定义了一个子组件及多个不同类型的HOC组件来测试,对子组件的内部属性,方法及状态等的访问情况。

/**
 * 高阶组件Demo
 */

 import React, { Component } from 'react'

 class HOCDemo extends Component{
   static sayHello() {
     console.log('hello from hocdemo static....')
   }

   constructor(props) {
     super(props)
     this.state={
       name: "HOC_DEMO",
       age: 66
     }
     console.log('HOCDemo Son constructor')
     this.focus = this.focus.bind(this)
   }

   componentWillMount(){
    console.log('HOCDemo Son componentWillMount')

    !!this.props.name && this.setState({
        age: this.props.age,
        name: this.props.name
    })
   }

   componentDidMount() {
    console.log('HOCDemo Son componentDidMount')
   }

   componentWillReceiveProps(nextProps) {
     console.log('HOCDemo Son componentWillReceiveProps')
     console.log(nextProps)
   }

   focus(){
     this.inputElement.focus()
   }

   render(){
    const outerStyle = {
      margin: "auto",
      text: "center"
    }
    const inputStyle = {
      border: 0,
      padding: '2px'
    }
    return (
      

姓名:{this.state.name}

年龄: {}} ref={(input) => { this.inputElement = input; !!this.props.inputRef && this.props.inputRef(input) }} />

) } } // HOC: // 父组件操作子组件里的input (父组件通过传回调函数给子组件,子组件通过该回调数将input给到父组件) const EnhanceWrapper = (WrappedComponent) => { let inputElement = null function handlerClick (){ inputElement.focus() } function wrappedComponentStaic(){ WrappedComponent.sayHello() } return props => (
{ inputElement = el}} {...props} />
) } /* HOC : 返回一个类 √ 原组件所在位置(能否被包裹或包裹其他组件) √ 能否取到或操作原组件的props 乄 能否取到或操作state 乄 能否通过ref访问到原组件中的dom元素 √ 是否影响原组件生命周期等方法 √ 是否取到原组件static方法 X  能否劫持原组件生命周期 乄 能否渲染劫持 */ const EnhanceWrapperClass = (WrappedComponent) => { return class WrapperComponent extends Component{ static wrappedComponentStaic(){ WrappedComponent.sayHello() } constructor(props) { super(props) console.log('wrappercomponent parent constructor') this.handleClick = this.handlerClick.bind(this) } componentWillMount(){ console.log('WrapperComponent parent componentWillMount') } componentDidMount(){ console.log('wrapperComponent parent componentDidMount') } handlerClick(){ this.inputElement.focus() } render(){ return (
{ this.inputElement = el}} {...this.props} />
) } } } /* HOC: 继承原组件后,返回一个新class component // 此种方式最大特点是允许 HOC 通过 this 访问到 WrappedComponent,所以可以读取和操作state/ref/生命周期方法 √ 原组件所在位置(能否被包裹或包裹其他组件) √ 能否取到或操作原组件的props √ 能否取到或操作state √ 能否通过ref访问到原组件中的dom元素 √ 是否影响原组件生命周期等方法 √ 是否取到原组件static方法 √ 能否劫持原组件生命周期 √ 能否渲染劫持 */ const EnhanceWrapperExtendSon = (WrappedComponent) => { return class WrapperComponent extends WrappedComponent { constructor(props){ super(props) console.log('WrapperComponent parent constructor') console.log("HOC parent this", this) } componentDidMount() { // 通过super可以调用继承类的内部方法 (这里不能用this 的原因是, 内部自己调用自己没有推出条件,造成死循环) super.componentDidMount() // 父类自己的DidMount 输出 console.log('WrapperComponent parent componentDidMount') } handlerClick(){ // 这里通过this 可以拿到所继承类的内部属性(inputElement)及方法 this.inputElement.focus() } render(){ return (
{super.render()}

姓名: {this.state.name}

) } } } const WrapperComponent = EnhanceWrapperExtendSon(HOCDemo) export default WrapperComponent

五.  现实应用场景实战

 

 

 

 

 

未完待续.....

你可能感兴趣的:(ReactJS)