React高阶组件

React高阶组件一 认识高阶组件什么是高阶组件呢 相信很多人都听说过 也用过高阶函数 它们非常相似 所以我们可以先来回顾一下什么是高阶函数 高阶函数的维基百科定义 至少满足以下条件之一 接受一个或多个函数作为输入 输出一个函数 JavaScript 中比较常见的 filter map reduce 都是高阶函数 那么什么是高阶组件呢 高阶组件的英文是 Higher OrderCompone 简称为 HOC 官方的定义 高阶组件是参数为组件 返回值为新组件的函数 我们可以进行如下的解析

一、认识高阶组件

什么是高阶组件呢? 相信很多人都听说过,也用过 高阶函数,它们非常相似,所以我们可以先来回顾一下什么是 高阶函数。

高阶函数的维基百科定义:至少满足以下条件之一:

  • 接受一个或多个函数作为输入;
  • 输出一个函数;

JavaScript中比较常见的filter、map、reduce都是高阶函数。

那么什么是高阶组件呢?

  • 高阶组件的英文是 Higher-Order Components,简称为 HOC;
  • 官方的定义:高阶组件是参数为组件,返回值为新组件的函数

我们可以进行如下的解析:

  • 首先, 高阶组件 本身不是一个组件,而是一个函数
  • 其次,这个函数的参数是一个组件返回值也是一个组件

二、高阶组件的定义

  • 高阶组件的调用过程类似于这样:
    在这里插入图片描述

  • 高阶函数的编写过程类似于这样:
    在这里插入图片描述
    在这里插入图片描述




组件的名称问题:

  • 在ES6中,类表达式中类名是可以省略的;
  • 组件的名称都可以通过displayName来修改;
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述








import React, {     PureComponent } from 'react'; class App extends PureComponent {     render() {     return ( <div> app: {    this.props.name} </div> ); } } function enhanceComponent2(WrappedComponent) {     function NewComponent(props) {     return <WrappedComponent {    ...props} /> } NewComponent.displayName = 'zep2' return NewComponent } // function enhanceComponent(WrappedComponent) {     // class NewComponent extends PureComponent {     // render() {     // return     // } // } // NewComponent.displayName = 'zep' // return NewComponent // } const EnhanceComponent = enhanceComponent2(App) export default EnhanceComponent; 

高阶组件并不是React API的一部分,它是基于React的 组合特性而形成的设计模式;

高阶组件在一些React第三方库中非常常见:

  • 比如redux中的connect;(后续会讲到)
  • 比如react-router中的withRouter;(后续会讲到)

三、高阶组件的应用—— props的增强

利用高阶组件来共享Context:

  1. 未使用高阶组件共享Context时:
import React, { 
   PureComponent, createContext} from 'react'; // 创建Context const UserContext = createContext({ 
    nickname: '默认', level: -1, region: '中国' }) class Home extends PureComponent { 
    render() { 
    return ( <UserContext.Consumer> { 
    user => { 
    return <h2>Home { 
   `昵称:${ 
     user.nickname} 等级:${ 
     user.level} 区域:${ 
     user.region}`}</h2> } } </UserContext.Consumer> ) } } class About extends PureComponent { 
    render() { 
    return ( <UserContext.Consumer> { 
    user => { 
    return <h2>Home { 
   `昵称:${ 
     user.nickname} 等级:${ 
     user.level} 区域:${ 
     user.region}`}</h2> } } </UserContext.Consumer> ) } } class App extends PureComponent { 
    render() { 
    return ( <div> app <UserContext.Provider value={ 
   { 
   nickname: 'zep', level: 50, region: '深圳'}}> <Home/> <About/> </UserContext.Provider> </div> ); } } export default App; 

在这里插入图片描述

  1. 使用高阶组件共享Context时:
    在这里插入图片描述
    在这里插入图片描述




import React, {    PureComponent, createContext} from 'react'; // 定义高阶组件 function withUser(WrappedComponent) {     return function (props) {     return ( <UserContext.Consumer> {     user => {     return <WrappedComponent {    ...props} {    ...user} /> } } </UserContext.Consumer> ) } } // 创建Context const UserContext = createContext({     nickname: '默认', level: -1, region: '中国' }) class Home extends PureComponent {     render() {     return <h2>Home {    `昵称:${      this.props.nickname} 等级:${      this.props.level} 区域:${      this.props.region}`}</h2> } } class About extends PureComponent {     render() {     return <h2>Home {    `昵称:${      this.props.nickname} 等级:${      this.props.level} 区域:${      this.props.region}`}</h2> } } const UserHome = withUser(Home) const UserAbout = withUser(About) class App extends PureComponent {     render() {     return ( <div> app <UserContext.Provider value={    {    nickname: 'zep', level: 50, region: '深圳'}}> <UserHome/> <UserAbout/> </UserContext.Provider> </div> ); } } export default App; 

四、高阶组件的应用—— 渲染判断鉴权

在开发中,我们可能遇到这样的场景:

  • 某些页面是必须用户登录成功才能进行进入;
  • 如果用户没有登录成功,那么直接跳转到登录页面;
import React, { 
   PureComponent} from 'react'; // 高阶组件 function withAuth (WrappedComponent) { 
    const NewCpn = function (props) { 
    const { 
   isLogin} = props if (isLogin) { 
    return <WrappedComponent { 
   ...props} /> } else { 
    return <LoginPage { 
   ...props} /> } } NewCpn.displayName = 'AuthCpn' return NewCpn } // 登录组件 class LoginPage extends PureComponent { 
    render() { 
    return <h2>LoginPage</h2> } } // 购物车组件 class CartPage extends PureComponent { 
    render() { 
    return <h2>CartPage</h2> } } const AuthCartPage = withAuth(CartPage) class App extends PureComponent { 
    render() { 
    return ( <div> <AuthCartPage isLogin={ 
   false} /> </div> ); } } export default App; 

五、高阶组件的应用—— 生命周期劫持

import React, { 
   PureComponent} from 'react'; function withRenderTime(WrappedComponent) { 
    return class extends PureComponent { 
    // 即将渲染时获取当前的时间 componentWillMount() { 
    this.beginTime = Date.now() } // 渲染完成再获取当前时间 componentDidMount() { 
    this.endTime = Date.now() const interval = this.endTime - this.beginTime console.log(`${ 
     WrappedComponent.name}渲染时间: ${ 
     interval}`) } render() { 
    return <WrappedComponent { 
   ...this.props} /> } } } class Home extends PureComponent{ 
    /* // 即将渲染时获取当前的时间 componentWillMount() { this.beginTime = Date.now() }*/ render() { 
    return <h2>Home</h2> } /*// 渲染完成再获取当前时间 componentDidMount() { this.endTime = Date.now() const interval = this.endTime - this.beginTime console.log('Home渲染时间:' + interval) }*/ } class About extends PureComponent{ 
    render() { 
    return <h2>About</h2> } } const TimeHome = withRenderTime(Home) const TimeAbout = withRenderTime(About) class App extends PureComponent { 
    render() { 
    return ( <div> App <TimeHome /> <TimeAbout /> </div> ); } } export default App; 

六、高阶函数的意义

  • Mixin 可能会相互依赖,相互耦合,不利于代码维护
  • 不同的Mixin中的方法可能会相互冲突
  • Mixin非常多时,组件是可以感知到的,甚至还要为其做相关处理,这样会给代码造成滚雪球式的复杂性

当然,HOC也有自己的一些缺陷:

  • HOC需要在原组件上进行包裹或者嵌套,如果大量使用HOC,将会产生非常多的嵌套,这让调试变得非常困难;
  • HOC可以劫持props,在不遵守约定的情况下也可能造成冲突;

Hooks的出现,是开创性的,它解决了很多React之前的存在的问题

  • 比如this指向问题
  • 比如hoc的嵌套复杂度问题等
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/200431.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月20日 上午10:51
下一篇 2026年3月20日 上午10:52


相关推荐

  • SpringBoot——JWT实现

    SpringBoot——JWT实现SpringBoot——JWT实现

    2022年4月23日
    50
  • 计算机适配器有什么作用,例举适配器是什么

    计算机适配器有什么作用,例举适配器是什么随着科技进步,网络的进步,电脑已逐渐渗透到我们生活的方方面面,但是我们对于电脑的一些配置却不怎么了解,比如我们经常用到的适配器。下面,我就将适配器的一些小知识分享给大家我们在生活中或者使用电脑的时候经常会看到适配器一词,很多朋友就纳闷了,适配器是什么呢?有什么作用呢?针对这些问题,小编给大家整理了一些适配器的介绍,赶紧来瞧瞧吧适配器介绍电脑图解1适配器是一个接口转换器,也就是一种起中间连接作用的配…

    2022年6月7日
    51
  • crontab的使用方法_crontab用法

    crontab的使用方法_crontab用法crontab设置ubuntu16.04server自带crontab执行crontab-e选择编辑器后在文本最后添加上以下 1000***/home/ubuntu/cron_cmd.sh&gt;/home/ubuntu/cron_log2&gt;&amp;1我这里执行了一个脚本文件,里面可以放很多命令,log输出到指定文件夹。至于什么是2&gt;&amp;1可以参考这里…

    2022年8月24日
    7
  • aarch64指令集_AArch64应用程序级编程模型

    aarch64指令集_AArch64应用程序级编程模型根据实现选择,体系结构支持多级执行特权,由从EL0到EL3的不同异常级别表示。EL0对应于最低的特权级别,通常被描述为无特权。应用层程序员模型是在EL0上执行软件的程序员模型。系统软件决定异常级别,因此决定软件运行的特权级别。当操作系统同时支持EL1和EL0执行时,应用程序通常在EL0上运行。允许操作系统以唯一的或共享的方式将系统资源分配给应用程序。从其他进程中提供一定程度的保护,因此有助于保护操…

    2022年10月17日
    4
  • js免费调用天气API

    js免费调用天气APIjs调用天气API文档参考链接:天气API文档1、首先登陆天气API进行用户注册点击右上角进行注册、登录2、打开API文档如下图其中appid和appsecret则在天气API控制器中查看其中appid和version和appsecret3者为必填选项,例如https://www.tianqiapi.com/api?version=v9&appid=84122144&appsecret=m70vbv6Acityid、city、ip则代表三种查询方式(三选一)(城市i

    2022年10月8日
    9

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号