欢迎光临
我们一直在努力

React类组件与函数组件详解:掌握两种组件的核心差异与选型策略

一、React组件概述

1.1 React组件的基本概念

React组件是构建用户界面的独立、可复用的代码单元。组件可以将复杂的UI拆分成多个独立、可维护的部分,每个组件负责渲染页面中的一部分内容。在React中,组件接收输入(props)并返回描述屏幕展示内容的React元素。

1.2 组件化开发的优势

组件化开发带来了诸多好处,包括代码复用性提升、维护成本降低、团队协作效率提高等。通过组件化,开发者可以像搭积木一样快速构建复杂的应用界面,同时每个组件都可以独立测试和开发。

1.3 React组件的两大分类

在React的发展历程中,主要存在两种组件形式:类组件和函数组件。类组件是React早期的主要编写方式,而函数组件随着Hooks的引入逐渐成为主流。下面通过流程图展示两者的关系与核心特征:

#publish-mermaid-1787762378893-0{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#publish-mermaid-1787762378893-0 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#publish-mermaid-1787762378893-0 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#publish-mermaid-1787762378893-0 .error-icon{fill:#552222;}#publish-mermaid-1787762378893-0 .error-text{fill:#552222;stroke:#552222;}#publish-mermaid-1787762378893-0 .edge-thickness-normal{stroke-width:1px;}#publish-mermaid-1787762378893-0 .edge-thickness-thick{stroke-width:3.5px;}#publish-mermaid-1787762378893-0 .edge-pattern-solid{stroke-dasharray:0;}#publish-mermaid-1787762378893-0 .edge-thickness-invisible{stroke-width:0;fill:none;}#publish-mermaid-1787762378893-0 .edge-pattern-dashed{stroke-dasharray:3;}#publish-mermaid-1787762378893-0 .edge-pattern-dotted{stroke-dasharray:2;}#publish-mermaid-1787762378893-0 .marker{fill:#333333;stroke:#333333;}#publish-mermaid-1787762378893-0 .marker.cross{stroke:#333333;}#publish-mermaid-1787762378893-0 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#publish-mermaid-1787762378893-0 p{margin:0;}#publish-mermaid-1787762378893-0 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#publish-mermaid-1787762378893-0 .cluster-label text{fill:#333;}#publish-mermaid-1787762378893-0 .cluster-label span{color:#333;}#publish-mermaid-1787762378893-0 .cluster-label span p{background-color:transparent;}#publish-mermaid-1787762378893-0 .label text,#publish-mermaid-1787762378893-0 span{fill:#333;color:#333;}#publish-mermaid-1787762378893-0 .node rect,#publish-mermaid-1787762378893-0 .node circle,#publish-mermaid-1787762378893-0 .node ellipse,#publish-mermaid-1787762378893-0 .node polygon,#publish-mermaid-1787762378893-0 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1787762378893-0 .rough-node .label text,#publish-mermaid-1787762378893-0 .node .label text,#publish-mermaid-1787762378893-0 .image-shape .label,#publish-mermaid-1787762378893-0 .icon-shape .label{text-anchor:middle;}#publish-mermaid-1787762378893-0 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#publish-mermaid-1787762378893-0 .rough-node .label,#publish-mermaid-1787762378893-0 .node .label,#publish-mermaid-1787762378893-0 .image-shape .label,#publish-mermaid-1787762378893-0 .icon-shape .label{text-align:center;}#publish-mermaid-1787762378893-0 .node.clickable{cursor:pointer;}#publish-mermaid-1787762378893-0 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#publish-mermaid-1787762378893-0 .arrowheadPath{fill:#333333;}#publish-mermaid-1787762378893-0 .edgePath .path{stroke:#333333;stroke-width:1px;}#publish-mermaid-1787762378893-0 .flowchart-link{stroke:#333333;fill:none;}#publish-mermaid-1787762378893-0 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1787762378893-0 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#publish-mermaid-1787762378893-0 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1787762378893-0 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#publish-mermaid-1787762378893-0 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#publish-mermaid-1787762378893-0 .cluster text{fill:#333;}#publish-mermaid-1787762378893-0 .cluster span{color:#333;}#publish-mermaid-1787762378893-0 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#publish-mermaid-1787762378893-0 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#publish-mermaid-1787762378893-0 rect.text{fill:none;stroke-width:0;}#publish-mermaid-1787762378893-0 .icon-shape,#publish-mermaid-1787762378893-0 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1787762378893-0 .icon-shape p,#publish-mermaid-1787762378893-0 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#publish-mermaid-1787762378893-0 .icon-shape .label rect,#publish-mermaid-1787762378893-0 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1787762378893-0 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#publish-mermaid-1787762378893-0 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#publish-mermaid-1787762378893-0 .node .neo-node{stroke:#9370DB;}#publish-mermaid-1787762378893-0 [data-look=\”neo\”].node rect,#publish-mermaid-1787762378893-0 [data-look=\”neo\”].cluster rect,#publish-mermaid-1787762378893-0 [data-look=\”neo\”].node polygon{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1787762378893-0 [data-look=\”neo\”].swimlane.cluster rect{filter:none;}#publish-mermaid-1787762378893-0 [data-look=\”neo\”].node path{stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1787762378893-0 [data-look=\”neo\”].node .outer-path{filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1787762378893-0 [data-look=\”neo\”].node .neo-line path{stroke:#9370DB;filter:none;}#publish-mermaid-1787762378893-0 [data-look=\”neo\”].node circle{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1787762378893-0 [data-look=\”neo\”].node circle .state-start{fill:#000000;}#publish-mermaid-1787762378893-0 [data-look=\”neo\”].icon-shape .icon{fill:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1787762378893-0 [data-look=\”neo\”].icon-shape .icon-neo path{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1787762378893-0 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

React组件

类组件 Class Component

函数组件 Function Component

继承 React.Component

使用 this.state 管理状态

使用生命周期方法

纯函数形式

使用 Hooks 管理状态

使用 Hooks 处理副作用

二、类组件详解

2.1 类组件的定义与基本结构

类组件是使用ES6 class语法定义的React组件,它必须继承自React.Component或React.PureComponent。类组件通过render方法返回要渲染的内容。以下是一个简单的类组件示例:

import React, { Component } from 'react';
class Welcome extends Component {
constructor(props) {
super(props);
this.state = {
message: 'Hello, React!'
};
}
render() {
return (
<div>
<h1>{this.state.message}</h1>
<p>Welcome, {this.props.name}</p>
</div>
);
}
}
export default Welcome;

2.2 类组件的状态管理(state)

类组件通过this.state来管理组件的内部状态,使用this.setState()方法更新状态。状态更新是异步的,React会将多个setState调用合并为一次更新以提高性能。

class Counter extends Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
increment = () => {
this.setState((prevState) => ({
count: prevState.count + 1
}));
};
render() {
return (
<div>
<p>Count: {this.state.count}</p>
<button onClick={this.increment}>Add</button>
</div>
);
}
}

2.3 类组件的生命周期方法

类组件提供了丰富的生命周期方法,分为三个阶段:挂载、更新和卸载。通过流程图可以清晰展示完整的生命周期执行流程:

#publish-mermaid-1787762379129-1{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#publish-mermaid-1787762379129-1 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#publish-mermaid-1787762379129-1 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#publish-mermaid-1787762379129-1 .error-icon{fill:#552222;}#publish-mermaid-1787762379129-1 .error-text{fill:#552222;stroke:#552222;}#publish-mermaid-1787762379129-1 .edge-thickness-normal{stroke-width:1px;}#publish-mermaid-1787762379129-1 .edge-thickness-thick{stroke-width:3.5px;}#publish-mermaid-1787762379129-1 .edge-pattern-solid{stroke-dasharray:0;}#publish-mermaid-1787762379129-1 .edge-thickness-invisible{stroke-width:0;fill:none;}#publish-mermaid-1787762379129-1 .edge-pattern-dashed{stroke-dasharray:3;}#publish-mermaid-1787762379129-1 .edge-pattern-dotted{stroke-dasharray:2;}#publish-mermaid-1787762379129-1 .marker{fill:#333333;stroke:#333333;}#publish-mermaid-1787762379129-1 .marker.cross{stroke:#333333;}#publish-mermaid-1787762379129-1 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#publish-mermaid-1787762379129-1 p{margin:0;}#publish-mermaid-1787762379129-1 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#publish-mermaid-1787762379129-1 .cluster-label text{fill:#333;}#publish-mermaid-1787762379129-1 .cluster-label span{color:#333;}#publish-mermaid-1787762379129-1 .cluster-label span p{background-color:transparent;}#publish-mermaid-1787762379129-1 .label text,#publish-mermaid-1787762379129-1 span{fill:#333;color:#333;}#publish-mermaid-1787762379129-1 .node rect,#publish-mermaid-1787762379129-1 .node circle,#publish-mermaid-1787762379129-1 .node ellipse,#publish-mermaid-1787762379129-1 .node polygon,#publish-mermaid-1787762379129-1 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1787762379129-1 .rough-node .label text,#publish-mermaid-1787762379129-1 .node .label text,#publish-mermaid-1787762379129-1 .image-shape .label,#publish-mermaid-1787762379129-1 .icon-shape .label{text-anchor:middle;}#publish-mermaid-1787762379129-1 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#publish-mermaid-1787762379129-1 .rough-node .label,#publish-mermaid-1787762379129-1 .node .label,#publish-mermaid-1787762379129-1 .image-shape .label,#publish-mermaid-1787762379129-1 .icon-shape .label{text-align:center;}#publish-mermaid-1787762379129-1 .node.clickable{cursor:pointer;}#publish-mermaid-1787762379129-1 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#publish-mermaid-1787762379129-1 .arrowheadPath{fill:#333333;}#publish-mermaid-1787762379129-1 .edgePath .path{stroke:#333333;stroke-width:1px;}#publish-mermaid-1787762379129-1 .flowchart-link{stroke:#333333;fill:none;}#publish-mermaid-1787762379129-1 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1787762379129-1 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#publish-mermaid-1787762379129-1 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1787762379129-1 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#publish-mermaid-1787762379129-1 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#publish-mermaid-1787762379129-1 .cluster text{fill:#333;}#publish-mermaid-1787762379129-1 .cluster span{color:#333;}#publish-mermaid-1787762379129-1 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#publish-mermaid-1787762379129-1 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#publish-mermaid-1787762379129-1 rect.text{fill:none;stroke-width:0;}#publish-mermaid-1787762379129-1 .icon-shape,#publish-mermaid-1787762379129-1 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1787762379129-1 .icon-shape p,#publish-mermaid-1787762379129-1 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#publish-mermaid-1787762379129-1 .icon-shape .label rect,#publish-mermaid-1787762379129-1 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1787762379129-1 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#publish-mermaid-1787762379129-1 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#publish-mermaid-1787762379129-1 .node .neo-node{stroke:#9370DB;}#publish-mermaid-1787762379129-1 [data-look=\”neo\”].node rect,#publish-mermaid-1787762379129-1 [data-look=\”neo\”].cluster rect,#publish-mermaid-1787762379129-1 [data-look=\”neo\”].node polygon{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1787762379129-1 [data-look=\”neo\”].swimlane.cluster rect{filter:none;}#publish-mermaid-1787762379129-1 [data-look=\”neo\”].node path{stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1787762379129-1 [data-look=\”neo\”].node .outer-path{filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1787762379129-1 [data-look=\”neo\”].node .neo-line path{stroke:#9370DB;filter:none;}#publish-mermaid-1787762379129-1 [data-look=\”neo\”].node circle{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1787762379129-1 [data-look=\”neo\”].node circle .state-start{fill:#000000;}#publish-mermaid-1787762379129-1 [data-look=\”neo\”].icon-shape .icon{fill:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1787762379129-1 [data-look=\”neo\”].icon-shape .icon-neo path{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1787762379129-1 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

组件挂载 Mounting

constructor

getDerivedStateFromProps

render

componentDidMount

组件更新 Updating

getDerivedStateFromProps

shouldComponentUpdate

render

getSnapshotBeforeUpdate

componentDidUpdate

组件卸载 Unmounting

componentWillUnmount

常用生命周期方法说明:

  • constructor: 初始化state和绑定方法
  • componentDidMount: 组件挂载后调用,适合发起网络请求
  • componentDidUpdate: 组件更新后调用,可进行DOM操作
  • componentWillUnmount: 组件卸载前调用,用于清理定时器等
  • 2.4 类组件的事件处理

    类组件中事件处理需要注意this绑定问题。常见的绑定方式有以下几种:

    class EventHandler extends Component {
    constructor(props) {
    super(props);
    // 方式一:在构造函数中绑定
    this.handleClick = this.handleClick.bind(this);
    }
    handleClick() {
    console.log('Button clicked');
    }
    // 方式二:使用箭头函数(推荐)
    handleToggle = () => {
    console.log('Toggle clicked');
    };
    render() {
    return (
    <div>
    <button onClick={this.handleClick}>Click</button>
    <button onClick={this.handleToggle}>Toggle</button>
    {/* 方式三:在render中使用箭头函数 */}
    <button onClick={() => this.handleClick()}>Inline</button>
    </div>
    );
    }
    }

    2.5 类组件的Props使用

    类组件通过this.props访问传入的属性。Props是只读的,组件不应修改自身的props。

    class Greeting extends Component {
    render() {
    const { name, age } = this.props;
    return (
    <div>
    <p>Name: {name}</p>
    <p>Age: {age}</p>
    </div>
    );
    }
    }
    // 使用组件
    // <Greeting name="Alice" age={25} />

    三、函数组件详解

    3.1 函数组件的定义与基本结构

    函数组件是使用JavaScript函数定义的React组件,它接收props作为参数并返回JSX。函数组件没有this,无法使用state和生命周期(在Hooks出现之前)。以下是一个基本示例:

    import React from 'react';
    function Welcome(props) {
    return (
    <div>
    <h1>Hello, {props.name}</h1>
    </div>
    );
    }
    // 箭头函数形式
    const Greeting = ({ name }) => (
    <div>
    <h1>Hello, {name}</h1>
    </div>
    );
    export default Welcome;

    3.2 useState Hook状态管理

    useState是React提供的Hook,让函数组件能够使用状态。它返回一个数组,包含当前状态值和更新状态的函数。

    import React, { useState } from 'react';
    function Counter() {
    const [count, setCount] = useState(0);
    const [user, setUser] = useState({ name: '', age: 0 });
    const increment = () => {
    setCount(count + 1);
    };
    const updateUser = () => {
    setUser(prev => ({ …prev, name: 'Bob' }));
    };
    return (
    <div>
    <p>Count: {count}</p>
    <button onClick={increment}>Add</button>
    <button onClick={updateUser}>Update User</button>
    </div>
    );
    }

    3.3 useEffect Hook副作用处理

    useEffect让函数组件能够执行副作用操作,相当于类组件中componentDidMount、componentDidUpdate和componentWillUnmount的组合。

    import React, { useState, useEffect } from 'react';
    function DataFetcher() {
    const [data, setData] = useState(null);
    const [loading, setLoading] = useState(true);
    // 相当于 componentDidMount 和 componentDidUpdate
    useEffect(() => {
    fetch('https://api.example.com/data')
    .then(response => response.json())
    .then(data => {
    setData(data);
    setLoading(false);
    });
    }, []); // 空数组表示只在挂载时执行
    // 相当于 componentWillUnmount
    useEffect(() => {
    const timer = setInterval(() => {
    console.log('Timer running');
    }, 1000);
    return () => {
    clearInterval(timer);
    };
    }, []);
    if (loading) return <div>Loading…</div>;
    return <div>{JSON.stringify(data)}</div>;
    }

    3.4 其他常用Hooks介绍

    React提供了多种内置Hooks,以下是一些常用Hooks的使用示例:

    import React, {
    useState,
    useEffect,
    useContext,
    useReducer,
    useCallback,
    useMemo,
    useRef
    } from 'react';
    // useContext: 访问Context
    const ThemeContext = React.createContext('light');
    function ThemedButton() {
    const theme = useContext(ThemeContext);
    return <button>Current theme: {theme}</button>;
    }
    // useReducer: 复杂状态管理
    function todoReducer(state, action) {
    switch (action.type) {
    case 'add':
    return […state, action.payload];
    case 'remove':
    return state.filter((_, i) => i !== action.index);
    default:
    return state;
    }
    }
    function TodoList() {
    const [todos, dispatch] = useReducer(todoReducer, []);
    const addTodo = () => {
    dispatch({ type: 'add', payload: 'New Todo' });
    };
    return (
    <div>
    <button onClick={addTodo}>Add Todo</button>
    <ul>{todos.map((todo, i) => <li key={i}>{todo}</li>)}</ul>
    </div>
    );
    }
    // useCallback 和 useMemo: 性能优化
    function OptimizedComponent({ data }) {
    const [count, setCount] = useState(0);
    const memoizedValue = useMemo(() => {
    return data.map(item => item * 2);
    }, [data]);
    const handleClick = useCallback(() => {
    setCount(c => c + 1);
    }, []);
    return (
    <div>
    <p>Count: {count}</p>
    <button onClick={handleClick}>Click</button>
    </div>
    );
    }

    3.5 函数组件的事件处理与Props

    函数组件的事件处理更加简洁,无需考虑this绑定问题。Props直接作为函数参数传入。

    function UserCard({ user, onUpdate }) {
    const [editing, setEditing] = useState(false);
    const handleSave = () => {
    onUpdate(user.id);
    setEditing(false);
    };
    return (
    <div>
    <h3>{user.name}</h3>
    {editing ? (
    <button onClick={handleSave}>Save</button>
    ) : (
    <button onClick={() => setEditing(true)}>Edit</button>
    )}
    </div>
    );
    }

    四、类组件与函数组件的区别

    4.1 语法结构差异

    类组件使用ES6 class语法,需要继承React.Component;函数组件使用普通函数或箭头函数定义。通过流程图对比两者结构:

    #publish-mermaid-1787762379691-2{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#publish-mermaid-1787762379691-2 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#publish-mermaid-1787762379691-2 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#publish-mermaid-1787762379691-2 .error-icon{fill:#552222;}#publish-mermaid-1787762379691-2 .error-text{fill:#552222;stroke:#552222;}#publish-mermaid-1787762379691-2 .edge-thickness-normal{stroke-width:1px;}#publish-mermaid-1787762379691-2 .edge-thickness-thick{stroke-width:3.5px;}#publish-mermaid-1787762379691-2 .edge-pattern-solid{stroke-dasharray:0;}#publish-mermaid-1787762379691-2 .edge-thickness-invisible{stroke-width:0;fill:none;}#publish-mermaid-1787762379691-2 .edge-pattern-dashed{stroke-dasharray:3;}#publish-mermaid-1787762379691-2 .edge-pattern-dotted{stroke-dasharray:2;}#publish-mermaid-1787762379691-2 .marker{fill:#333333;stroke:#333333;}#publish-mermaid-1787762379691-2 .marker.cross{stroke:#333333;}#publish-mermaid-1787762379691-2 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#publish-mermaid-1787762379691-2 p{margin:0;}#publish-mermaid-1787762379691-2 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#publish-mermaid-1787762379691-2 .cluster-label text{fill:#333;}#publish-mermaid-1787762379691-2 .cluster-label span{color:#333;}#publish-mermaid-1787762379691-2 .cluster-label span p{background-color:transparent;}#publish-mermaid-1787762379691-2 .label text,#publish-mermaid-1787762379691-2 span{fill:#333;color:#333;}#publish-mermaid-1787762379691-2 .node rect,#publish-mermaid-1787762379691-2 .node circle,#publish-mermaid-1787762379691-2 .node ellipse,#publish-mermaid-1787762379691-2 .node polygon,#publish-mermaid-1787762379691-2 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1787762379691-2 .rough-node .label text,#publish-mermaid-1787762379691-2 .node .label text,#publish-mermaid-1787762379691-2 .image-shape .label,#publish-mermaid-1787762379691-2 .icon-shape .label{text-anchor:middle;}#publish-mermaid-1787762379691-2 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#publish-mermaid-1787762379691-2 .rough-node .label,#publish-mermaid-1787762379691-2 .node .label,#publish-mermaid-1787762379691-2 .image-shape .label,#publish-mermaid-1787762379691-2 .icon-shape .label{text-align:center;}#publish-mermaid-1787762379691-2 .node.clickable{cursor:pointer;}#publish-mermaid-1787762379691-2 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#publish-mermaid-1787762379691-2 .arrowheadPath{fill:#333333;}#publish-mermaid-1787762379691-2 .edgePath .path{stroke:#333333;stroke-width:1px;}#publish-mermaid-1787762379691-2 .flowchart-link{stroke:#333333;fill:none;}#publish-mermaid-1787762379691-2 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1787762379691-2 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#publish-mermaid-1787762379691-2 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1787762379691-2 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#publish-mermaid-1787762379691-2 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#publish-mermaid-1787762379691-2 .cluster text{fill:#333;}#publish-mermaid-1787762379691-2 .cluster span{color:#333;}#publish-mermaid-1787762379691-2 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#publish-mermaid-1787762379691-2 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#publish-mermaid-1787762379691-2 rect.text{fill:none;stroke-width:0;}#publish-mermaid-1787762379691-2 .icon-shape,#publish-mermaid-1787762379691-2 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1787762379691-2 .icon-shape p,#publish-mermaid-1787762379691-2 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#publish-mermaid-1787762379691-2 .icon-shape .label rect,#publish-mermaid-1787762379691-2 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1787762379691-2 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#publish-mermaid-1787762379691-2 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#publish-mermaid-1787762379691-2 .node .neo-node{stroke:#9370DB;}#publish-mermaid-1787762379691-2 [data-look=\”neo\”].node rect,#publish-mermaid-1787762379691-2 [data-look=\”neo\”].cluster rect,#publish-mermaid-1787762379691-2 [data-look=\”neo\”].node polygon{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1787762379691-2 [data-look=\”neo\”].swimlane.cluster rect{filter:none;}#publish-mermaid-1787762379691-2 [data-look=\”neo\”].node path{stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1787762379691-2 [data-look=\”neo\”].node .outer-path{filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1787762379691-2 [data-look=\”neo\”].node .neo-line path{stroke:#9370DB;filter:none;}#publish-mermaid-1787762379691-2 [data-look=\”neo\”].node circle{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1787762379691-2 [data-look=\”neo\”].node circle .state-start{fill:#000000;}#publish-mermaid-1787762379691-2 [data-look=\”neo\”].icon-shape .icon{fill:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1787762379691-2 [data-look=\”neo\”].icon-shape .icon-neo path{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1787762379691-2 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}函数组件 (Function Component)类组件 (Class Component)对应对应对应对应关键对比结果

    代码量

    类组件: 较多函数组件: 简洁

    学习曲线

    类组件: this绑定复杂函数组件: 更直观

    性能

    类组件: 较重函数组件: 更轻量

    逻辑复用

    类组件: HOC/Render Props函数组件: 自定义Hooks

    未来趋势

    React官方推荐函数组件 + Hooks

    class Component extends React.Component

    constructor初始化state和绑定方法

    render方法返回JSX

    生命周期方法

    this.state / this.props通过this访问

    挂载阶段componentDidMount

    更新阶段componentDidUpdate

    卸载阶段componentWillUnmount

    错误处理componentDidCatch

    执行副作用API调用/订阅

    清理工作取消订阅/清除定时器

    function Component props

    直接返回JSX

    Hooks函数

    props参数直接访问

    useState状态管理

    useEffect副作用处理

    useContext上下文访问

    useReducer复杂状态逻辑

    useCallback函数缓存

    useMemo值缓存

    useRefDOM引用/持久化

    useLayoutEffectDOM同步副作用

    自定义Hooks逻辑复用

    三个生命周期合一挂载/更新/卸载

    B3b的清理函数

    4.2 状态管理方式对比

    类组件使用this.state和this.setState管理状态;函数组件使用useState Hook。两者在状态更新上有明显差异:

    // 类组件
    class CounterClass extends Component {
    state = { count: 0 };
    increment = () => {
    this.setState({ count: this.state.count + 1 });
    };
    }
    // 函数组件
    function CounterFunc() {
    const [count, setCount] = useState(0);
    const increment = () => {
    setCount(count + 1);
    };
    }

    4.3 生命周期处理对比

    类组件使用明确的生命周期方法,函数组件使用useEffect Hook统一处理。对比表格如下:

    | 功能 | 类组件 | 函数组件 |

    |——|——–|———-|

    | 挂载后 | componentDidMount | useEffect(() => {}, []) |

    | 更新后 | componentDidUpdate | useEffect(() => {}) |

    | 卸载前 | componentWillUnmount | useEffect中return函数 |

    | 应该更新 | shouldComponentUpdate | React.memo |

    | 获取快照 | getSnapshotBeforeUpdate | 无直接对应 |

    4.4 性能表现对比

    函数组件在React 16.8之后通过Hooks优化,性能已与类组件相当甚至更优。主要差异如下:

  • 函数组件编译后体积更小
  • 函数组件无需创建组件实例
  • React.memo比PureComponent更灵活
  • Hooks避免了HOC和render props的嵌套地狱
  • 4.5 适用场景对比

    #publish-mermaid-1787762381019-3{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#publish-mermaid-1787762381019-3 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#publish-mermaid-1787762381019-3 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#publish-mermaid-1787762381019-3 .error-icon{fill:#552222;}#publish-mermaid-1787762381019-3 .error-text{fill:#552222;stroke:#552222;}#publish-mermaid-1787762381019-3 .edge-thickness-normal{stroke-width:1px;}#publish-mermaid-1787762381019-3 .edge-thickness-thick{stroke-width:3.5px;}#publish-mermaid-1787762381019-3 .edge-pattern-solid{stroke-dasharray:0;}#publish-mermaid-1787762381019-3 .edge-thickness-invisible{stroke-width:0;fill:none;}#publish-mermaid-1787762381019-3 .edge-pattern-dashed{stroke-dasharray:3;}#publish-mermaid-1787762381019-3 .edge-pattern-dotted{stroke-dasharray:2;}#publish-mermaid-1787762381019-3 .marker{fill:#333333;stroke:#333333;}#publish-mermaid-1787762381019-3 .marker.cross{stroke:#333333;}#publish-mermaid-1787762381019-3 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#publish-mermaid-1787762381019-3 p{margin:0;}#publish-mermaid-1787762381019-3 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#publish-mermaid-1787762381019-3 .cluster-label text{fill:#333;}#publish-mermaid-1787762381019-3 .cluster-label span{color:#333;}#publish-mermaid-1787762381019-3 .cluster-label span p{background-color:transparent;}#publish-mermaid-1787762381019-3 .label text,#publish-mermaid-1787762381019-3 span{fill:#333;color:#333;}#publish-mermaid-1787762381019-3 .node rect,#publish-mermaid-1787762381019-3 .node circle,#publish-mermaid-1787762381019-3 .node ellipse,#publish-mermaid-1787762381019-3 .node polygon,#publish-mermaid-1787762381019-3 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1787762381019-3 .rough-node .label text,#publish-mermaid-1787762381019-3 .node .label text,#publish-mermaid-1787762381019-3 .image-shape .label,#publish-mermaid-1787762381019-3 .icon-shape .label{text-anchor:middle;}#publish-mermaid-1787762381019-3 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#publish-mermaid-1787762381019-3 .rough-node .label,#publish-mermaid-1787762381019-3 .node .label,#publish-mermaid-1787762381019-3 .image-shape .label,#publish-mermaid-1787762381019-3 .icon-shape .label{text-align:center;}#publish-mermaid-1787762381019-3 .node.clickable{cursor:pointer;}#publish-mermaid-1787762381019-3 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#publish-mermaid-1787762381019-3 .arrowheadPath{fill:#333333;}#publish-mermaid-1787762381019-3 .edgePath .path{stroke:#333333;stroke-width:1px;}#publish-mermaid-1787762381019-3 .flowchart-link{stroke:#333333;fill:none;}#publish-mermaid-1787762381019-3 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1787762381019-3 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#publish-mermaid-1787762381019-3 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1787762381019-3 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#publish-mermaid-1787762381019-3 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#publish-mermaid-1787762381019-3 .cluster text{fill:#333;}#publish-mermaid-1787762381019-3 .cluster span{color:#333;}#publish-mermaid-1787762381019-3 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#publish-mermaid-1787762381019-3 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#publish-mermaid-1787762381019-3 rect.text{fill:none;stroke-width:0;}#publish-mermaid-1787762381019-3 .icon-shape,#publish-mermaid-1787762381019-3 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1787762381019-3 .icon-shape p,#publish-mermaid-1787762381019-3 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#publish-mermaid-1787762381019-3 .icon-shape .label rect,#publish-mermaid-1787762381019-3 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1787762381019-3 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#publish-mermaid-1787762381019-3 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#publish-mermaid-1787762381019-3 .node .neo-node{stroke:#9370DB;}#publish-mermaid-1787762381019-3 [data-look=\”neo\”].node rect,#publish-mermaid-1787762381019-3 [data-look=\”neo\”].cluster rect,#publish-mermaid-1787762381019-3 [data-look=\”neo\”].node polygon{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1787762381019-3 [data-look=\”neo\”].swimlane.cluster rect{filter:none;}#publish-mermaid-1787762381019-3 [data-look=\”neo\”].node path{stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1787762381019-3 [data-look=\”neo\”].node .outer-path{filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1787762381019-3 [data-look=\”neo\”].node .neo-line path{stroke:#9370DB;filter:none;}#publish-mermaid-1787762381019-3 [data-look=\”neo\”].node circle{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1787762381019-3 [data-look=\”neo\”].node circle .state-start{fill:#000000;}#publish-mermaid-1787762381019-3 [data-look=\”neo\”].icon-shape .icon{fill:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1787762381019-3 [data-look=\”neo\”].icon-shape .icon-neo path{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1787762381019-3 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}是否是否是否

    组件选择决策

    是否需要复杂生命周期?

    考虑类组件

    是否是遗留项目?

    保持现有类组件

    优先使用函数组件

    是否需要ErrorBoundary?

    必须用类组件

    可考虑重构为函数组件

    使用Hooks管理状态和副作用

    五、如何选择与最佳实践

    5.1 何时使用类组件

    虽然函数组件已成为主流,但以下场景仍需要使用类组件:

  • 需要实现ErrorBoundary错误边界
  • 遗留项目维护,不便于重构
  • 需要使用getSnapshotBeforeUpdate等特殊生命周期
  • 团队技术栈仍以类组件为主
  • 5.2 何时使用函数组件

    推荐在以下场景使用函数组件:

  • 新项目开发
  • 需要复用状态逻辑
  • 追求更简洁的代码结构
  • 需要更好的TypeScript支持
  • 5.3 类组件向函数组件迁移指南

    迁移步骤如下:

  • 将class转换为函数
  • 将this.state替换为useState
  • 将生命周期方法替换为useEffect
  • 将this.props替换为函数参数
  • 移除this绑定相关代码
  • 测试组件功能是否正常
  • // 迁移前:类组件
    class UserProfile extends Component {
    state = { user: null };
    componentDidMount() {
    fetchUser(this.props.userId).then(user => {
    this.setState({ user });
    });
    }
    render() {
    if (!this.state.user) return <div>Loading…</div>;
    return <div>{this.state.user.name}</div>;
    }
    }
    // 迁移后:函数组件
    function UserProfile({ userId }) {
    const [user, setUser] = useState(null);
    useEffect(() => {
    fetchUser(userId).then(setUser);
    }, [userId]);
    if (!user) return <div>Loading…</div>;
    return <div>{user.name}</div>;
    }

    赞(0)
    未经允许不得转载:171主机测评 » React类组件与函数组件详解:掌握两种组件的核心差异与选型策略
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址