文章目录

React 组件:函数组件与类组件对比

发布于 2026-04-16 01:22:52 · 浏览 22 次 · 评论 0 条

React 组件:函数组件与类组件对比

React 开发中,构建用户界面的基本单位是组件。目前最主流的组件定义方式有两种:函数组件和类组件。虽然随着 React 16.8 版本引入 Hooks 后,函数组件的功能已经非常强大,但在很多老旧项目或特定场景下,类组件依然存在。了解两者的区别与转换逻辑,是编写高质量 React 代码的基础。


1. 认识两种组件的定义方式

在代码层面,两者的写法有明显的结构差异。类组件是基于 ES6 Class 的语法糖,而函数组件本质就是一个 JavaScript 函数。

类组件

类组件必须继承自 React.Component,并且必须实现一个 render 方法,该方法返回 JSX。

import React, { Component } from 'react';

class CounterClass extends Component {
  constructor(props) {
    super(props);
    // 初始化状态
    this.state = {
      count: 0
    };
  }

  // 更新状态的方法
  increment = () => {
    this.setState({ count: this.state.count + 1 });
  };

  // 必须实现的渲染方法
  render() {
    return (
      <div>
        <p>当前计数: {this.state.count}</p>
        <button onClick={this.increment}>增加</button>
      </div>
    );
  }
}

export default CounterClass;

函数组件

函数组件没有 this,没有 render 方法,直接接收 props 并返回 JSX。

import React, { useState } from 'react';

function CounterFunction() {
  // 使用 Hook 声明状态
  const [count, setCount] = useState(0);

  const increment = () => {
    // 直接调用设置函数更新状态
    setCount(count + 1);
  };

  return (
    <div>
      <p>当前计数: {count}</p>
      <button onClick={increment}>增加</button>
    </div>
  );
}

export default CounterFunction;

2. 核心特性对比

通过以下表格,可以快速掌握两者在关键维度上的区别。

特性维度 类组件 函数组件
定义方式 使用 class 定义,继承 React.Component 使用 function 定义,是一个纯函数
内部状态 使用 this.state 存储数据 使用 useStateuseReducer Hook 存储数据
状态更新 必须调用 this.setState() 调用 State Hook 返回的更新函数(如 setCount
生命周期 拥有完整的生命周期方法(如 componentDidMount 使用 useEffect Hook 统一处理副作用
this 指向 需要处理 this 绑定问题(如 .bind(this) 或箭头函数) 不存在 this,无需绑定
性能优化 使用 React.PureComponentshouldComponentUpdate 使用 React.memouseMemouseCallback
代码量 较多,包含构造函数、render 方法等样板代码 较少,逻辑更加紧凑和直观
逻辑复用 主要依赖高阶组件(HOC)和 Render Props 使用自定义 Hooks 极其便捷

3. 状态与生命周期的转换实操

将类组件重构为函数组件是现代 React 开发的常见需求。重点关注状态管理和生命周期方法的映射。

3.1 状态管理迁移

在类组件中,状态通常是一个对象,通过 this.setState 进行合并更新;在函数组件中,推荐将状态拆分为多个独立的变量。

迁移步骤

  1. 移除 constructorthis.state
  2. 引入 useState Hook。
  3. this.state.count 替换为 count 变量。
  4. this.setState({ count: ... }) 替换为 setCount(...)

3.2 生命周期方法迁移

类组件的生命周期逻辑(如数据请求、订阅、手动修改 DOM)在函数组件中统一由 useEffect 接管。

迁移对照表

类组件生命周期 函数组件 useEffect 依赖项 说明
componentDidMount useEffect(() => { ... }, []) 空依赖数组表示仅在组件挂载后执行一次。
componentDidUpdate useEffect(() => { ... }, [someProp]) 依赖数组包含变量,当变量变化时执行。
componentWillUnmount useEffect(() => { return () => { ... } }, []) useEffect 的返回函数会在组件卸载前执行。

代码示例
假设一个组件需要在挂载时获取数据,并在卸载时清除计时器。

类组件写法

class DataComponent extends Component {
  state = { data: null };
  timer = null;

  componentDidMount() {
    // 模拟数据获取
    this.fetchData();
    // 设置计时器
    this.timer = setInterval(() => console.log('Tick'), 1000);
  }

  componentWillUnmount() {
    // 清除计时器
    clearInterval(this.timer);
  }

  fetchData = () => {
    // fetch logic...
    this.setState({ data: 'Loaded' });
  };

  render() {
    return <div>{this.state.data}</div>;
  }
}

函数组件转换写法

import React, { useState, useEffect } from 'react';

function DataComponent() {
  const [data, setData] = useState(null);

  useEffect(() => {
    // 对应 componentDidMount
    const fetchData = () => {
      // fetch logic...
      setData('Loaded');
    };
    fetchData();

    const timer = setInterval(() => console.log('Tick'), 1000);

    // 对应 componentWillUnmount
    return () => {
      clearInterval(timer);
    };
  }, []); // 空数组确保只运行一次

  return <div>{data}</div>;
}

4. 如何选择组件类型

在当前(2026年)的技术环境下,推荐策略如下:

优先选择函数组件

  1. 新建项目:默认使用函数组件配合 Hooks。代码更少,逻辑复用性更强,且是 React 官方推荐的发展方向。
  2. 逻辑复用:如果需要在多个组件间共享状态逻辑,自定义 Hooks 比高阶组件更简洁直观。
  3. 性能优化:利用 useMemouseCallback 可以更细粒度地控制渲染,避免类组件中繁琐的 this 判断。

保留类组件的情况

  1. 维护老项目:如果项目代码库中已经大量使用了类组件,且运行稳定,没有必要全部重写。
  2. 错误边界:目前错误边界组件必须使用类组件实现(因为依赖于 static getDerivedStateFromErrorcomponentDidCatch 生命周期)。
  3. 极其复杂的生命周期交互:虽然 useEffect 很强大,但在极少数涉及特定渲染阶段精确控制的复杂场景下,类组件的生命周期可能更符合直觉。

5. 注意闭包陷阱的特性差异

在函数组件中,每一次渲染都会拥有独立的 props 和 state。函数内部捕获的值是渲染那一时刻的值。而类组件中的 this 始终指向最新的组件实例。

这意味着,如果在函数组件中使用了异步操作(如 setTimeoutsetTimeout),需要注意回调函数中引用的 state 是否过期。

解决方法
使用 useRef 保存可变变量,或者使用 setState 的函数式更新形式(setCount(prev => prev + 1)),确保总是获取到最新的状态。

评论 (0)

暂无评论,快来抢沙发吧!

扫一扫,手机查看

扫描上方二维码,在手机上查看本文