认识高阶组件

  1. HOC:高阶组件 (Higher-Order Component),以组件作为参数,并返回一个组件;
  2. 通常,可以利用 HOC 实现横切关注点:
    1. eg1:有多个组件,每个组件在创建组件和销毁组件时,需要作日志记录;
    2. eg2:有多个组件,它们需要显示一些内容,得到的数据结构完全一致;

高阶组件的使用案例

渲染判断鉴权

JavaScript
JavaScript
import React from 'react'

/**
 * 高阶组件
 * @param {*} comp 组件
 */
export default function withLogin(Comp) {
    return function LoginWrapper(props) {
        if (props.isLogin) {
            return <Comp {...props} />
        }
        return null;
    }
}
import React from 'react'
import withLogin from "./withLogin"

class A extends React.Component {
    // 不再关注跟该组件不相关的事情
    render() {
        return <h1>A:{this.props.a}</h1>
    }
}

let AComp = withLogin(A);

export default class App extends React.Component {
    render() {
        return (
            <div>
                <AComp isLogin a={1} />
            </div>
        )
    }
}

生命周期劫持

JavaScript
JavaScript
import React from "react"

/**
 * 高阶组件
 * @param {*} comp 组件
 */
export default function withLog(Comp, str) {
    return class LogWrapper extends React.Component {
        componentDidMount() {
            console.log(`日志:组件${Comp.name}被创建了!${Date.now()}`);
        }

        componentWillUnmount() {
            console.log(`日志:组件${Comp.name}被销毁了!${Date.now()}`);
        }

        render() {
            return (
                <>
                    <h1>{str}</h1>
                    <Comp {...this.props} />
                </>
            )
        }
    }
}
import React from 'react'
import withLog from "./withLog";

class A extends React.Component {
    // 不再关注跟该组件不相关的事情
    render() {
        return <h1>A:{this.props.a}</h1>
    }
}

let AComp = withLog(A, "abc");

export default class App extends React.Component {
    render() {
        return (
            <div>
                <AComp a={1} />
            </div>
        )
    }
}

注意

  1. 不要在 render 中生成高阶组件并使用;

    export default class App extends React.Component {
        render() {
            // 会被重复创建和销毁
            let AComp = withLogin(withLog(A, "abc"));
    
            return (
                <div>
                    <AComp isLogin a={1} />
    
                    <button onClick={() => { this.setState({}) }}>点击</button>
                </div>
            )
        }
    }
    
  2. 不要在高阶组件内部更改传入的组件(限制了组件之后的扩展);

    /**
     * 高阶组件
    * @param {*} comp 组件
    */
    export default function withLog(Comp, str) {
        // 修改了传入组件的 componentDidMount
        Comp.prototype.componentDidMount = function() { }
    
        return class LogWrapper extends React.Component {
            componentDidMount() {
                console.log(`日志:组件${Comp.name}被创建了!${Date.now()}`);
            }
    
            componentWillUnmount() {
                console.log(`日志:组件${Comp.name}被销毁了!${Date.now()}`);
            }
    
            render() {
                return (
                    <>
                        <h1>{str}</h1>
                        <Comp {...this.props} />
                    </>
                )
            }
        }
    }
    

高阶函数的意义

  1. 利用高阶组件可以针对某些 React 代码进行更加优雅的处理;

  2. 其实早期的 React 有提供组件之间的一种复用方式是 mixin,目前已经不再建议使用:

    1. Mixin 可能会相互依赖,相互耦合,不利于代码维护;
    2. 不同的 Mixin 中的方法可能会相互冲突;
    3. Mixin 非常多时,组件是可以感知到的,甚至还要为其做相关处理,这样会给代码造成滚雪球式的复杂性;
  3. 当然,HOC 也有自己的一些缺陷:

    1. HOC 需要在原组件上进行包裹或者嵌套,如果大量使用 HOC,将会产生非常多的嵌套,这让调试变得非常困难;
    2. HOC 可以劫持 props,在不遵守约定的情况下也可能造成冲突;
  4. Hooks 的出现,是开创性的,它解决了很多 React 之前的存在的问题,比如 this 指向问题、比如 HOC 的嵌套复杂度问题等等;

打赏作者
您的打赏是我前进的动力
微信
支付宝
评论

中午好👏🏻,我是 ✍🏻   疯狂 codding 中...

粽子

这有关于前端开发的技术文档和你分享。

相信你可以在这里找到对你有用的知识和教程。

了解更多

目录

  1. 1. 认识高阶组件
  2. 2. 高阶组件的使用案例
    1. 2.1. 渲染判断鉴权
    2. 2.2. 生命周期劫持
  3. 3. 注意
  4. 4. 高阶函数的意义