React为什么要使用函数式组件代替类组件?一文弄懂函数式组件的优势!

React为什么要使用函数式组件代替类组件?

1.什么是类组件和函数组件?

1.1 类组件

类组件就是基于ES6语法定义,需要继承React.compoent实现,是react早期的组件定义形式

示例代码:

javascript 复制代码
import React from 'react';
​
class Counter extends React.Component {
  // 初始化状态
  state = { count: 0 };
​
  // 事件处理方法
  handleIncrement = () => {
    // 更新状态(触发重新渲染)
    this.setState({ count: this.state.count + 1 });
  };
​
  // 生命周期方法:组件挂载后执行
  componentDidMount() {
    console.log('组件已挂载');
  }
​
  // 渲染 UI
  render() {
    return (
      <div>
        <p>计数:{this.state.count}</p>
        <button onClick={this.handleIncrement}>+1</button>
      </div>
    );
  }
}
​
export default Counter;

代码特征:

  • 需要使用class关键字,需要继承React.Component
  • 强依赖this关键字访问数据,this.state管理内部状态,this.setState来触发状态更新和组件渲染
  • 强依赖生命周期,手动实现在什么阶段干什么事情这一内容

1.2 函数式组件

以javascript函数形式定义组件

javascript 复制代码
import React, { useState, useEffect } from 'react';
​
// 函数组件接收 props(可选)
const Counter = (props) => {
  // 通过 useState 管理状态(替代 this.state 和 this.setState)
  const [count, setCount] = useState(0);
​
  // 事件处理函数(无需绑定 this)
  const handleIncrement = () => {
    setCount(count + 1); // 更新状态(触发重新渲染)
  };
​
  // 通过 useEffect 处理副作用(替代生命周期方法)
  useEffect(() => {
    console.log('组件已挂载或 count 变化');
    // 组件卸载时执行清理逻辑(替代 componentWillUnmount)
    return () => console.log('组件将卸载');
  }, [count]); // 依赖数组:仅当 count 变化时执行
​
  // 直接返回 UI(无需 render() 方法)
  return (
    <div>
      <p>计数:{count}</p>
      <button onClick={handleIncrement}>+1</button>
    </div>
  );
};
​
export default Counter;

代码特征:

  • 本质是一个普通函数,接收 props 作为参数,返回 JSX。(符合react的函数式原则,UI = f(props))
  • 早期(无 Hooks 时)只能是 "无状态组件"(仅依赖 props 渲染,无法管理内部状态),引入 Hooks 后可通过 useState 管理状态,通过 useEffect 处理副作用。
  • 无需 this 关键字,直接通过函数参数获取 props,逻辑独立,不依赖组件本身

2.为什么react后期逐渐使用函数式组件来代替类组件?

2.1 设计理念

类组件:对应的是面向对象的设计理念

函数式组件:对应的是函数式编程的设计理念

我们开发者编写的代码,应该是声明式的代码,即数据是如何变化的代码

然后react框架的工作应该是,把声明式的代码,转换成命令式的DOM操作

即数据和渲染是强绑定的

但是,类组件对这方面具有其局限性

2.2 类组件的局限性

2.2.1 类组件的数据和渲染存在天然的割裂

因为类组件强依赖于this的指向,对于react的设计理念来说,应该无论如何,输入一个data,都应该可以准确的渲染到ui上面去,但是由于this指向的可变性,导致如果this的绑定错误的话,数据的变化无法准确的反映在页面上面,这不符合函数式设计的理念

2.2.2 类组件具有命令式编程的痕迹

react推崇的声明式编程,开发者应该只关心(UI是什么样的),而不必关心(如何通过DOM操作来实现这种变化)

但是类组件的生命周期的设计,使得开发者需要去做这样一件事情(开发者需要手动去控制在什么时机执行什么事情

取而代之,函数式+hook的做法更贴合声明式,useEffect这个hook,可以实现当依赖变化的时候自动更新UI,无需开发者手动关心时机,只需要描述UI与数据的依赖关系

2.2.3 类组件使逻辑强依赖组件,无法抽离逻辑本身
ini 复制代码
class UserForm extends React.Component {
  state = { username: '', password: '', error: '' };
​
  // 事件处理逻辑
  handleInputChange = (e) => { ... };
​
  // 数据验证逻辑
  validateForm = () => { ... };
​
  // API 请求逻辑
  submitForm = async () => { ... };
​
  render() { ... }
}

比如上述这段代码,一个组件里面的所有逻辑,都与组件物理绑定,通过state绑定,无法抽离

php 复制代码
// 抽离的验证逻辑(完全独立,不依赖任何组件)
function useFormValidation(initialValues) {
  const [values, setValues] = useState(initialValues);
  const [error, setError] = useState('');
​
  const validate = () => {
    if (!values.username) setError('用户名不能为空');
    // ... 其他验证逻辑
  };
​
  return { values, setValues, error, validate };
}
​
// 在组件中复用
function UserForm() {
  const { values, setValues, error, validate } = useFormValidation({ username: '', password: '' });
  // ... 直接使用复用的逻辑
}
​
// 另一个组件也能复用
function ProfileForm() {
  const { values, setValues, error, validate } = useFormValidation({ name: '', age: '' });
  // ...
}

而对于函数式组件来说,可以抽离逻辑,在多个组件进行复用

2.2.4 类组件封装的内容过于庞大

类组件通常内部已经封装好了许多内容,比如各种生命周期,但对于一些简单的组件,从头编写一个类组件显得十分繁杂,许多内容不是必须项

相关推荐
小小前端_我自坚强3 小时前
Vue 3 使用心得
前端·javascript·vue.js
GBVFtou3 小时前
浏览器嵌套兼容处理
前端
华仔啊3 小时前
前端真的需要懂算法吗?该怎么样学习?
前端·javascript
笔尖的记忆3 小时前
【前端架构和框架】react准备知识
前端·javascript
拜无忧3 小时前
【小游戏】逃逸小球h5,登录背景,缺口逃逸小球多边形
前端
烛阴3 小时前
Python 列表推导式:让你的代码更优雅、更高效
前端·python
文心快码BaiduComate3 小时前
开工不累,双强护航:文心快码接入 DeepSeek-V3.2-Exp和 GLM-4.6,助你节后高效Coding
前端·人工智能·后端
快乐是一切4 小时前
PDF底层格式之水印解析与去除机制分析
前端·数据结构
麋鹿原4 小时前
Android Room 数据库之简单上手
前端·kotlin