React Class 组件与函数组件全方位对比

发布于:2025-02-10 ⋅ 阅读:(36) ⋅ 点赞:(0)

一、定义方式和语法结构

  • Class组件
    • 使用ES6的class关键字来定义,并且需要继承React.Component
    • 例如:
      import React, { Component } from 'react';
      
      class MyClassComponent extends Component {
        render() {
          return <div>Class Component</div>;
        }
      }
      
  • 函数组件
    • 使用函数来定义,函数接收props作为参数,并且返回一个React元素。
    • 例如:
      import React from 'react';
      
      function MyFunctionComponent(props) {
        return <div>Function Component</div>;
      }
      

二、状态管理(State)

  • Class组件
    • 有自己的内部状态(state),通过this.state来访问,并且可以通过this.setState()方法来更新状态。
    • 状态初始化通常在constructor中进行。
    • 例如:
      class MyClassComponent extends Component {
        constructor(props) {
          super(props);
          this.state = {
            count: 0
          };
        }
      
        incrementCount = () => {
          this.setState(prevState => ({
            count: prevState.count + 1
          }));
        }
      
        render() {
          return (
            <div>
              <p>Count: {this.state.count}</p>
              <button onClick={this.incrementCount}>Increment</button>
            </div>
          );
        }
      }
      
  • 函数组件
    • 在早期版本中没有自己的状态,但从React 16.8引入Hooks后,可以使用useState钩子来添加状态。
    • 例如:
      import React, { useState } from 'react';
      
      function MyFunctionComponent() {
        const [count, setCount] = useState(0);
      
        const incrementCount = () => {
          setCount(prevCount => prevCount + 1);
        }
      
        return (
          <div>
            <p>Count: {count}</p>
            <button onClick={incrementCount}>Increment</button>
          </div>
        );
      }
      

三、生命周期方法(Lifecycle Methods)

  • Class组件
    • 有一系列的生命周期方法,如componentDidMountcomponentDidUpdatecomponentWillUnmount等,用于在组件的不同阶段执行特定操作。
    • 例如:
      class MyClassComponent extends Component {
        componentDidMount() {
          console.log('Component did mount');
        }
      
        componentDidUpdate() {
          console.log('Component did update');
        }
      
        componentWillUnmount() {
          console.log('Component will unmount');
        }
      
        render() {
          return <div>Class Component</div>;
        }
      }
      
  • 函数组件
    • 在没有Hooks之前没有生命周期方法,但使用Hooks后,可以通过useEffect钩子来模拟生命周期行为。
    • 例如:
      import React, { useEffect } from 'react';
      
      function MyFunctionComponent() {
        useEffect(() => {
          console.log('Component did mount');
          return () => {
            console.log('Component will unmount');
          };
        }, []);
      
        return <div>Function Component</div>;
      }
      

四、性能优化

  • Class组件
    • 通常通过shouldComponentUpdate生命周期方法来进行性能优化,决定组件是否需要重新渲染。
    • 例如:
      class MyClassComponent extends Component {
        shouldComponentUpdate(nextProps, nextState) {
          // 只在count改变时重新渲染
          return this.state.count!== nextState.count;
        }
      
        render() {
          return <div>Class Component</div>;
        }
      }
      
  • 函数组件
    • 使用React.memo高阶组件或者useMemouseCallback钩子来进行性能优化。
    • 例如:
      import React, { useState, useCallback, memo } from 'react';
      
      const MyFunctionComponent = memo(({ count }) => {
        return <div>Function Component - Count: {count}</div>;
      });
      
      function ParentComponent() {
        const [count, setCount] = useState(0);
        const incrementCount = useCallback(() => {
          setCount(prevCount => prevCount + 1);
        }, []);
      
        return (
          <div>
            <MyFunctionComponent count={count} />
            <button onClick={incrementCount}>Increment</button>
          </div>
        );
      }
      

五、上下文使用

  • Class组件
    • 使用this.context来访问上下文数据,并且需要定义contextType属性来指定上下文的类型。
    • 例如:
      import React, { Component } from 'react';
      
      class MyClassComponent extends Component {
        static contextTypes = {
          theme: PropTypes.string
        };
      
        render() {
          return <div>Theme: {this.context.theme}</div>;
        }
      }
      
  • 函数组件
    • 使用useContext钩子来访问上下文数据。
    • 例如:
      import React, { useContext } from 'react';
      
      const ThemeContext = React.createContext('light');
      
      function MyFunctionComponent() {
        const theme = useContext(ThemeContext);
        return <div>Theme: {theme}</div>;
      }
      

六、事件绑定

  • Class组件
    • 事件绑定通常在constructor中进行,或者使用类字段属性来绑定。
    • 例如:
      class MyClassComponent extends Component {
        constructor(props) {
          super(props);
          this.handleClick = this.handleClick.bind(this);
        }
      
        handleClick() {
          console.log('Button clicked');
        }
      
        render() {
          return <button onClick={this.handleClick}>Click me</button>;
        }
      }
      
    • 或者使用类字段属性(需要Babel插件支持):
      class MyClassComponent extends Component {
        handleClick = () => {
          console.log('Button clicked');
        }
      
        render() {
          return <button onClick={this.handleClick}>Click me</button>;
        }
      }
      
  • 函数组件
    • 事件绑定直接在函数内部定义,无需额外的绑定操作。
    • 例如:
      function MyFunctionComponent() {
        const handleClick = () => {
          console.log('Button clicked');
        };
      
        return <button onClick={handleClick}>Click me</button>;
      }
      

七、渲染机制与性能差异基础

  • Class组件
    • Class组件基于类的继承来构建,有自己的生命周期方法。在每次更新时,它会根据shouldComponentUpdate生命周期方法的返回值来决定是否重新渲染。如果没有实现shouldComponentUpdate,只要父组件重新渲染或者自身的stateprops有变化,组件就会重新渲染。
    • 例如,在一个有多个子组件的父组件中,如果一个无关子组件的state变化导致父组件重新渲染,那么没有优化的Class子组件也会跟着重新渲染。
  • 函数组件
    • 函数组件本身是无状态的(在没有Hooks之前),在React 16.8引入Hooks后,可以使用useStateuseEffect等Hooks来处理状态和副作用。函数组件的重新渲染取决于其依赖项的变化。
    • 例如,使用React.memo高阶组件可以对函数组件进行简单的性能优化,它类似于Class组件中的shouldComponentUpdate,会对props进行浅比较,只有props变化时才重新渲染。

八、代码可读性和简洁性

  • Class组件
    • 由于有较多的模板代码(如constructorsuper、生命周期方法等),代码可能相对冗长。
  • 函数组件
    • 特别是在使用Hooks后,代码通常更加简洁和直观,能够以更函数式的风格编写。