React JS 中的类组件

2025年1月7日 | 阅读 12 分钟

在 React.js 中,类组件是使用 JavaScript 类来创建和管理组件的一种方式。在引入带 Hooks 的函数组件之前,类组件一直是定义 React 组件的传统方式。尽管函数组件现在是构建 React 组件的首选方式,但类组件仍然受支持并在现有代码库中使用。

下面是一个简单的 React 类组件示例

  • 在此示例中,MyComponent 是一个继承自 React 库中的 Component 的类。构造函数用于初始化组件的状态。render 方法定义了组件应该渲染到 DOM 的内容。在这种情况下,它显示一个计数和一个按钮,当按钮被点击时,它会调用 incrementCount 方法,该方法会更新状态。
  • 类组件还支持 componentDidMount、componentDidUpdate 和 componentWillUnmount 等生命周期方法,用于管理组件生命周期中的副作用和交互。
  • 随着 React Hooks 的引入,函数组件提供了一种更简洁、更易读的方式来管理状态和副作用,使其成为编写 React 组件的首选。然而,类组件在遗留代码库中仍然具有相关性,并且在需要处理旧代码或与依赖类组件的库集成的情况下可能很有用。

生命周期方法

类组件带有一组生命周期方法,您可以覆盖这些方法来控制组件在其生命周期不同阶段的行为。以下是一些常用的生命周期方法

componentDidMount:此方法在组件渲染到 DOM 后调用。它通常用于数据获取、设置计时器或添加事件监听器等任务。

componentDidUpdate:此方法在组件的 props 或 state 发生更改时调用。它可以用于更新 DOM 或根据 props 或 state 的变化触发副作用等任务。

componentWillUnmount:此方法在组件从 DOM 中删除之前调用。这是清理在 componentDidMount 中创建的任何资源(例如计时器或事件监听器)的好地方。

状态管理

类组件使用 this.state 对象处理状态。您可以使用 this.setState() 更新状态。需要注意的是,this.setState 是异步的,React 可能会为了性能原因对它进行批量处理。如果您需要在更新状态后执行某个操作,可以将一个回调函数作为第二个参数传递给 this.setState。

类组件用法示例

让我们通过解释如何在另一个组件或您的应用程序中使用 MyComponent 类来扩展之前的示例。

在此示例中,我们导入了 MyComponent 类并在 App 函数组件中渲染了它。这就是您可以在应用程序中使用类组件的方式。

何时使用类组件

虽然带 Hooks 的函数组件是创建 React 组件的首选方式,但仍有情况您可能需要使用类组件

  • 遗留代码:如果您正在处理大量使用类组件的旧代码库,您可能需要维护或重构它们。
  • 集成:如果您需要与设计为类组件的第三方库或组件集成,您可能需要创建类组件以实现兼容性。
  • 复杂的状态管理:在少数情况下,当您有复杂的状态管理需求时,类组件的 setState 方法和生命周期方法可能提供更多控制。
  • 教学或学习 React:在教授或学习 React 时,类组件可以帮助演示生命周期方法和基于类的组件结构的理念,但请记住,这些知识最终应扩展到带 Hooks 的函数组件,以适应现代开发。

从类组件迁移到函数组件

如果您有一个使用类组件的现有代码库,并且想迁移到带 Hooks 的函数组件,您可以逐步进行。从将新组件创建为函数组件开始,然后根据需要逐步重构现有的类组件。您通常可以在函数组件中重用类组件中的逻辑和功能。

React 提供了 useState 和 useEffect 等 Hooks 来帮助您在函数组件中管理状态和副作用,从而使过渡更顺畅。

将 Props 传递给类组件

与函数组件一样,类组件也可以接收 props。您可以在类组件内的 this.props 对象中访问这些 props。以下是如何在类组件中传递和使用 props 的示例

在此示例中,Greeting 类组件接收一个 name prop,它使用该 prop 来显示个性化问候。当您在另一个组件中使用此组件时,您可以像这样传递 name prop

在类组件中处理事件

类组件可以通过定义事件处理方法来处理事件,例如用户点击。以下是一个示例

在此示例中,ClickCounter 类组件定义了一个 incrementCount 方法,当点击“Increment”按钮时,该方法会更新状态。

类属性和方法

您可以在类组件中定义自己的类属性和方法。这些属性和方法可用于管理状态和行为。

在此示例中,myProperty 是一个类属性,myMethod 是一个类方法。您可以使用 this.myProperty 在组件内访问 myProperty,并可以使用 this.myMethod() 调用 myMethod。

使用构造函数 vs. 类属性

在现代 JavaScript 和 React 中,您通常可以避免使用构造函数方法,而使用类属性来初始化状态和绑定方法。以下是如何使用类属性重写 ClickCounter 示例

在此更新的代码中,我们为 state 和 incrementCount 使用类属性,这使我们能够使用箭头函数自动绑定正确的上下文,从而无需在构造函数中手动绑定事件处理程序。

请记住,类组件虽然仍然受支持,但在现代 React 开发中越来越少见,由于其简洁性,带 Hooks 的函数组件通常是新项目的首选。但是,类组件对于维护和处理遗留代码库仍然很有价值。

与 React 类组件相关的信息

绑定方法

在类组件中,正确将事件处理方法绑定到组件实例非常重要。这可确保这些方法中的 this 关键字指向组件本身。您可以通过在构造函数中绑定方法、使用箭头函数或使用带箭头函数的类属性来实现,如前面的示例所示。

以下是如何在构造函数中手动绑定方法的

在此示例中,我们在构造函数中显式地将 handleClick 方法绑定到组件实例。

不可变地更新状态

在类组件中更新状态时,遵循 React 的不可变原则至关重要。与其直接修改状态,不如创建一个代表更新状态的新对象。然后,React 将比较新状态和先前状态,并有效地更新组件。

以下是如何在类组件中正确更新状态

使用 setState 的函数形式可确保您使用的是先前状态,并可防止在多个状态更新同时发生时出现潜在的竞态条件。

类组件和 React Context

类组件还可以使用 contextType 属性或 Consumer 组件从 React Context 中消耗数据。虽然带 Hooks 的函数组件通常用于处理 Context,但如果需要,您仍然可以使用类组件。

以下是使用 contextType 从 React Context 消耗数据的类组件的示例

在此示例中,MyComponent 类使用 contextType 静态属性从 MyContext 上下文消耗数据。

遗留支持

  • 虽然带 Hooks 的函数组件是构建 React 组件的现代方式,但类组件将继续得到 React 的支持和维护。如果您有一个现有代码库或需要与依赖类组件的库或项目一起工作,您仍然可以有效地使用它们。
  • 然而,建议为新项目学习和使用带 Hooks 的函数组件,因为它们提供了更简洁、更易读的编写 React 组件的方式,并符合 React 生态系统中的最新最佳实践。

调试类组件

在 React 中调试类组件时,您可以利用浏览器开发者工具和 React DevTools 扩展来更深入地了解组件的状态、props 和生命周期。

  • React DevTools:为您的浏览器安装 React DevTools 扩展。它允许您检查组件树、查看组件 props 和状态,并在开发过程中与组件进行交互。
  • 控制台日志:您可以在类组件方法中添加 console.log 语句,将值和调试信息打印到浏览器控制台。这有助于跟踪组件的流程并理解状态和 props 的变化。

React Strict Mode:开发过程中,您可以将应用程序包装在 React 的 Strict Mode 中,以捕获潜在问题并使用调试功能。它有助于识别组件中的副作用和潜在问题。

类组件在 Hooks 的背景下

随着 React Hooks 的引入,以前仅限于类组件的许多功能现在可以在函数组件中使用。例如

  • useState 和 useEffect Hooks 提供了类似于类组件状态和生命周期方法的状态管理和副作用处理。
  • useContext hook 允许函数组件从 React context 消耗数据。
  • 自定义 Hooks 使您能够跨组件封装和共享逻辑,类似于您在类组件中创建实用方法的方式。

因此,在现代 React 开发中,对类组件的需求已大大减少。在开始新项目时,通常建议使用带 Hooks 的函数组件,因为它们提供了更精简、更一致的组件构建方式。

然而,类组件仍然是 React 生态系统的一部分,并且仍在现有代码库中使用。开发人员应该熟悉类组件和带 Hooks 的函数组件,以便有效地处理不同年代和风格的 React 代码库。

测试类组件

测试 React 中的类组件是确保组件按预期工作的重要开发过程的一部分。您可以使用 Jest 和 React Testing Library 等测试库来达到此目的。

以下是使用 Jest 和 React Testing Library 测试类组件的基本示例

在此示例中,我们导入要测试的组件(MyComponent),渲染它,使用 fireEvent.click 模拟按钮点击,然后使用断言来验证组件是否正常工作。

在 React Router 中使用类组件

如果您正在使用 React Router,您可以将类组件用作路由组件。这是一个简单的例子

在此示例中,我们定义了类组件(Home 和 About),并将它们用作 App 组件中特定路由的组件。

类组件的弃用

  • 虽然 React 仍然支持类组件,但值得注意的是,React 团队一直在积极推广带 Hooks 的函数组件作为编写 React 代码的首选方式。React 中的许多新功能和改进都专注于函数组件,而类组件在某种程度上被认为是过时的。
  • 建议为新项目使用带 Hooks 的函数组件,并在适当的时候考虑重构现有的类组件。然而,类组件将继续工作,您可以根据需要维护和更新依赖它们的代码库。

性能考虑

在性能方面,带 Hooks 的函数组件通常比类组件更有效。函数组件通常更简洁,并且带有某些优化,例如可以使用 React.memo 高阶组件来防止不必要的重新渲染。

话虽如此,当正确使用时,类组件仍然可以具有高性能。您可以通过以下方式对其进行优化

使用 shouldComponentUpdate:通过实现 shouldComponentUpdate 生命周期方法,您可以根据 props 或 state 的变化来控制组件何时应重新渲染。这有助于防止不必要的重新渲染。

使用 PureComponent:您可以继承 PureComponent 类而不是 Component,以自动执行 props 和 state 的浅比较,以确定是否需要重新渲染。这可以在某些情况下节省性能。

Memoizing Methods:您可以使用 memoization 技术,例如在类属性中缓存昂贵计算的结果,以避免在每次渲染时重新计算它们。

类组件的优点和缺点

优点

  • 成熟:类组件自 React 早期就已存在,因此有大量的文档和可用资源。
  • 强大的生命周期控制:它们对组件生命周期提供了细粒度的控制,这在复杂场景中可能很有用。

缺点

  • 样板代码:与带 Hooks 的函数组件相比,类组件需要更多的样板代码。
  • 冗长:在类组件中管理状态和生命周期会使代码更加冗长,难以阅读。
  • 未来可能弃用:随着函数组件和 Hooks 的引入,类组件被认为不太现代化,React 团队已表示未来的开发和增强将侧重于函数组件。

总之,虽然类组件仍在使用于某些代码库,特别是遗留项目,但 React 开发的趋势是朝着带 Hooks 的函数组件发展,因为它们具有简洁性和可读性。建议在新项目中使用函数组件,并在可能的情况下考虑将类组件重构为函数组件。


下一个主题React 基础