彻底搞清高阶函数与高阶组件的关系

2,237 阅读2分钟

大家知道在React和Vue中都存在高阶组件。尤其是在React应用更为普遍一些。其实高阶组件的定义来源于高阶函数。首先我们先看看什么是高阶函数。

一、 高阶函数

高阶函数英文叫Higher-order function。对其他函数进行操作的函数,可以将它们作为参数或返回它们。

这句话有点费解,其实我们可以归纳为以下条件满足之一就可以认为的高阶函数

  • 接受参数为函数
  • 返回参数为函数

下面我们举例说明 首先我们先写一个普通函数比如:一个加法运算函数,传入两个数字返回一个两数之和。

const add = (x, y) => x + y
console.log(`add: ${add(1, 2)}`)

下面我们写一个高阶函数目的是希望将原有的加法运算函数的结果进行修饰 比如我们希望将结果做一个简单的格式化 :比如让他的返回结果用“[]”包裹。

大家注意这个高阶函数同时满足了高阶函数的两个特点传入参数和返回值都是函数。

// 高阶函数
const format = fn => (...args) => `[${fn(...args)}]`
const myAdd = format(add)
console.log(`format: ${myAdd(1, 2)}`)

运行结果

如果想通过参数定义包裹的字符的话 就需要将原有的函数进行柯里化 或者 说是升阶

const format = (front, end) => fn => (...args) => `${front}${fn(...args)}${end}`
const myAdd = format('【','】')(add)
console.log(`format: ${myAdd(1, 2)}`)

最终的运行结果

总结来说,可以通过高阶函数将普通函数的功能进行了扩展。

二、 高阶组件

那么什么是高阶组件呢。 我们以React为例 ,首先我们先回顾一下React时候是什么呢。 React 中有一个经典的公式:

const View = f(data)

也就是函数即组件

既然是函数 那么函数式编程中的一切规律也都适用包括高阶函数。

既然函数即组件 那当然就叫高阶组件了。

1. 普通组件

为了验证高阶组件,首先先做一个普通组件

import React from 'react'
const Text = props => (
    <div>{props.children}</div>
)
export default () => (
    <div>
        <Text>ABC</Text>
    </div>
)

这是一个普通的函数式组件目的就是显示一个字符串

运行结果:

2 高阶组件

接着定义一个高阶组件将原有的字符串显示组件增加一些修饰 比如:加一个[] 包裹

const withFormat = Comp => props => {
    return <Comp>[ {props.children} ]</Comp>
}
const MyText = withFormat(Text)

export default () => (
    <div>
        <MyText>ABC</MyText>
    </div>
)

运行结果:

以上就是一个最简单的高阶组件

当然利用高阶组件最好用的功能还是为组价提供数据和方法,为普通组件赋能。 我们在高阶组件中通过props传值为普通组件分别传入一个格式化方法和一个字符串(数据)

const withFormat = Comp => props => {
    // 提供一个格式化方法
    const format = text => `[${text}]`
    // 提供一个数据
    const data = '>>>>'
    return <Comp {...props} format={format} data={data} ></Comp>
}

然后我们在普通组件中尝试调用一下这个方法和数据

const Text = props => (
    <div>{props.format(props.children)} - {props.data}</div>
)
const MyText = withFormat(Text)
export default () => (
    <div>
        <MyText>ABC</MyText>
    </div>
)

3. 高阶函数工厂

下面我们做一个更加复杂的例子 比如我们先创建一个高阶组件,功能是为了给组件增加字体颜色。

const withColor =  Comp => props => (
    <div style={{ color : red }}>
        <Comp {...props}></Comp>
    </div>
)

如果希望将颜色作为参数配置的话 就需要将原有的函数做柯里化 其实就是给原有的高阶函数升阶 或者也可以认为是创建了一个高阶函数工厂

最后代码完成的样子

const withColor = color => Comp => props => (
    <div style={{ color }}>
        <Comp {...props}></Comp>
    </div>
)

const MyText = withFormat(Text)
const MyText = withColor('blue')(withFormat(Text))

export default () => (
    <div>
        <MyText>ABC</MyText>
    </div>
)

学到这大家应该搞清楚高阶函数的和高阶组件的关系了吧。