React高阶组件

本文介绍了React高阶组件(HOC),它是一种实现状态逻辑复用的技术,采用包装(装饰)模式。高阶组件是接收组件并返回增强版组件的函数,通过在内部创建类组件并传递复用状态。使用步骤包括创建以with开头的函数,指定组件参数,创建内部类组件并渲染参数组件,最后设置displayName以方便调试。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.概述

  • 目的:实现状态逻辑复用

  • 采用 包装(装饰)模式

  • 比如 手机:获取保护功能

  •      手机壳: 提供保护功能
    
  • 高阶组件就相当于手机壳,通过包装组件,增强组件功能。

  • 高阶组件(HOC,Higher-OrderComponent)是一个函数,接收要包装的组件,返回增强后的组件

  • 高阶组件内部创建一个类组件,在这个类组件中提供复用的状态逻辑代码,通过prop将复用的状态传递给被包装组件 WrappedComponent

const EnhancedComponent = withHOC(WrappedComponent)

2. 使用步骤

  1. 创建一个函数,名称约定以 with 开头
  2. 指定函数参数,参数应该以大写字母开头(作为要渲染的组件)
  3. 在函数内部创建一个类组件,提供复用的状态逻辑代码,并返回
  4. 在该组件中,渲染参数组件,同时将状态通过 prop 传递给参数组件
  5. 调用该高阶组件,传入要增强的组件,通过返回值拿到增强后的组件,并将其渲染到页面中
/* 
  高阶组件
*/

import img from './images/cat.png'

// 创建高阶组件
function withMouse(WrappedComponent) {
  // 该组件提供复用的状态逻辑
  class Mouse extends React.Component {
    // 鼠标状态
    state = {
      x: 0,
      y: 0
    }

    handleMouseMove = e => {
      this.setState({
        x: e.clientX,
        y: e.clientY
      })
    }

    // 控制鼠标状态的逻辑
    componentDidMount() {
      window.addEventListener('mousemove', this.handleMouseMove)
    }

    componentWillUnmount() {
      window.removeEventListener('mousemove', this.handleMouseMove)
    }

    render() {
      return <WrappedComponent {...this.state} />
    }
  }

  return Mouse
}

// 用来测试高阶组件
const Position = props => (
  <p>
    鼠标当前位置:(x: {props.x}, y: {props.y})
  </p>
)

// 猫捉老鼠的组件:
const Cat = props => (
  <img
    src={img}
    alt=""
    style={{
      position: 'absolute',
      top: props.y - 64,
      left: props.x - 64
    }}
  />
)

// 获取增强后的组件:
const MousePosition = withMouse(Position)

// 调用高阶组件来增强猫捉老鼠的组件:
const MouseCat = withMouse(Cat)

class App extends React.Component {
  render() {
    return (
      <div>
        <h1>高阶组件</h1>
        {/* 渲染增强后的组件 */}
        <MousePosition />
        <MouseCat />
      </div>
    )
  }
}

ReactDOM.render(<App />, document.getElementById('root'))

3. 设置 displayName

  • 使用高阶组件存在的问题:得到的两个组件名称相同
  • 原因:默认情况下,React使用组件名称作为 displayName
  • 解决方式:为高阶组件设置displayName ,便于调试时区分不同的组件。
  • displayName 的作用:用于设置调试信息(ReactDeveloper Tools信息)
/* 
  高阶组件
*/

import img from './images/cat.png'

// 创建高阶组件
function withMouse(WrappedComponent) {
  // 该组件提供复用的状态逻辑
  class Mouse extends React.Component {
    // 鼠标状态
    state = {
      x: 0,
      y: 0
    }

    handleMouseMove = e => {
      this.setState({
        x: e.clientX,
        y: e.clientY
      })
    }

    // 控制鼠标状态的逻辑
    componentDidMount() {
      window.addEventListener('mousemove', this.handleMouseMove)
    }

    componentWillUnmount() {
      window.removeEventListener('mousemove', this.handleMouseMove)
    }

    render() {
      return <WrappedComponent {...this.state} />
    }
  }

  // 设置displayName
  Mouse.displayName = `WithMouse${getDisplayName(WrappedComponent)}`

  return Mouse
}

function getDisplayName(WrappedComponent) {
  return WrappedComponent.displayName || WrappedComponent.name || 'Component'
}

// 用来测试高阶组件
const Position = props => (
  <p>
    鼠标当前位置:(x: {props.x}, y: {props.y})
  </p>
)

// 猫捉老鼠的组件:
const Cat = props => (
  <img
    src={img}
    alt=""
    style={{
      position: 'absolute',
      top: props.y - 64,
      left: props.x - 64
    }}
  />
)

// 获取增强后的组件:
const MousePosition = withMouse(Position)

// 调用高阶组件来增强猫捉老鼠的组件:
const MouseCat = withMouse(Cat)

class App extends React.Component {
  render() {
    return (
      <div>
        <h1>高阶组件</h1>
        {/* 渲染增强后的组件 */}
        <MousePosition />
        <MouseCat />
      </div>
    )
  }
}
### React 高阶组件(HOC)的概念及用法 #### 1. 定义 高阶组件(Higher-Order Component,简称 HOC)是一种常见的 React 设计模式。其本质是一个函数,该函数接受一个组件作为输入参数,并返回一个新的组件[^1]。 #### 2. 使用场景 HOC 主要用于解决以下问题: - **代码复用与模块化**:通过封装通用逻辑到 HOC 中,减少重复代码。 - **增删改 props**:可以在不改变原始组件的情况下动态调整传入的属性。 - **渲染劫持**:控制子组件的渲染行为,比如条件渲染或数据预处理[^2]。 #### 3. 实现方式 HOC 的实现主要有两种方法: ##### 3.1 属性代理(Props Proxy) 这是最常见的 HOC 实现方式之一。通过将额外的 prop 或功能注入目标组件来增强它的能力。下面是一个简单的例子: ```javascript function withLogging(WrappedComponent) { return class WithLogging extends React.Component { componentDidMount() { console.log('Component has mounted'); } componentWillUnmount() { console.log('Component will unmount'); } render() { return <WrappedComponent {...this.props} />; } }; } ``` 在这个示例中,`withLogging` 是一个 HOC,它可以为任何组件添加日志记录的功能[^3]。 ##### 3.2 反向继承(Inheritance Inversion, II) 这种方式较少见,但也可以用来创建 HOC。它涉及让父组件继承自目标组件并覆盖某些方法或状态。不过由于 JSX 和 ES6 类语法的原因,在现代开发中更推荐使用 Props Proxy 方法。 #### 4. 示例 以下是官方文档中的经典案例——如何利用 HOC 来共享状态逻辑: 假设我们有一个需要显示加载指示器的应用程序部分,则可以构建这样一个 HOC: ```javascript import React from 'react'; // 创建一个名为 `withLoadingIndicator` 的 HOC function withLoadingIndicator(WrappedComponent) { return class LoadingIndicatorWrapper extends React.Component { constructor(props) { super(props); this.state = { isLoading: true }; } async componentDidMount() { await new Promise(resolve => setTimeout(resolve, 2000)); // 模拟异步操作 this.setState({ isLoading: false }); } render() { const { isLoading } = this.state; if (isLoading) { return <div>Loading...</div>; } return <WrappedComponent {...this.props} />; } }; } // 被包装的真实组件 const Content = () => ( <div> This is the content after loading completes. </div> ); export default withLoadingIndicator(Content); ``` 此代码片段展示了如何通过引入加载状态管理机制扩展基础组件的行为[^2]。 #### 5. 注意事项 当使用 HOC 时需注意以下几点: - 尽量保持原有组件接收到的 props 不变,除非有特殊需求才去修改它们。 - 如果项目依赖于热更新工具如 Fast Refresh,请测试确认这些特性不会破坏由 HOC 添加的新成员变量或方法[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值