为了账号安全,请及时绑定邮箱和手机立即绑定

通俗理解react中的高阶组件(Higher-Order Components)

有时候人们很喜欢造一些名字很吓人的名词,让人一听这个名词就觉得自己不可能学会,从而让人望而却步。但是其实这些名词背后所代表的东西其实很简单。

我不能说高阶组件就是这么一个东西。但是它是一个概念上很简单,但却非常常用、实用的东西,被大量 React.js 相关的第三方库频繁地使用。在前端的业务开发当中,你不掌握高阶组件其实也可以完成项目的开发,但是如果你能够灵活地使用高阶组件,可以让你代码更加优雅,复用性、灵活性更强。它是一个加分项,而且加的分还不少。

高阶组件是一个函数(而不是组件),它接受一个组件作为参数,返回一个新的组件。这个新的组件会使用你传给它的组件作为子组件 -引用自React.js小书

我希望通过自己的理解,然后把一些本来就简单但是被说复杂的东西,通过自己的语言去把它通俗易懂地说出来,毕竟我也是俗人一个,俗人讲俗话最容易懂了不是吗?

那么根据这里的定义,我们先写两个函数来进行举栗子:

比如我们写个函数,实现去冰箱拿牛奶,我们先要打开冰箱才能拿到牛奶,假如localstorage就是冰箱,牛奶这个变量就存在里面,那么我们可以这么写

function want(){
 let milk=window.localstorage.getItem('milk');
 console.log('I want'+orange)
}

比如我们写个函数,实现又去冰箱拿牛奶喝,我们先要打开冰箱才能拿到牛奶,假如localstorage就是冰箱,牛奶这个变量就存在里面,那么我们可以这么写

   function drink(){
    let milk=window.localstorage.getItem('milk');
    console.log('I drink'+milk)
    }

每次我们都要去打开冰箱去重复这个动作,是不是很烦,所以我们要进行优化,我们只要告诉某个函数,说我们要拿牛奶,怎么拿我不管,拿到之后我可以进行任意操作。

首先我们先对原本的函数进行优化

function want(milk){
 console.log('I want'+orange)
}

比如我们写个函数,实现又去冰箱拿牛奶喝,我们先要打开冰箱才能拿到牛奶,假如localstorage就是冰箱,牛奶这个变量就存在里面,那么我们可以这么写

function drink(milk){
console.log('I drink'+milk)
}
function wrapWithMilk(withAction){
  let newAction=()=>{
    let milk=window.localstorage.getItem('milk');
    withAction(milk);
  }
 return newAction; 
}

want=wrapWithMilk(want);
drink=wrapWithMilk(drink);
want();
drink();

这里wrapWithMilk就是我们所说的高阶函数了,我们只需要知道want跟drink的第一个参数是milk就行,怎么拿到的我们都不用去管啦

接下来说说高阶组件

其实高阶组件就是一个没有副作用的纯函数

我们将函数转换为reat组件试下

import React, {Component} from 'react'
class Want extends Component {
constructor(props) {
super(props);
this.state = {
milk: ''
}
}

componentWillMount() {
let milk= localStorage.getItem('milk');
this.setState({    
milk: milk
})
}

render() {
return (
<div>I want {this.state.milk}</div>
) } 
export default Want;
}

class Drink extends Component {
constructor(props) {
super(props);
this.state = {
milk: ''
}
}
componentWillMount() {
let milk= localStorage.getItem('milk');
this.setState({
milk: milk
})
}
render() {
return (
<div>I drink{this.state.milk}</div>
) } 
export default Drink;
}

两个组件大部分代码都是重复的唉。
按照上一节wrapWithMilk函数的思路,我们来写一个高阶组件(高阶组件就是一个函数,且该函数接受一个组件作为参数,并返回一个新的组件)。

import React, {Component} from 'react'

export default (WrappedComponent) => {
class NewComponent extends Component {
    constructor() {
        super();
        this.state = {
            milk: ''
        }
    }

 componentWillMount() {
        let milk= localStorage.getItem('milk');
        this.setState({
            milk: milk
        })
    }

    render() {
        return <WrappedComponent&rt; username={this.state.milk}/&rt;
    }
}

return NewComponent
}

然后我们来去简化我们的Want跟Drink组件

class Want extends Component {
  render() {
  return (
  <div>I want {this.props.milk}</div>
) 
} 
export default Want;

class Drink extends Component {
  render() {
   return (
<div>I drink{this.props.milk}</div>
    ) 
 }  
export default Drink;
}

然后我们调用高阶组件去改造它

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

class Want extends Component {

render() {
    return (
        <div&rt;I want{this.props.milk} <div&rt;
    )
}
}
Welcome = wrapWithUsername(Want); 
export default Want;

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

class Drink extends Component {

    render() {
        return (
            <div>I drink {this.props.milk} <div>
        )
    }
}

Welcome = wrapWithUsername(Drink);

export default Drink;

高阶组件就是把milk通过props传递给目标组件了。目标组件只管从props里面拿来用就好了。

现在可以理解react-redux的connect函数了~

把redux的state和action创建函数,通过props注入给了Component。
你在目标组件Component里面可以直接用this.props去调用redux state和action创建函数了。

ConnectedComment = connect(mapStateToProps, mapDispatchToProps)(Component);

connect是一个返回函数的函数(就是个高阶函数)
const enhance = connect(mapStateToProps, mapDispatchToProps);
返回的函数就是一个高阶组件,该高阶组件返回一个与Redux store 关联起来的新组件

const ConnectedComment = enhance(Component);

antd的Form也是一样的

const WrappedNormalLoginForm = Form.create()(NormalLoginForm);
点击查看更多内容
5人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消