从小白到入门react高阶组件

原文链接:https://segmentfault.com/a/1190000010371752

知识

高阶组件:他描述得是接受react组件作为输入,输出一个新的react组件。
更通俗的讲:高阶组件是通过包裹(wrapped)被传入的react组件,经过一系列处理最终返回一个相对增强(enhanced)的React组件,供其他组件调用。

实现一个高阶组件
  • 下面我们来实现一个最简单的高阶组件(函数),它接受一个React组件(WrappedComponent),包裹后然后返回。
import React, {Component} from 'react';
export default function widthDemo1(WrappedComponent) {
    return class HOC extends Component {
        render() {
            return <div>
                <div className="demo-header">
                    我是普通组件的标题-高阶组件
                </div>
                <WrappedComponent {...this.props}/>
            </div>
        }
    }
}
  • 在其他组件里,我们引用这个高阶组件,用来强化它。
@widthDemo1
export default class Demo extends Component {
  render() {
    return (
      <div>
        我是一个普通组件
      </div>
    );
  }
}

在这个简单的例子里面,高阶函数就做了一件事,那就是为包裹的组件添加了一个标题。这个高阶组件可以用到任何一个乣添加此逻辑的组件上面,只需要被此高阶组件装饰即可。

高阶组件的进阶
组件参数

还是以上述例子为例,此高阶组件仅仅只是展示了我是标题这个名称,但是为了更好的抽象,此标题应当可以被参数化,如下方式调用。

// 如果传入参数,则传入的参数将作为组件的标题呈现
import React, { Component } from 'react';
import widthDemo1 from './demo-1';
@widthDemo1('我是普通组件的标题-高阶组件demo')
export default class Demo1 extends Component {
    render() {
        return (
            <div>
                我是一个正常普通组件
            </div>
        );
    }
}

widthDemo1需要被改写成如下形式,它接受一个参数,然后返回一个高阶组件(函数)。

import React, {Component} from 'react';
function getDisplayName(component) {
    return component.displayName || component.name || 'Component';
}
export default function (title){
    return  function widthDemo1(WrappedComponent) {
        return class HOC extends Component {
            // static displayName = `HOC(${getDisplayName(WrappedComponent)})`
            render() {
                return <div>
                    <div className="demo-header">
                        {title}
                    </div>
                    <WrappedComponent {...this.props}/>
                </div>
            }
        }
    }
}

使用Es6写法更简单

import React, {Component} from 'react';
function getDisplayName(component) {
    return component.displayName || component.name || 'Component';
}
export default (title)=>(WrappedComponent)=> class HOC extends Component {
            // static displayName = `HOC(${getDisplayName(WrappedComponent)})`
    render() {
        return <div>
            <div className="demo-header">
                {title}
            </div>
            <WrappedComponent {...this.props}/>
        </div>
    }
}
基于属性代理的方式
import React, {Component} from 'react';
function getDisplayName(component) {
    return component.displayName || component.name || 'Component';
}
export default (title)=>(WrappedComponent)=> class HOC extends Component {
            // static displayName = `HOC(${getDisplayName(WrappedComponent)})`
    render() {
        const newProps = {
            test:'hoc'
        }
        return <div>
            <div className="demo-header">
                {title}
            </div>
            <WrappedComponent {...this.props} {...newProps}/>
        </div>
    }
}
基于反向继承的方式

这种方式返回的React组件继承了被传入的组件,所以它能够访问到的区域、权限更多,相比属性代理方式,它更像打入组织内部,对其进行修改。具体的可以参考附录里提供的链接进行深入学习。
在这里我们引用高阶组件

import React, { Component } from 'react';
import widhtDemmoLoading from './demo-loading'
@widhtDemmoLoading(state => state.isLoading)
export default class Demo1 extends Component {
    state = {
        isLoading: true
    };
    componentDidMount(){
        let _this=this
        setTimeout(function(){
            _this.setState({
                isLoading: false
            });
        }, 3000);
    }
    render() {
        console.log(this.props);
        return (
            <div>
                我是一个正常普通组件
            </div>
        );
    }
}

高阶组件写法

import React, {Component} from 'react';

export default (isCheck)=>(WrappedComponent)=> class  extends WrappedComponent {

    render() {
        console.log(this.state);

        return <div>
            <div className="demo-header">
                plus首页
            </div>
            {
                isCheck(this.state) ? '加载中。。。' : '加载完成'
            }
        </div>
    }
}
组合多个高阶组件

上面讲的,我们为组件增强了一个功能,加入需要同时增强多个功能呢。例如,我们需要给组件一个标题,同时又需要在页面为加载的时候显示一个loading

import React, { Component } from 'react';
import widthDemo1 from './demo-1';
import widhtDemmoLoading from './demo-loading'
@widthDemo1('我是普通组件的标题-高阶组件demo1122')
@widhtDemmoLoading(state => state.isLoading)
export default class Demo1 extends Component {}

使用compose可以简化上述过程,也能体现函数式编程的思想。

import React, { Component } from 'react';
import {compose} from 'redux'
import widthDemo1 from './demo-1';
import widhtDemmoLoading from './demo-loading'
const enhance=compose(widthDemo1('我是普通组件的标题-高阶组件demo1122'),widhtDemmoLoading(state => state.isLoading))
@enhance
export default class Demo1 extends Component {}

这里借用的是redux的compose 方法。
还可以直接引用这个方法

const compose= function (...funcs) {
    if (funcs.length === 0) {
        return arg => arg
    }
    if (funcs.length === 1) {
        return funcs[0]
    }
    return funcs.reduce((a, b) => (...args) => a(b(...args)))
}
高阶组件实战
总结

高阶组件最大的好处就是解耦和灵活性,在react的开发中还是很有用的。
当然这不可能是高阶组件的全部用法。掌握了它的一些技巧,还有一些限制,你可以结合你的应用场景,发散思维,尝试一些不同的用法。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值