通俗理解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);
共同学习,写下你的评论
评论加载中...
作者其他优质文章