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

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

标签:
React

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


我不能说高阶组件就是这么一个东西。但是它是一个概念上很简单,但却非常常用、实用的东西,被大量 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&rt;I drink {this.props.milk} <div&rt;
        )
    }
}
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);


点击查看更多内容
4人点赞

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

评论

作者其他优质文章

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

100积分直接送

付费专栏免费学

大额优惠券免费领

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

举报

0/150
提交
取消