当前位置: 首页 > news >正文

React 函数组件和类组件的区别

1. 定义方式

  • 函数组件:使用 ES6 的函数定义组件,接收 props 作为参数,返回一个 JSX 元素或 null。
function Welcome(props) {return <h1>Hello, {props.name}</h1>;
}
  • 类组件:使用 ES6 的类定义组件,继承自 React.Component,通过 render 方法返回 JSX。
class Welcome extends React.Component {render() {return <h1>Hello, {this.props.name}</h1>;}
}

2. 状态管理

  • 函数组件:在 React 16.8 之前,函数组件没有自己的状态,需要通过外部状态管理库(如 Redux)或父组件传值来管理状态。React 16.8 引入了 Hooks 后,函数组件可以通过 useState Hook 管理自己的状态。
import React, { useState } from 'react';function Counter() {const [count, setCount] = useState(0);return (<div><p>You clicked {count} times</p><button onClick={() => setCount(count + 1)}>Click me</button></div>);
}
  • 类组件:通过 this.state 来管理组件的内部状态,并使用 this.setState 方法来更新状态。
class Counter extends React.Component {constructor(props) {super(props);this.state = { count: 0 };}render() {return (<div><p>You clicked {this.state.count} times</p><button onClick={() => this.setState({ count: this.state.count + 1 })}>Click me</button></div>);}
}

3. 生命周期方法

  • 函数组件:没有生命周期方法,但在 React 16.8 引入 Hooks 后,可以通过 useEffect Hook 来实现类似生命周期的功能。
import React, { useState, useEffect } from 'react';function DataFetching() {const [data, setData] = useState([]);useEffect(() => {fetch('https://api.example.com/data').then(response => response.json()).then(data => setData(data));}, []); // 空数组表示类似 componentDidMount 的效果return (<div>{data.map(item => (<div key={item.id}>{item.name}</div>))}</div>);
}
  • 类组件:拥有多个生命周期方法,如 componentDidMount、componentDidUpdate、componentWillUnmount 等,这些方法在组件的挂载、更新和卸载过程中自动调用。
class DataFetching extends React.Component {constructor(props) {super(props);this.state = { data: [] };}componentDidMount() {fetch('https://api.example.com/data').then(response => response.json()).then(data => this.setState({ data }));}render() {return (<div>{this.state.data.map(item => (<div key={item.id}>{item.name}</div>))}</div>);}
}
  • 类组件:拥有多个生命周期方法,如 componentDidMount、componentDidUpdate、componentWillUnmount 等,这些方法在组件的挂载、更新和卸载过程中自动调用。
class DataFetching extends React.Component {constructor(props) {super(props);this.state = { data: [] };}componentDidMount() {fetch('https://api.example.com/data').then(response => response.json()).then(data => this.setState({ data }));}render() {return (<div>{this.state.data.map(item => (<div key={item.id}>{item.name}</div>))}</div>);}
}

4. 组件的复用性

  • 函数组件:更易于复用逻辑,可以通过自定义 Hooks 来提取组件逻辑,实现逻辑的复用。
function useCounter(initialCount) {const [count, setCount] = useState(initialCount);const increment = () => setCount(count + 1);return { count, increment };
}function Counter() {const { count, increment } = useCounter(0);return (<div><p>You clicked {count} times</p><button onClick={increment}>Click me</button></div>);
}
  • 类组件:复用逻辑通常需要借助高阶组件(HOC)或继承的方式,相对来说更加复杂。

5. 性能优化

  • 函数组件:可以通过 React.memo 对组件进行性能优化,避免不必要的重渲染。
const MyComponent = React.memo(function MyComponent(props) {/* 只有 props 发生变化时才会重新渲染 */return /* ... */;
});
  • 类组件:可以通过 shouldComponentUpdate 方法来控制组件是否更新,从而优化性能。
class MyComponent extends React.Component {shouldComponentUpdate(nextProps, nextState) {return nextProps.value !== this.props.value || nextState.count !== this.state.count;}render() {/* ... */}
}

React.memo 和shouldComponentUpdate 详细讲解

React.memo

React.memo 是 React 提供的一个高阶组件,用于优化函数组件的性能。 当组件的 props 没有发生变化时,它可以阻止组件的不必要的重新渲染。

用法

import React, { memo } from 'react';const MyComponent = (props) => {console.log('MyComponent render', props.value);return <div>{props.value}</div>;
};// 使用 React.memo 包裹组件
const MemoizedMyComponent = memo(MyComponent, (prevProps, nextProps) => {// 自定义比较逻辑return prevProps.value === nextProps.value; // 如果返回 true,则不重新渲染
});// 在父组件中使用
function ParentComponent() {const [count, setCount] = useState(0);return (<div><button onClick={() => setCount(count + 1)}>Update Count</button><MemoizedMyComponent value={count} /></div>);
}

参数说明

  • 第一个参数:要被优化的函数组件。
  • 第二个参数(可选):一个比较函数,用于比较当前 props 和上一个 props。如果返回 true,组件不会重新渲染;如果返回 false,组件会重新渲染。如果不提供此函数,React 会使用默认的浅比较(shallow comparison)。

默认行为
如果不提供自定义的比较函数,React 会使用浅比较来判断 props 是否发生变化。浅比较会检查对象的引用是否相同,而不是进行深度比较。

const MemoizedMyComponent = memo(MyComponent);
shouldComponentUpdate

shouldComponentUpdate 是类组件中的一个生命周期方法,用于控制组件是否应该在状态或属性发生变化时重新渲染。 如果返回 false,组件不会重新渲染;如果返回 true,组件会重新渲染。

用法

class MyComponent extends React.Component {shouldComponentUpdate(nextProps, nextState) {// 自定义比较逻辑return nextProps.value !== this.props.value || nextState.count !== this.state.count;}render() {console.log('MyComponent render', this.props.value, this.state.count);return <div>{this.props.value}</div>;}
}// 在父组件中使用
function ParentComponent() {const [count, setCount] = useState(0);return (<div><button onClick={() => setCount(count + 1)}>Update Count</button><MyComponent value={count} /></div>);
}
对比
特性React.memoshouldComponentUpdate
适用组件类型函数组件类组件
使用方式高阶组件,包裹函数组件类组件的生命周期方法
参数两个参数:要优化的组件和自定义比较函数(可选)两个参数: 和
默认行为浅比较无默认行为,需要手动实现比较逻辑
性能影响优化函数组件的渲染性能优化类组件的渲染性能
适用场景简单的展示型函数组件,或需要根据 props 变化控制渲染的场景复杂的类组件,需要精细控制渲染逻辑的场景
代码简洁性代码简洁,易于使用需要手动实现比较逻辑,代码可能较为复杂
选择建议
  • 如果你使用的是函数组件,建议使用 React.memo 来优化性能。
  • 如果你使用的是类组件,建议使用 shouldComponentUpdate 来优化性能。
  • 在复杂的业务场景中,可以结合 React.memo 和 shouldComponentUpdate 来实现更精细的性能优化。

6. 代码简洁性

  • 函数组件:代码更为简洁,逻辑清晰,尤其是使用 Hooks 后,可以将相关逻辑放在一起,增强可读性。
  • 类组件:代码相对复杂,需要处理 this 的指向问题,且生命周期方法分散在不同地方,逻辑可能不够直观。

7. 使用场景

  • 函数组件:适用于简单的展示型组件或逻辑较为简单的场景,随着 Hooks 的引入,函数组件的功能得到了极大的增强,现在也被广泛用于复杂的业务场景。
  • 类组件:适用于需要管理复杂状态和生命周期的组件,或者在一些特殊的场景下(如需要使用 ref 来访问 DOM 节点)。

总结

特性函数组件类组件
定义方式使用函数定义,接收 参数,返回 JSX使用类定义,继承自 ,通过 方法返回 JSX
状态管理React 16.8 之前无状态,16.8 之后通过 Hook 管理状态通过 和 管理状态
生命周期方法无生命周期方法,通过 Hook 实现类似功能拥有多个生命周期方法,如 、 等
复用逻辑通过自定义 Hooks 复用逻辑通过高阶组件(HOC)或继承复用逻辑
性能优化使用使用
代码简洁性更为简洁,逻辑清晰代码相对复杂,需处理 指向
使用场景简单展示型组件或逻辑简单的场景,现在也适用于复杂业务场景复杂状态管理和生命周期控制的场景,或特殊场景(如需要访问 DOM 节点)
http://www.xdnf.cn/news/18541.html

相关文章:

  • Oracle日志系统之重做日志和归档日志
  • linux驱动之poll
  • k8s介绍与实践
  • android测试硬件工具 安卓硬件测试命令
  • AI Agents系列之AI代理架构体系
  • 解决splice改变原数组的BUG(拷贝数据)
  • threadLocal的内存泄漏及解决方法
  • python 对接支付宝账单流程及问题处理
  • 写论文时降AIGC和降重的一些注意事项
  • Linux系统之----冯诺依曼结构
  • 基础编程题目集 6-1 简单输出整数
  • CUDAfy的使用
  • 【工具】gtest
  • 2025年大一训练-DP1
  • 【Qt】初识Qt(二)
  • 多模态大语言模型arxiv论文略读(二十七)
  • python——字符串使用
  • linux 学习 4.1 目录查询的相关命令(不涉及修改的命令)
  • 电脑里的AI帮手:Open Interpreter智能助手食用指南
  • rocketMQ 常见问题记录
  • 010数论——算法备赛
  • 1panel第三方应用商店(本地商店)配置和使用
  • 实时直播弹幕系统设计
  • 面试算法高频08-动态规划-02
  • pgsql中使用jsonb的mybatis-plus和jps的配置
  • 初识Redis · 客户端“Hello world“
  • 研0大模型学习(第四、五天)
  • java输出HelloWorld
  • 微服务调用中的“大对象陷阱”:CPU飙高问题解析与优化
  • 华为openEuler操作系统全解析:起源、特性与生态对比