美文网首页
React 高阶组件

React 高阶组件

作者: 爱吃豆包 | 来源:发表于2019-11-21 14:59 被阅读0次

    当 React 组件被包裹时(wrapped),高阶组件会返回一个增强(enhanced)的 React 组件。高阶组件让我们的代码更具有复用性、逻辑性与抽象特性。
    它可以对 render 方法作劫持,也可以控制 props 与 state

    实现高阶组件的方法有如下两种。

    属性代理(props proxy)。高阶组件通过被包裹的 React 组件来操作 props。
    1.控制 props :查询/添加/修改 props
    2.通过 refs 使用引用:可以调用组件的实例方法,查询/添加/修改 props
    3.抽象 state:抽象 state ,进行统一管理

    反向继承(inheritance inversion)。高阶组件继承于被包裹的 React 组件。
    (反向继承,我用的不多。。。)

    属性代理

    1.控制 props

    编写一个高阶组件

    import React, { Component } from 'react'
    
    /**
     * 高阶组件 装饰器模式
     * 
     *      装饰传递进来的组件
     * 
     * @param {*} WrappedComponent 
     */
    const MyComtainer = (WrappedComponent) => {
      return class extends Component {
        
        render() {
    
            // 这里代理传递进来的组件,代理 props  (属性代理)
    
            // 第一种写法
            // const { name, ...oldProps } = this.props
            // const newProps = { ...oldProps, name: '装饰'  }
            // return <WrappedComponent { ...newProps } />
    
            // 第二种写法
            const newPropsName = { name: "装饰器" }
            return <WrappedComponent { ...this.props } { ...newPropsName } />
        }
    
      }
    
    }
    
    export default MyComtainer
    
    

    被代理的组件

    import React, { Component } from 'react'
    import MyComtainer from './MyContainer';
    
    // @MyComtainer
    class MyCompoent extends Component {
    
        render() {
          return <div>{this.props.name || '没有值'}</div>
        }
    
    }
    
    // export default MyCompoent
    // 使用高阶组件装饰一下
    export default MyComtainer(MyCompoent)
    
    

    使用代理组件

    import React, { Component } from 'react'
    import MyCompoent from './MyCompoent'
    
    class App extends Component {
        render() {
            // 通过 props 传递 name
            return <MyCompoent name="高阶组件"/>
        }
    }
    
    export default App
    
    

    此时,页面显示 装饰器 字样!

    因为通过 MyComtainer 高阶组件进行了装饰,把原本的 高阶组件 字样变更为 装饰器 字样

    2.refs 引用

    高阶组件

    import React, { Component } from 'react'
    
    /**
     * 高阶组件 装饰器模式
     * 
     *      装饰传递进来的组件
     * 
     *      通过 refs 引用:可以调用组件的实例方法,还可以 查询/添加/删除/修复 prosp
     * 
     * @param {*} WrappedComponent 
     */
    const MyComtainer = (WrappedComponent) => {
      return class extends Component {
    
        /**
         * WrappedComponent 被渲染时,refs 回调函数会被执行
         * @param {实例 } WrappedComponentInstance 是 WrappedComponent 组件的实例
         */
        proc(WrappedComponentInstance) {
          console.log('WrappedComponentInstance: ', WrappedComponentInstance)
          
          // 调用 被传递进来的组件的 getUserName() 函数
          WrappedComponentInstance.getUserName()
    
        }
        
        render() {
    
            // 第一种方式
            const props = Object.assign({}, this.props, {
              ref: this.proc.bind(this),
            });
            console.log('props:', props)
    
            // 添加/删除/修复 prosp
            const newProps = { name: '装饰' }
            return <WrappedComponent { ...props } { ...newProps } />
    
            // 第二种方式
            // return <WrappedComponent { ...props } { ...newProps } ref={ref => this.proc.bind(this)}/>
        }
    
      }
    
    }
    
    export default MyComtainer
    
    

    被代理的组件

    import React, { Component } from 'react'
    import MyComtainer from './MyContainer';
    
    // @MyComtainer
    class MyCompoent extends Component {
    
        getUserName() {
            console.log('调用 MyCompoent 组件的 getUserName 函数')
        }
    
        render() {
          return <div>{this.props.name || '没有值'}</div>
        }
    
    }
    
    // export default MyCompoent
    // 使用高阶组件装饰一下
    export default MyComtainer(MyCompoent)
    

    使用代理组件

    import React, { Component } from 'react'
    import MyCompoent from './MyCompoent'
    
    class App extends Component {
    
        render() {
            // 通过 props 传递 name
            return <MyCompoent name="高阶组件" />
        }
    }
    
    export default App
    

    此时,页面显示 装饰器 字样!

    因为通过 MyComtainer 高阶组件进行了装饰,把原本的 高阶组件 字样变更为 装饰器 字样
    然后控制台会打印出 调用 MyCompoent 组件的 getUserName() 函数(因为被装饰器调用了getUserName() 函数

    3.抽象 state

    高阶组件

    import React, { Component } from 'react'
    
    /**
     * 高阶组件 装饰器模式
     * 
     *      装饰传递进来的组件
     * 
     *      抽象 state 
     * 
     * @param {*} WrappedComponent 
     */
    const MyComtainer = (WrappedComponent) => {
      return class extends Component {
    
        constructor(props) {
          super(props);
          this.state = {
            input: ''
          }
    
          // this.onNewChange = this.onNewChange.bind(this)
        }
    
        onNewChange(e) {
          console.log(e.target.value)
          this.setState({ value: e.target.value })
        }
        
        render() {
            // 高阶组件这里,设置 state,以及事件
            const newProps = {
              input: {
                value: this.state.value,
                onChange: e => this.onNewChange(e),
              }
            }
            console.log(newProps)
            return <WrappedComponent { ...this.props.input } { ...newProps } />
        }
    
      }
    
    }
    
    export default MyComtainer
    
    

    被代理的组件

    import React, { Component } from 'react'
    import MyComtainer from './MyContainer';
    
    // @MyComtainer
    class MyCompoent extends Component {
    
        render() {
          return <input name="input" defaultValue="这是一个组件" { ...this.props.input }/>
        }
    
    }
    
    // export default MyCompoent
    export default MyComtainer(MyCompoent)
    
    
    

    使用代理组件

    import React, { Component } from 'react'
    import MyCompoent from './MyCompoent'
    
    class App extends Component {
    
        render() {
            // 通过 props 传递 name
            return <MyCompoent name="高阶组件" />
        }
    }
    
    export default App
    
    
    

    经过 MyComtainer 高阶组件,进行修饰,绑定一个 onChange 事件,会在控制台打印出 当前的值

    还可以对组件进行元素包裹

    import React, { Component } from 'React';
    const MyContainer = (WrappedComponent) =>
    class extends Component {
        render() {
          return (
            <div style={{display: 'block'}}>
              <WrappedComponent {...this.props} />
            </div>
          )
      }
    }
    

    反向继承方式,我用的不多。。。就不写出来了

    相关文章

      网友评论

          本文标题:React 高阶组件

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