React中类组件和函数组件的理解和区别

react代码模块分为类组件和函数组件。

语法和定义内部状态管理生命周期性能可读性和维护性上下文集成状态管理库等角度对比React中类组件和函数组件。

1、语法和定义

类组件:

使用 ES6 的类(class)语法定义的 React 组件。它们具有更复杂的功能,特别是在 React 16.8 之前,它们是唯一能够使用状态(state)和生命周期方法的组件。

特点:

  • 使用 class 关键字定义,并继承自 React.Component
  • 能够使用 state 来管理组件的内部状态。
  • 可以使用生命周期方法,如 componentDidMountcomponentDidUpdate componentWillUnmount 等。
  • 通过 this.props 来访问传递给组件的属性(props)。
import React, { Component } from 'react';

class HelloComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  increment = () => {
    this.setState({ count: this.state.count + 1 });
  }

  render() {
    return (
      <div>
        <p>Count: {this.state.count}</p>
        <button onClick={this.increment}>Increment</button>
      </div>
    );
  }
}

export default HelloComponent;

函数组件(Function Component):

函数组件是使用 JavaScript 函数定义的 React 组件。自 React 16.8 以来,函数组件通过引入 Hooks 可以实现状态管理和副作用处理,功能上已经与类组件基本等价。 

特点:

  • 使用 JavaScript 函数定义,通常是更简单和推荐的方式。
  • 在函数组件中,无法直接使用 this,而是通过 Hooks(如> useState useEffect)来管理状态和副作用。
  • 更加简洁,通常用于无状态组件,但在有状态需求时也可以使用 Hooks
import React, { useState } from 'react';

function HelloComponent() {
  const [count, setCount] = useState(0);

  const increment = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
    </div>
  );
}

export default HelloComponent;

 

2、内部状态管理

类组件:

使用类组件时,可以通过组件的内部状态(state)来管理组件的数据。

import React from 'react';
 
class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }
 
  render() {
    return (
      <div>
        <p>Count: {this.state.count}</p>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>Increase</button>
      </div>
    );
  }
}
 
export default Counter;

函数组件(Function Component):

函数组件可以使用hooks(React 16.8+)来管理内部状态。

useState钩子:

import React, { useState } from 'react';
 
function Counter() {
  const [count, setCount] = useState(0);
 
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increase</button>
    </div>
  );
}
 
export default Counter;

useReducer钩子(适用于复杂的状态逻辑):

import React, { useReducer } from 'react';
 
function Counter() {
  const [count, dispatch] = useReducer((state, action) => {
    switch (action.type) {
      case 'increment':
        return state + 1;
      case 'decrement':
        return state - 1;
      default:
        throw new Error();
    }
  }, 0);
 
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => dispatch({ type: 'increment' })}>Increase</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>Decrease</button>
    </div>
  );
}
 
export default Counter;

3、生命周期

类组件:

类组件生命周期(三个阶段:挂载阶段,更新阶段,卸载阶段)

挂载阶段执行顺序 :constructor->componentWillMount->render->componentDidMount

更新阶段执行顺序: shouldComponentUpdate->componentWillUpdate->render->componentDidUpdate

销毁阶段: componentWillUnmount

import React  from "react";
import {Link} from 'react-router-dom'
class Demo extends React.Component{
  
    constructor(props){
        super(props)
        console.log("constructor")
    }
    state = {
        num:1
    }
    UNSAFE_componentWillMount(){
        console.log("componentWillMount")
    }
    componentDidMount(){
        console.log("componentDidMount")
    }
    shouldComponentUpdate(){
      console.log('shouldComponentUpdate')
      return true
    }
    UNSAFE_omponentWillUpdate(){
        console.log("componentWillUpdate")
    }
    componentDidUpdate(){
        console.log("componentDidUpdate")
    }
    componentWillUnmount(){
        console.log("componentWillUnmount")
    }
    Submit = () =>  {
        this.setState({num:this.state.num+=1})
    }
    render(){
        console.log('render')
        return(
            <>
              <Link to='/app1'>App1</Link>
              //这里替换成自己的即可
              <h3>{this.state.num}</h3>
              <button onClick={this.Submit}>改变</button>
            </>
        )
    }
}
export default Demo

函数组件(Function Component):

函数组件本质没有生命周期,但是我们通过Hooks来模仿类组件当中的生命周期(也是三个阶段)

import { useState ,useEffect} from "react"
function App1 (){
    const [username ,setUsername] = useState('')
    const setChange = event => {
        setUsername(event.target.value);
      };
        // useEffect  =  vue mounted 区别是只要视图更新就变化 感觉类似watch 但是他又是初始化的 时候第一个
        //  useEffect(()=>{},[])
        useEffect(()=>{
          console.log('模拟componentDidMount第一次渲染', username)
            return () =>{
                console.log('模拟componentWillUnmount执行销毁后')
            }
        },[username])
    return(
        <>
          <input value={username} onChange={setChange}></input>
        </>
    )
}
export default  App1

4、性能

React类组件和函数组件之间的性能对比主要关注以下几个方面:

角度类组件函数组件
渲染性能在渲染时会进行shouldComponentUpdate生命周期检查需要使用React.memo或自定义比较逻辑来避免不必要的重渲染
状态更新可以在shouldComponentUpdate中实现更细粒度的更新检查需要使用React.memo或自定义比较逻辑来避免不必要的重渲染
组件的状态和生命周期复杂性可能会引入更多的对象和函数,这可能会影响GC(垃圾回收)-
内存占用因为其实例和可能的引用,可能会占用更多内存-

5、可读性和维护性

可读性和维护性是评估代码质量的重要指标。

  • 类组件的可读性和维护性可能不如函数组件。类组件中的this指向以及生命周期方法(如componentDidMount)可能会增加理解和维护的难度。

  • 函数组件的可读性和维护性较好,因为它们就像纯函数,更接近于数学函数的定义,更容易理解和维护。

  • 对于简单的组件,使用函数组件是首选,因为它们更简单且易于理解。

  • 对于需要管理状态或生命周期事件的组件,类组件是必须的。

  • 可以使用hooks(React 16.8+)来编写函数组件,它们可以让你在不编写类的情况下使用state和其他React特性。

如:类组件

class MyComponent 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>
    );
  }
}

函数组件(Function Component):

function MyComponent() {
  const [count, setCount] = React.useState(0);
 
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>Click me</button>
    </div>
  );
}

在这个例子中,函数组件MyComponent通过React.useState hook管理了状态,使得它的定义更接近于类组件的行为,同时更易于阅读和维护。 

6、上下文

类组件:可以通过this.context访问上下文。需要在类组件上使用static contextType声明期望访问的上下文,或者使用contextTypes属性进行类型检查(使用React 16.6之前的API)。

import React, { Component } from 'react';
 
class MyClassComponent extends Component {
  static contextType = MyContext; // 使用最新的context API
 
  componentDidMount() {
    const data = this.context; // 访问上下文
  }
 
  render() {
    return <div>My Class Component</div>;
  }
}

函数组件(Function Component):可以使用useContext钩子从React获取上下文。

import React, { useContext } from 'react';
 
function MyFunctionComponent() {
  const contextData = useContext(MyContext); // 使用hooks获取上下文
 
  return <div>My Function Component</div>;
}

注意:useContext只能在函数组件或者自定义钩子中使用。类组件不能使用这种方式访问上下文。

7、集成状态管理库

React中,类组件函数组件可以使用状态管理库来管理复杂的状态。常见的状态管理库有Redux、MobX、Context API等。

8、总结类组件、函数组件的优缺点

角度类组件函数组件
优点
  1. 完全控制:可以访问所有React生命周期的钩子。

  2. 状态(state)管理:可以维护和更新组件的状态。

  3. 复杂交互:类组件可以管理更复杂的交互,如动画、表单等。

  4. 性能优化:使用shouldComponentUpdate生命周期方法来优化渲染。

  1. 轻量级:函数组件不涉及创建类实例所带来的开销,并且它们自然阻止了this上的问题。

  2. 简单:代码通常更简洁,更容易编写和维护。

  3. Hooks:React 16.8+引入了Hooks,使函数组件可以使用状态(state)和其他React特性。

缺点
  1. 与函数组件相比,更多的开销,如创建类实例、绑定this等。

  2. 容易产生this指向问题,需要手动绑定this。

  1. 不能访问整个组件生命周期的所有钩子,例如componentDidCatch和componentDidMount。

  2. 对于复杂的交云,可能需要额外的库或自定义钩子。

  3. 不能使用ref属性,因为React无法在每次渲染时返回同一个函数实例。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/910853.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ruoyi-vue集成tianai-captcha验证码

后端代码 官方使用demo文档&#xff1a;http://doc.captcha.tianai.cloud/#%E4%BD%BF%E7%94%A8demo 我的完整代码&#xff1a;https://gitee.com/Min-Duck/RuoYi-Vue.git 主pom.xml 加入依赖 <!-- 滑块验证码 --><dependency><groupId>cloud.tianai.captc…

ctfshow(316)--XSS漏洞--反射性XSS

Web316 进入界面&#xff1a; 审计 显示是关于反射性XSS的题目。 思路 首先想到利用XSS平台解题&#xff0c;看其他师傅的wp提示flag是在cookie中。 当前页面的cookie是flagyou%20are%20not%20admin%20no%20flag。 但是这里我使用XSS平台&#xff0c;显示的cookie还是这样…

move_base

move_base 官方介绍&#xff1a;http://wiki.ros.org/move_base 如果在仿真环境下&#xff0c; sensor source、odometry source 和 sensor transforms 都已提供好&#xff0c;我们只需要完成以下部分&#xff1a; 一、编写导航程序 ①创建 ROS 工作空间 和 pkg 包 mkdir -p …

探索开放资源上指令微调语言模型的现状

人工智能咨询培训老师叶梓 转载标明出处 开放模型在经过适当的指令调整后&#xff0c;性能可以与最先进的专有模型相媲美。但目前缺乏全面的评估&#xff0c;使得跨模型比较变得困难。来自Allen Institute for AI和华盛顿大学的研究人员们进行了一项全面的研究&#xff0c;探索…

微信小程序uniapp基于Android的流浪动物管理系统 70c3u

文章目录 项目介绍具体实现截图技术介绍mvc设计模式小程序框架以及目录结构介绍错误处理和异常处理java类核心代码部分展示详细视频演示源码获取 项目介绍 以往流浪猫狗的救助网站相关信息的管理&#xff0c;都是工作人员手工统计。这种方式不但时效性低&#xff0c;而且需要查…

MiniWord

1.nuget 下载配置 2.引用 3. var value = new Dictionary<string, object>() { ["nianfen"] = nianfen, ["yuefen"] = yuefen, ["yuefenjian1"] = (int.Par…

【算法与数据结构】【链表篇】【题1-题5】

题1.从尾到头打印链表 题目&#xff1a;输入一个链表的头结点&#xff0c;从尾到头反过来打印出每个节点的值。链表的定义如下&#xff1a; struct ListNode {int mValue;ListNode *mNext;ListNode *mPrev; }; 1.1 方法一&#xff1a;栈 思路&#xff1a;要反过来打印&…

8.机器学习--决策树

(⊙﹏⊙)下周有要开组会&#xff0c;不知道该说啥&#xff0c;啊啊啊啊&#x1f62b; 目录 1.基本概念 2.ID3算法 3.C4.5算法 4.CART算法 5.连续与缺失值处理 5.1.连续值处理 5.2.缺失值处理 6.剪枝处理 6.1.预剪枝策略 6.2.后剪枝策略 7.实例代码 1.基本概念 提…

C#的6种常用集合类

一.先来说说数组的不足&#xff08;也可以说集合与数组的区别&#xff09;&#xff1a; 1.数组是固定大小的&#xff0c;不能伸缩。虽然System.Array.Resize这个泛型方法可以重置数组大小&#xff0c;但是该方法是重新创建新设置大小的数组&#xff0c;用的是旧数组的元素初始…

以太网交换安全:MAC地址漂移

一、什么是MAC地址漂移&#xff1f; MAC地址漂移是指设备上一个VLAN内有两个端口学习到同一个MAC地址&#xff0c;后学习到的MAC地址表项覆盖原MAC地址表项的现象。 MAC地址漂移的定义与现象 基本定义&#xff1a;MAC地址漂移发生在一个VLAN内的两个不同端口学习到相同的MAC地…

qt QHttpMultiPart详解

1. 概述 QHttpMultiPart是Qt框架中用于处理HTTP多部分请求的类。它类似于RFC 2046中描述的MIME multipart消息&#xff0c;允许在单个HTTP请求中包含多个数据部分&#xff0c;如文件、文本等。这种多部分请求在上传文件或发送带有附件的邮件等场景中非常有用。QHttpMultiPart类…

【SQL实验】高级查询(难点.三)含附加数据库操作

完整代码在文章末尾【代码是自己的解答&#xff0c;并非标准答案&#xff0c;也有可能写错&#xff0c;文中可能会有不准确或待完善之处&#xff0c;恳请各位读者不吝批评指正&#xff0c;共同促进学习交流】 将素材中的“学生管理”数据库附加到SQL SERVER中&#xff0c;完成以…

基于Spring Boot+Vue的助农销售平台(协同过滤算法、限流算法、支付宝沙盒支付、实时聊天、图形化分析)

&#x1f388;系统亮点&#xff1a;协同过滤算法、节流算法、支付宝沙盒支付、图形化分析、实时聊天&#xff1b; 一.系统开发工具与环境搭建 1.系统设计开发工具 后端使用Java编程语言的Spring boot框架 项目架构&#xff1a;B/S架构 运行环境&#xff1a;win10/win11、jdk1…

std::copy

std::copy 是 C 标准库中的一个算法&#xff0c;用于将一个序列中的元素复制到另一个位置。这个算法定义在 <algorithm> 头文件中。 --- 函数原型 std::copy 有几个不同的重载版本&#xff0c;但以下是最常用的两个&#xff1a; template <class InputIterator, c…

Linux之sed命令详解

文章目录 &#x1f34a;自我介绍&#x1f34a;sed概述&#x1f34a;sed语法讲解格式&#xff1a;options 命令选项{commmand}[flags] &#x1f34a;场景训练 你的点赞评论就是对博主最大的鼓励 当然喜欢的小伙伴可以&#xff1a;点赞关注评论收藏&#xff08;一键四连&#xff…

现代Web开发:React Hooks深入解析

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 现代Web开发&#xff1a;React Hooks深入解析 现代Web开发&#xff1a;React Hooks深入解析 现代Web开发&#xff1a;React Hook…

大语言模型(LLM)入门级选手初学教程 III

指令微调 一、指令数据的构建 包括任务描述&#xff08;也称为指令&#xff09;、任务输入-任务输出以及可选的示例。 Self-Instruct 指令数据生成&#xff1a;从任务池中随机选取少量指令数据作为示例&#xff0c;并针对Chat-GPT 设计精细指令来提示模型生成新的微调数据…

算法工程师重生之第四十六天(字符串接龙 有向图的完全可达性 岛屿的周长)

参考文献 代码随想录 一、字符串接龙 题目描述 字典 strList 中从字符串 beginStr 和 endStr 的转换序列是一个按下述规格形成的序列&#xff1a; 1. 序列中第一个字符串是 beginStr。 2. 序列中最后一个字符串是 endStr。 3. 每次转换只能改变一个字符。 4. 转换过程…

魅力标签云,奇幻词云图 —— 数据可视化新境界

目录 目的原理详解建议 标签云&#xff1a;用于汇总生成的标签&#xff0c;一般是独立词汇运行前的准备代码示例 词云&#xff1a;对本文中出现频率较高的词&#xff0c;视觉上突出显示总结 目的 掌握文本与文档可视化&#xff1a;使用特定软件或编程语言&#xff08;如Python…

云计算答案

情境一习题练习 一、选择题 1、在虚拟机VMware软件中实现联网过程&#xff0c;图中箭头所指的网络连接方式与下列哪个相关&#xff08; C &#xff09;。 A.仅主机模式 B.桥接 C.NAT D.嫁接 2、请问下图这个虚拟化架构属于什么类型&#xff08; A …