我的编程空间,编程开发者的网络收藏夹
学习永远不晚

React用法之高阶组件的用法详解

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

React用法之高阶组件的用法详解

监介

高阶组件也就是我们常说的HOC,是React中用于复用组件逻辑的一种高级技巧。HOC自身不是React API的一部分,他是一种基于React的组合特性而形成的设计模式。

其实就是组件作为参数,返回值也是组件的函数,他是纯函数,不会修改传入的组件,也不会使用继承来复制其行为。相反,HOC通过将组件包装在容器组件中来组成新组件。HOC是纯函数,没有副作用。

使用HOC的原因

  • 抽取重复代码,实现组件复用:相同功能组件复用
  • 条件渲染,控制组件的渲染逻辑(渲染劫持):权限控制
  • 捕获/劫持被处理组件的生命周期,常见场景:组件渲染性能追踪、日志打点。

HOC的实现方式

先来看一个简单的HOC实现方式

function withLog(Component) {
	return function (props) {
		console.log(`[${new Date().toISOString()}] ${Component.name} props:`, props);
		return <Component {...props} />;
	};
}

这个HOC接收一个组件作为参数,返回一个新的组件,新的组件在渲染之前会先输出当前时间和传入的组件的名称和props到控制台,然后再将props传递给原始组件进行渲染。

使用这个HOC可以像下面这样

function MyComponent(props) {
	return <div>{props.message}</div>;
}

const MyComponentWithLog = withLog(MyComponent);

ReactDOM.render(
	<MyComponentWithLog message="Hello, world!" />,
	document.getElementById('root')
);

渲染的时候控制台会输出

[2023-04-16T00:00:00.000Z] MyComponent props: { message: "Hello, world!" }

可以看到,HOC 可以用来增强组件的功能,比如添加日志、添加权限校验、添加数据预处理等。

其实HOC的实现方式主要分为两种:属性代理和反向继承

属性代理

使用组合的方式,将组件包装在容器上,依赖父子组件的生命周期关系来:

  • 返回无状态的函数组件
  • 返回class组件

操作props

// 可以通过属性代理,拦截父组件传递过来的porps并进行处理。

// 返回一个无状态的函数组件
function HOC(WrappedComponent) {
  const newProps = { type: 'HOC' };
  return props => <WrappedComponent {...props} {...newProps}/>;
}

// 返回一个有状态的 class 组件
function HOC(WrappedComponent) {
  return class extends React.Component {
    render() {
      const newProps = { type: 'HOC' };
      return <WrappedComponent {...this.props} {...newProps}/>;
    }
  };
}

抽象state

通过属性代理无法直接操作原组件的state,可以通过props和回调函数抽象state

function HOC(WrappedComponent) {
  return class extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        name: '',
      };
      this.onChange = this.onChange.bind(this);
    }
    
    onChange = (event) => {
      this.setState({
        name: event.target.value,
      })
    }
    
    render() {
      const newProps = {
        name: {
          value: this.state.name,
          onChange: this.onChange,
        },
      };
      return <WrappedComponent {...this.props} {...newProps} />;
    }
  };
}

// 使用
@HOC
class Example extends Component {
  render() {
    return <input name="name" {...this.props.name} />;
  }
}

这里我们稍微做一下解释。我们主要的目的是想通过传给HOC的这个组件来修改HOC的state,在HOC中定义了onChange方法目的是可以修改state。如果在WrappedComponent中调用onChange方法呢?我们可以定义一个对象作为WrappedComponent的props,然后将onChange方法存储在定义的对象上,传给WrappedComponent。

在WrappedComponent中,我们定义了一个input,我们都知道input有value属性作为input的值,还有一个onChange方法作为change事件,我们把传给WrappedComponent的props结构刚好就是value和onChange。这样当input在change的时候就可以就修改state的值了。

通过props实现条件渲染

通过props来控制是否渲染及传入数据

import * as React from 'react';

function HOC (WrappedComponent) {
  return (props) => (
  <div>
    {
      props.isShow ? (
        <WrappedComponent
          {...props}
        />
      ) : <div>暂无数据</div>
    }
  </div>
  );
}

export default HOC;

其他元素wrapper传入的组件

function withBackgroundColor(WrappedComponent) {
  return class extends React.Component {
    render() {
      return (
        <div style={{ backgroundColor: '#ccc' }}>
            <WrappedComponent {...this.props} {...newProps} />
        </div>
      );
    }
  };
}

反向继承

使用一个函数接收一个组件作为参数传入,并返回一个继承了该传入组件的类组件,且在返回组件的render()方法中返回了super.render()方法。

const HOC = (WrappedComponent) => {
	return class extends WrappedComponent {
		render() {
			return super.render()
		}
	}
}
  • 允许HOC通过this访问到原组件,可以直接读取和操作原组件的state/ref等
  • 可以通过render.super()获取传入组件的render,可以有选择的渲染劫持
  • 劫持原组件生命周期方法
function HOC(WrappedComponent){
  const didMount = WrappedComponent.prototype.componentDidMount;
  
  // 继承了传入组件
  return class HOC extends WrappedComponent {
    async componentDidMount(){
      // 劫持 WrappedComponent 组件的生命周期
      if (didMount) {
        await didMount.apply(this);
      }
      ...
    }

    render(){
      //使用 super 调用传入组件的 render 方法
      return super.render();
    }
  }
}

读取/操作原组件的state

function HOC(WrappedComponent){
  const didMount = WrappedComponent.prototype.componentDidMount;
  // 继承了传入组件
  return class HOC extends WrappedComponent {
    async componentDidMount(){
      if (didMount) {
        await didMount.apply(this);
      }
      // 将 state 中的 number 值修改成 2
      this.setState({ number: 2 });
    }

    render(){
      //使用 super 调用传入组件的 render 方法
      return super.render();
    }
  }
}

通过this.setState({ number: 2 });修改了原组件WrappedComponent中的state的number值

条件渲染

const HOC = (WrappedComponent) =>
  class extends WrappedComponent {
    render() {
      if (this.props.isRender) {
        return super.render();
      } else {
        return <div>暂无数据</div>;
      }
    }
  }

修改react树

// 修改返回render结果
function HigherOrderComponent(WrappedComponent) {
  return class extends WrappedComponent {
    render() {
      const tree = super.render();
      const newProps = {};
      if (tree && tree.type === 'input') {
        newProps.value = 'something here';
      }
      const props = {
        ...tree.props,
        ...newProps,
      };
      const newTree = React.cloneElement(tree, props, tree.props.children);
      return newTree;
    }
  };
}

这里首先通过super.render()拿到需要渲染的树,然后对这个渲染树做了修改。比如如果是一个input,则修改它的value值。

属性代理和反向继承对比

  • 属性代理:从"组合"角度出发,有利于从外部操作WrappedComponent,可以操作props,或者在WrappedComponent外加一些拦截器(如:条件渲染,增加外部样式)
  • 反向继承:从"继承"角度出发,从内部操作WrappedComponent,可以操作组件内部的state,生命周期和render等,功能更强大

到此这篇关于React用法之高阶组件的用法详解的文章就介绍到这了,更多相关React高阶组件内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

React用法之高阶组件的用法详解

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

React用法之高阶组件的用法详解

高阶组件也就是我们常说的HOC,是React中用于复用组件逻辑的一种高级技巧。这篇文章主要通过一些示例带大家学习一下高阶组件的使用,希望对大家有所帮助
2023-05-16

React高阶组件使用详细介绍

高阶组件就是接受一个组件作为参数并返回一个新组件(功能增强的组件)的函数。这里需要注意高阶组件是一个函数,并不是组件,这一点一定要注意,本文给大家分享React高阶组件使用小结,一起看看吧
2023-01-29

React 中引入 CSS 高阶用法的方案详解

React中的CSS高阶用法旨在提升代码可维护性和可扩展性。CSS模块将样式封装于组件中,防止样式冲突。Sass/Less提供高级CSS功能,提升代码可重用性。styled-components创建可重用样式化组件。CSS-in-JS将样式内联于组件,实现动态样式操作。在选择方案时,考虑组件需求和高级功能的需要。通过采用这些高阶用法,开发者能编写更可靠、可扩展的React样式代码。
React 中引入 CSS 高阶用法的方案详解
2024-04-02

React 高阶组件与Render Props优缺点详解

这篇文章主要weidajai 介绍了React 高阶组件与Render Props优缺点详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2022-11-16

React高阶组件优化文件结构流程详解

高阶组件就是接受一个组件作为参数并返回一个新组件(功能增强的组件)的函数。这里需要注意高阶组件是一个函数,并不是组件,这一点一定要注意,本文给大家分享React高阶组件HOC使用小结,一起看看吧
2023-01-29

React-Native中一些常用组件的用法详解(一)

前言本文为大家介绍一下React-Native中一些常用的组件,由于对ES6的语法并没有完全掌握,这里暂时用ES5和ES6混用的语法。View组件View是一个支持Flexbox布局、样式、一些触摸处理、和一些无障碍功能的容器,并且它可以放
2023-05-31

React组件的用法概述

React组件用来实现局部功能效果的代码和资源的集合(html/css/js/image等等),这篇文章主要介绍了React组件的用法和理解,需要的朋友可以参考下
2023-02-17

React组件的使用详细讲解

React组件分为函数组件与class组件;函数组件是无状态组件,class称为类组件;函数组件只有props,没有自己的私有数据和生命周期函数;class组件有自己私有数据(this.state)和生命周期函数
2022-11-16

如何使用React高阶组件解决横切关注点问题

这篇文章主要介绍“如何使用React高阶组件解决横切关注点问题”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“如何使用React高阶组件解决横切关注点问题”文章能帮助大家解决问题。高阶组件(HOC)概
2023-07-04

react component function组件使用详解

这篇文章主要为大家介绍了react component function组件的使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2022-11-13

react-redux的connect用法详解

react-redux是react官方推出的redux绑定库,React-Redux将所有组件分成两大类一个是UI组件和容器组件,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
2023-01-31

编程热搜

目录