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

React组件简介

组件

在 React 中,组件(Component) 是 UI 的基本构建块。可以把它理解为一个独立的、可复用的 UI 单元,类似于函数,它接受输入(props),然后返回 React 元素来描述 UI。

组件的简单使用

在 React 中,组件主要分为两种:类组件和函数组件。但是在 React 18+ 之后,以不推荐使用类组件,而是推荐使用函数组件。

函数组件本质上是一个 Javascript 函数,然后返回一个 JSX 结构。函数组件的名字必须以大写字母开头,否则 React 会将其视为一个 HTML 标签。

函数组件更简单,它没有 this, 编写和阅读更简单,而状态则是通过 React Hooks 来实现的。下面是一个简单的函数组件的例子:

//  定义组件
function Button() {// 组件内部的逻辑return (<button>Click me</button>);
}

这样我们就创建了一个 React 组件,接下来,我们可以在 App 组件中使用它:

function App() {return (<div><Button /></div>)
}

除了 Button 组件,App 组件本身也是组件,也就是说组件可以嵌套使用。

组件的特点

  1. 组件必须返回一个 JSX 结构(或 null)
  2. 组件名称必须大写(如 MyComponent,不能写 myComponent)
  3. 可以组合嵌套(组件可以包含其他组件)
  4. 可以接收 props(用于传递数据)

组件的状态

在 React 组件中,状态(State) 是指组件内部可变的数据,用于控制组件的行为和 UI 的变化。当 state 发生变化 时,React 会自动重新渲染组件,更新 UI。

为什么需要状态?

有些数据不会变,比如 props 传递过来的值,但有些数据是会随用户交互变化的,比如:

  • 计数器的数值
  • 按钮的开关状态
  • 输入框中的内容

这些会变化的数据 就应该存到组件的 state 中。例如:

import { useState } from "react";function Counter() {// useState(0) 表示 count 初始值为 0const [count, setCount] = useState(0);return (<div><p>当前计数:{count}</p>{/* 点击按钮时,修改 count 值 */}<button onClick={() => setCount(count + 1)}>+1</button></div>);
}export default Counter;

当点击 +1 按钮时,会调用 setCount 方法,将 count 的值加 1,然后 React 会重新渲染组件,更新 UI。具体来说当组件的 state 发生变化时,React 执行以下流程:

  1. 调用 setState 或 useState 进行状态更新
  2. React 触发组件的重新渲染(函数组件会重新执行,类组件会触发 render 方法
  3. 生成新的 Virtual DOM(虚拟 DOM)
  4. 比较新的 Virtual DOM 和旧的 Virtual DOM(Diffing 算法)
  5. 计算差异后更新真实 DOM(Reconciliation 过程)

React 通过 useState(或 setState)触发状态更新,然后采用 调度机制(Scheduler)+ 批量更新(Batching) 来通知浏览器进行重新渲染。这种机制类似于 Qt 的信号槽或者是发布-订阅模式。但是 React 的更新机制与 Qt 的信号槽不同的是,React 的更新机制是异步的,而 Qt 的信号槽是同步的。

Virtual DOM 机制

React 并不会直接操作 真实 DOM(Real DOM),而是使用 Virtual DOM 来提升性能。

虚拟 DOM(Virtual DOM) 是 React 在内存中的 JavaScript 对象,它描述了 UI 结构。

每次 state 变化时,React 会重新创建一个新的 Virtual DOM。

Diffing 算法(Diff 算法)

React 通过 Diffing 算法 比较「新的 Virtual DOM」和「旧的 Virtual DOM」,找出不同点,只更新发生变化的部分,避免整个页面的重新渲染。

Diff 算法流程

  1. 树形对比

     如果新的 Virtual DOM 和旧的 Virtual DOM 不是相同的组件,则直接销毁旧组件,创建新组件。如果它们是同一个组件,则继续向下比较子元素。
    
  2. 属性对比(Props Diffing)

     如果 props 发生变化,则更新对应的 DOM 属性。
    
  3. 子元素对比(Children Diffing)

     使用Key 机制优化列表渲染(key 帮助 React 识别哪些元素是新增、删除或移动的,我们在列表渲染中接触过 key 机制)。
    

Reconciliation(协调过程)

React 在 Diffing 之后,使用 Reconciliation(协调过程) 将「最小的变更」应用到真实 DOM:

  • 仅修改需要更新的 DOM 节点
  • 不会重新创建整个 DOM 结构
  • 性能更高,避免不必要的操作

React 如何知道状态发生了变化?

当我们调用 setState(类组件)或 useState(函数组件)时,React 内部执行以下操作:

  1. 记录状态变更

    React 维护着一个 state 和 nextState。

    当调用 setState(newState) 时,React 不会立即修改 state,而是先把 newState 放入更新队列。

  2. 触发调度(Scheduler 机制)

    React 不是立刻重新渲染,而是将更新任务提交给 Scheduler(调度器),并进行批处理优化。

  3. 标记 Fiber 节点为「需要更新」

    React 使用 Fiber 架构,每个组件对应一个 Fiber 节点,setState 会让 Fiber 节点进入「更新状态」,等待下一次渲染。

为什么 React 不是立即更新?

React 采用 批量更新(Batching) 机制:

  • 同一个事件循环内的多个 setState 只会触发一次渲染,减少不必要的更新,提高性能。
  • React 18 引入 Concurrent Mode,可以延迟低优先级的更新,提高流畅度。

useState 修改状态

我们还是以一个简单的 Demo 为例,展示如何使用 useState 修改状态:

import { useState } from "react";   // 引入 useState
function Counter() {const [count, setCount] = useState(0);   // 初始化 count 为 0return (<div><p>当前计数:{count}</p><button onClick={() => setCount(count + 1)}>+1</button><button onClick={() => setCount(count - 1)}>-1</button></div>)
}

const [count, setCount] = useState(0); 这行代码就类似于发布订阅模式中,订阅者注册自己所需要关注的事件或消息。这里可以理解为订阅者注册了 count 变化时,会收到通知,然后更新 count 的值。

在 React 中,useState 是一个 Hook,用于在函数组件中添加状态。它返回一个数组,数组的第一个元素是当前状态的值,第二个元素是一个函数,用于更新状态。

直接改变 count 的值,并不会触发组件的重新渲染,因为 React 是通过 setState 来触发组件的重新渲染的。因此需要调用 setCount 来更新 count 的值,然后 React 会重新渲染组件,更新 UI。

多个状态值管理

你可以在 useState 中存储多个值,例如:

function UserInfo() {const [user, setUser] = useState({ name: "Alice", age: 25 });return (<div><p>姓名:{user.name}</p><p>年龄:{user.age}</p><button onClick={() => setUser({ ...user, age: user.age + 1 })}>生日+1</button></div>);
}

这里使用了 …user(展开运算符)来避免覆盖 name,仅修改 age。

组件样式控制

在 React 中,控制组件的样式,可以直接在行内样式中设置,也可以使用 className 属性来设置类名,然后在 CSS 文件中定义样式。在工程化中,一般是使用 className 来控制样式。

行内样式

在 React 中,你可以在行内样式中设置样式,例如:

<div style={{ color: 'red', fontSize: '16px' }}>Hello World</div>

在上面的例子中,style 属性是一个对象,其中包含了 CSS 属性及其值。你可以使用驼峰命名法来设置 CSS 属性,例如 color 和 fontSize。如果觉得 style 属性太长,可以定义一个变量来存储样式对象,然后使用变量来设置样式。例如:

const style = {color: 'red',fontSize: '16px'
}
<div style={style}>Hello World</div>

通过 className 来控制样式

在 React 中,你可以使用 className 属性来控制组件的样式,例如:

在 CSS 文件中,你可以定义一个类名为 my-class 的样式,例如:

.my-class {color: red;font-size: 16px;
}

在组件中,你可以使用 className 属性来设置类名,例如:

import './App.css';
<div className="my-class">Hello World</div>

相关文章:

React组件简介

组件 在 React 中&#xff0c;组件&#xff08;Component&#xff09; 是 UI 的基本构建块。可以把它理解为一个独立的、可复用的 UI 单元&#xff0c;类似于函数&#xff0c;它接受输入&#xff08;props&#xff09;&#xff0c;然后返回 React 元素来描述 UI。 组件的简单…...

iOS常见网络框架

URLSession、Alamofire 和 Moya 1. URLSession 1.1 核心概念 URLSession 是 Apple 官方提供的网络请求 API&#xff0c;封装在 Foundation 框架中。它支持 HTTP、HTTPS、FTP 等协议&#xff0c;可用于&#xff1a; ​ • 普通网络请求&#xff08;GET/POST&#xff09; ​ …...

蓝桥杯备考---->激光炸弹(二维前缀和)

本题我们可以构造二维矩阵&#xff0c;然后根据题意&#xff0c;枚举所有边长为m的正方形&#xff0c;找到消灭价值最多的炸弹 #include <iostream> using namespace std; const int N 1e4; int a[N][N]; int n,m; int f[N][N]; int main() {cin >> n >> m…...

python笔记之判断月份有多少天

1、通过随机数作为目标月份 import random month random.randint(1,12)2、判断对应的年份是闰年还是平年 因为2月这个特殊月份&#xff0c;闰年有29天&#xff0c;而平年是28天&#xff0c;所以需要判断对应的年份属于闰年还是平年&#xff0c;代码如下 # 判断年份是闰年还…...

数据结构 --树和森林

树和森林 树的存储结构 树的逻辑结构 树是一种递归定义的数据结构 树是n(n≥0)个结点的有限集。当n0时&#xff0c;称为空树。在任意一棵非空树中应满足&#xff1a; 1)有且仅有一个特定的称为根的结点。 2)当n>1时&#xff0c;其余结点可分为m(m>0)个互不相交的有…...

QOpenGLWidget视频画面上绘制矩形框

一、QPainter绘制 在QOpenGLWidget中可以绘制&#xff0c;并且和OpenGL的内容叠在一起。paintGL里面绘制完视频后&#xff0c;解锁资源&#xff0c;再用QPainter绘制矩形框。这种方式灵活性最好。 void VideoGLWidget::paintGL() {glClear(GL_COLOR_BUFFER_BIT);m_program.bi…...

Linux系统加固笔记

检查口令为空的账户 判断依据&#xff1a;存在则不符合 特殊的shell a./bin/false:将用户的shell设置为/bin/false&#xff0c;用户会无法登录&#xff0c;并且不会有任何提示信息b./sbib/nologin&#xff1a;nologin会礼貌的向用户发送一条消息&#xff0c;并且拒绝用户登录…...

【Go万字洗髓经】Golang中sync.Mutex的单机锁:实现原理与底层源码

本章目录 1. sync.Mutex锁的基本用法2. sync.Mutex的核心原理自旋到阻塞的升级过程自旋CAS 饥饿模式 3. sync.Mutex底层源码Mutex结构定义全局常量Mutex.Lock()方法第一次CAS加锁能够成功的前提是&#xff1f;竞态检测 Mutex.lockSlow()lockSlow的局部变量自旋空转state新值构造…...

npm前端模块化编程

1. 代码编写 使用npm和Webpack进行前端模块化编程的完整案例。这个案例将创建一个简单的网页&#xff0c;该网页显示一个标题和一个按钮&#xff0c;点击按钮会在控制台中打印一条消息。 步骤 1: 初始化项目 创建项目目录并初始化npm&#xff1a; mkdir my-modular-fronten…...

Django REST framework 源码剖析-认证器详解(Authentication)

Django REST framework 源码剖析-认证器详解(Authentication) 身份验证始终在视图的最开始运行&#xff0c;在权限和限制检查发生之前&#xff0c;以及在允许任何其他代码继续之前。request.user属性通常设置为contrib.auth包的user类的实例。request.auth属性用于任何其他身份…...

TCP/IP三次握手的过程,为什么要3次?

一&#xff1a;过程 第一次&#xff08;SYN&#xff09;&#xff1a; 客户端发送一个带有SYN标志的TCP报文段给服务器&#xff0c;设置SYN1&#xff0c;并携带初始序列号Seqx&#xff08;随机值&#xff09;&#xff0c;进入SYN_SENT状态。等待服务器相应。 第二次&#xff08…...

Centos6安装nerdctl容器运行时

Centos6安装nerdctl容器运行时 前言Centos6安装docker---失败--不可拉取镜像docker配置国内镜像加速 Centos6安装nerdctl-full容器管理工具为Centos6配置containerd服务开机自启动设置nerdctl自动补全 前言 本文写于2025年3月22日,因一些特殊业务需要用到Centos6Docker,但Cent…...

登录验证码的接口实习,uuid,code.

UID是唯一标识的字符串,下面是百度百科关于UUID的定义&#xff1a; UUID是由一组32位数的16进制数字所构成&#xff0c;是故UUID理论上的总数为16322128&#xff0c;约等于3.4 x 10^38。也就是说若每纳秒产生1兆个UUID&#xff0c;要花100亿年才会将所有UUID用完。 UUID的标准…...

用fofa语法搜索漏洞

FOFA是一款非常强大的搜索引擎 关于对于fofa的描述是&#xff1a;FOFA&#xff08;网络空间资产检索系统&#xff09;是世界上数据覆盖更完整的IT设备搜索引擎&#xff0c;拥有全球联网IT设备更全的DNA信息。 探索全球互联网的资产信息&#xff0c;进行资产及漏洞影响范围分析…...

设计一个基于机器学习的光伏发电功率预测模型,以Python和Scikit - learn库为例

下面为你设计一个基于机器学习的光伏发电功率预测模型&#xff0c;以Python和Scikit - learn库为例。此模型借助历史气象数据和光伏发电功率数据来预测未来的光伏发电功率。 模型设计思路 数据收集&#xff1a;收集历史气象数据&#xff08;像温度、光照强度、湿度等&#xf…...

20242817李臻《Linux⾼级编程实践》第6周

20242817李臻《Linux⾼级编程实践》第6周 一、AI对学习内容的总结 Linux进程间通信&#xff08;IPC&#xff09; 1. 进程间通信基本概念 作用: 数据传输&#xff1a;进程间传递数据&#xff08;字节到兆字节级别&#xff09;。共享数据&#xff1a;多个进程操作同一数据&…...

Vue 3中的Provide与Inject

在Vue 3中&#xff0c;provide和inject机制为组件间的通信提供了一种新的方式。不同于传统的父子组件通过props传递数据的方式&#xff0c;provide和inject允许祖先组件向其所有子孙组件提供数据&#xff0c;而无需通过中间层手动传递。这使得跨层级的组件通信变得更加直接和简…...

深入解析SQL2API平台:数据交互革新者

在数字化转型持续深入的当下&#xff0c;企业对数据的高效利用与管理的需求愈发迫切。SQL2API平台应运而生&#xff0c;成为助力企业突破数据交互困境的有力工具&#xff0c;特别是它由麦聪软件基于DaaS&#xff08;数据即服务&#xff09;产品创新衍生而来&#xff0c;备受业界…...

蓝桥杯算法题分享(二)

蓝桥杯算法题分享 本文将继续分享三道经典的蓝桥杯算法题&#xff0c;包括题目描述、解题思路和 Java 代码实现&#xff0c;帮助大家更好地理解算法的应用。对算法感兴趣的朋友可以点开我的主页查看我上周分享的另三道题。 第一题&#xff1a;次数差 题目描述 x 星球有 26 只…...

实战-MySQL5.7升级8.0遇到的四个问题

近期几个项目的MySQL由5.7升级到8.0&#xff0c;升级过程中遇到四个问题&#xff0c;记录下来分享一下&#xff1a; 第一个问题详见之前的文章&#xff1a; MySQL 5.7升级8.0报异常&#xff1a;处理新增关键字 第二个问题详见之前的文章&#xff1a; MySQL 5.7升级8.0报异常…...

为什么递归用栈?动态分配用堆?

文章目录 1. 区别2. 栈空间特点优点缺点 3. 堆空间特点优点缺点 4. 栈和堆的对比5. 总结 1. 区别 栈空间和堆空间是程序内存中的两块不同区域&#xff0c;分别用于不同的用途。 栈空间&#xff1a; 栈空间是由操作系统自动管理的内存区域&#xff0c;用于存储局部变量、函数…...

Java 中装饰者模式与策略模式在埋点系统中的应用

前言 在软件开发中&#xff0c;装饰者模式和策略模式是两种常用的设计模式&#xff0c;它们在特定的业务场景下能够发挥巨大的作用。本文将通过一个实际的埋点系统案例&#xff0c;探讨如何在 Java 中运用装饰者模式和策略模式&#xff0c;以及如何结合工厂方法模式来优化代码…...

计算机视觉总结

以下是针对上述问题的详细解答,并结合代码示例进行说明: 1. 改进YOLOv5人脸检测模块,复杂光照场景准确率从98.2%提升至99.5% 优化具体过程: 光照补偿:在数据预处理阶段,采用自适应光照补偿算法,对图像进行实时增强,以减少光照变化对人脸检测的影响。数据增强:在训练…...

无人设备遥控器之调度自动化技术篇

一、技术原理 信息采集与处理&#xff1a; 通过传感器、仪表等设备采集无人设备的各种数据&#xff0c;如位置、速度、状态等。 将采集到的数据传输到调度自动化系统中进行处理和分析&#xff0c;以获取设备的实时状态。 系统建模与优化&#xff1a; 调度自动化系统会根据…...

【AI】Orin Nano+ubuntu22.04上移植YoloV11,并使用DeepStream测试成功

【AI】郭老二博文之:AI学习目录汇总 1、准备工作 使用 sdk-manager 烧写 OrinNano, JetPack版本为6.0 DP,对应操作系统为:Ubuntu22.04 参见博客:【NVIDIA】Jetson Orin Nano系列:烧写Ubuntu22.04 2、安装 PyTorch 2.1 下载依赖 1)安装onnx pip install onnx -i h…...

K8S学习之基础四十五:k8s中部署elasticsearch

k8s中部署elasticsearch 安装并启动nfs服务yum install nfs-utils -y systemctl start nfs systemctl enable nfs.service mkdir /data/v1 -p echo /data/v1 *(rw,no_root_squash) >> /etc/exports exports -arv systemctl restart nfs创建运行nfs-provisioner需要的sa账…...

如何在 Windows 上安装并使用 Postman?

Postman 是一个功能强大的API测试工具&#xff0c;它可以帮助程序员更轻松地测试和调试 API。在本文中&#xff0c;我们将讨论如何在 Windows 上安装和使用 Postman。 Windows 如何安装和使用 Postman 教程&#xff1f;...

Langchain 提示词(Prompt)

基本用法 1. 基本概念 提示词模板 是一个字符串模板&#xff0c;其中包含一些占位符&#xff08;通常是 {variable} 形式的&#xff09;&#xff0c;这些占位符可以在运行时被实际值替换。LangChain 提供了多种类型的提示词模板&#xff0c;以适应不同的使用场景。 2. 主要类…...

什么是PHP伪协议

PHP伪协议是一种特殊的URL格式&#xff0c;允许开发者以不同于传统文件路径访问和操作资源。以下是一些常见的PHP伪协议及其详细介绍&#xff1a; 常见的PHP伪协议 1. **file://** - **用途**&#xff1a;访问本地文件系统。 - **示例**&#xff1a;file:///path/to/file.txt。…...

python脚本处理excel文件

1.对比perl和python 分别尝试用perl和python处理excel文件&#xff0c;发现perl的比较复杂&#xff0c;比如说read excel就有很多方式 Spreadsheet::Read use Spreadsheet::ParseExcel 不同的method&#xff0c;对应的取sheet的cell方式也不一样。更复杂的是处理含有中文内…...