react 给一个引用的组件添加新属性_高阶组件在React中的应用

197d5595dd4026e5b669aab5beefb949.png

高阶组件的定义

接受React组件作为输入,输出一个新的React组件。

概念源自于高阶函数,将函数作为参数,或者输出一个函数,如map,reduce,sort。

用haskell的函数签名来表示:

hocFactory:: W: React.component => E: React.component 

使用场景

可以用来对组件进行二次加工和抽象,比如:对Input组件进行样式改动、添加新的props属性;某些可以复用的逻辑抽象后再注入组件。

所以 HOC 的作用大概有以下几点:

  • 代码复用和逻辑抽象
  • 对 state 和 props 进行抽象和操作
  • Render 劫持

如何实现

  • 属性代理(props proxy):高阶组件通过被包裹的React组件来操作props,从而能够实现控制props、引用refs、抽象state。

1.1 控制props

import React, { Component, Fragment } from 'react';

const MyContainer = WrappedComponent =>
  class extends Component {
    render() {
      const newProps = {
        text: 'newText',
      };
      return (
        <>
          <span>通过 props proxy 封装HOC</span>
          <WrappedComponent {...this.props} {...newProps} />
        </>
      );
    }
  };

从这里可以看到,在render中返回来传入WrappedComponent 的React组件,这样我们就可以通过HOC在props中传递属性、添加组件及样式等等。

使用也是非常简单:

import React, { Component } from 'react';
import MyContainer from './MyContainer.jsx';

class App extends Component {
    ...
}

export default MyContainer(App);

当然也可以使用装饰器@decorator:”接收一个类作为参数,返回一个新的内部类“,与HOC的定义如出一辙,十分契合。

import React, { Component } from 'react';
import MyContainer from './MyContainer.jsx';

@MyContainer
class App extends Component {
    ...
}

export default App;

1.2 通过refs使用引用

import React, { Component } from 'react';

const RefsHOC = WrappedComponent =>
  class extends Component {
    
    proc(wrappedComponentInstance) {
      wrappedComponentInstance.refresh();
    }

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

export default RefsHOC;

render() 时会执行 ref 回调,即proc方法,该方法可以获取 WrappedComponent 的实例,其中包含组件的 props,方法,context等。我们也可以在 proc 中进行一些操作,如控制组件刷新等。

1.3 抽象state

我们可以通过向 WarppedComponent 提供 props 和 回调函数抽象state,将原组件抽象成展示型组件,隔离内部state。

import React, { Component } from 'react';

const MyContainer = WrappedComponent =>
  class extends Component {
    constructor(props) {
      super(props);
      this.state = {
        name: '',
      };
    }

    onHandleChange = e => {
      const val = e.target.value;
      this.setState({
        name: val,
      });
    };

    render() {
      const newProps = {
        name: {
          value: this.state.name,
          onChange: this.onHandleChange,
        },
      };
      return <WrappedComponent {...this.props} {...newProps} />;
    }
  };

我们将 input 组件中 name props 的 onChange方法提取到了高阶组件中,这样就有效的抽象了同样的state操作。

import React, { Component } from 'react';
import MyContainer from './MyContainer.jsx';

@MyContainer
class MyInput extends Component {
  render() {
    return <input type="text" {...this.props.name} />;
  }
}

export default MyInput;

参考链接

深入React技术栈​book.douban.com Javascript 中的装饰器​aotu.io
90185c597c6d63a550b4c97124ca6601.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值