学习 React【Plan - June - Week 1】

news2025/6/7 16:43:33

一、使用 JSX 书写标签语言

JSX 是一种 JavaScript 的语法扩展,React 使用它来描述用户界面。


什么是 JSX?

  • JSX 是 JavaScript 的一种语法扩展。
  • 看起来像 HTML,但它实际上是在 JavaScript 代码中写 XML/HTML。
  • 浏览器并不能直接运行 JSX,需要通过打包工具(如 Babel)将其转译为 JavaScript。

示例:

const element = <h1>Hello, world!</h1>;

1、JSX 的基本规则

使用大写字母定义组件

function MyButton() {
  return <button>I'm a button</button>;
}
  • 小写字母开头的标签,如 <div> 被解析为 HTML 标签。
  • 大写字母开头的标签,如 <MyButton> 被解析为 React 组件。

必须使用闭合标签

  • 所有标签必须闭合(类似 XML 语法)
// 正确
<input />
<br />
<MyComponent />

// 错误
<input>

使用 {} 插入 JavaScript 表达式

const user = "小明";
const element = <h1>Hello, {user}!</h1>;
  • 只能插入表达式(不是语句)

合法表达式:

{1 + 2}
{user.name}
{formatDate(date)}

非法语句:

{if (isTrue) { ... }}
{for (...) { ... }}

使用 className 代替 class

// HTML 写法
<div class="container"></div>

// JSX 写法
<div className="container"></div>

因为 class 是 JavaScript 的关键字,所以要使用 className


使用 camelCase 的属性名

// HTML 写法
<input tabindex="0" onclick="handleClick()" />

// JSX 写法
<input tabIndex={0} onClick={handleClick} />

2、条件渲染和列表渲染

条件渲染

使用三元表达式、逻辑与 &&

{isLoggedIn ? <LogoutButton /> : <LoginButton />}

{messages.length > 0 && <Notification messages={messages} />}

列表渲染

使用 map() 进行循环输出,并为每个子元素设置唯一的 key

const items = ['A', 'B', 'C'];

<ul>
  {items.map(item => <li key={item}>{item}</li>)}
</ul>

3、JSX 转换成 JavaScript 的原理

JSX 会被转译为 React.createElement 调用:

const element = <h1 className="title">Hello</h1>;

// 会被转换为:
const element = React.createElement('h1', { className: 'title' }, 'Hello');

4、组合 JSX

JSX 支持嵌套结构:

function App() {
  return (
    <div>
      <Header />
      <Content />
      <Footer />
    </div>
  );
}

可使用片段(Fragment)避免多余的 DOM 元素:

<>
  <td>内容1</td>
  <td>内容2</td>
</>

5、JSX Tips

注释写法:

{/* 这是注释 */}

多行 JSX 需要用括号包裹:

return (
  <div>
    <h1>Hello</h1>
  </div>
);

二、组件(Component)

React 应用是由组件构成的,组件是可以复用的 UI 单元。


什么是组件?

  • 组件(Component) 是 React 的核心概念。
  • 本质上是一个返回 JSX 的函数。
  • 组件名称必须以大写字母开头。

示例:

function MyButton() {
  return <button>I'm a button</button>;
}

在 JSX 中使用:

export default function MyApp() {
  return (
    <div>
      <h1>Welcome to my app</h1>
      <MyButton />
    </div>
  );
}

组件命名规则

  • 必须以大写字母开头,否则会被当成 HTML 标签。
  • 使用 PascalCase 命名约定(每个单词首字母大写)。

1、组件是函数,不是标签

function MyButton() {
  return <button>Click me</button>;
}

这个 MyButton 是一个函数,而 <MyButton /> 是它的使用方式(调用)


2、组件可以复用

你可以多次使用同一个组件,它们是互相独立的:

function MyApp() {
  return (
    <div>
      <MyButton />
      <MyButton />
    </div>
  );
}

每个 <MyButton /> 都会渲染一个独立的按钮。


3、组件的结构建议

建议为每个组件建一个文件(例如 MyButton.jsx),用于项目组织:

src/
├─ components/
│  └─ MyButton.jsx
└─ App.jsx

🧪 示例代码汇总

// MyButton.jsx
export default function MyButton() {
  return <button>I'm a button</button>;
}

// App.jsx
import MyButton from './MyButton';

export default function MyApp() {
  return (
    <div>
      <h1>Welcome to my app</h1>
      <MyButton />
      <MyButton />
    </div>
  );
}

三、State

React 的状态(state)允许组件“记住”信息。状态是让组件有“记忆”的机制,通常用于跟踪用户交互或界面变化。


1、什么是状态(State)?

  • 状态是组件的“记忆”
  • 在每次重新渲染时,组件的状态保持不变
  • 状态的变化会 触发组件的重新渲染

2、如何添加状态?

通过 useState Hook:

import { useState } from 'react';

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

useState 解释:

const [state, setState] = useState(initialValue);
名称含义
state当前状态值
setState用于更新状态的函数
initialValue初始状态值

3、状态的基本用法示例

import { useState } from 'react';

export default function MyButton() {
  const [count, setCount] = useState(0);

  function handleClick() {
    setCount(count + 1);
  }

  return (
    <button onClick={handleClick}>
      Clicked {count} times
    </button>
  );
}

4、每次点击发生了什么?

  1. 点击按钮时,handleClick 被调用。
  2. setCount(count + 1) 更新状态。
  3. React 重新渲染组件。
  4. 新的 count 显示在界面上。

状态更新不会改变当前值,而是触发一次新的渲染,组件中的 count 会更新为新值。


5、状态在组件之间是隔离的

每个组件实例有自己独立的状态。

<MyButton />
<MyButton />

上面两个按钮互不影响,即使它们使用相同的 useState


6、不要直接修改 state 变量

// 错误写法(不会触发重新渲染)
count = count + 1;

// 正确写法
setCount(count + 1);

只有通过 setCount 这样的更新函数,React 才会触发重新渲染。


7、多个状态变量

可以在一个组件中使用多个 useState

const [count, setCount] = useState(0);
const [name, setName] = useState('React');

8、示例完整代码

import { useState } from 'react';

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

  function handleClick() {
    setCount(count + 1);
  }

  return (
    <button onClick={handleClick}>
      Clicked {count} times
    </button>
  );
}

export default function MyApp() {
  return (
    <div>
      <h1>Welcome to my app</h1>
      <MyButton />
      <MyButton />
    </div>
  );
}

四、响应事件

React 使用类似 HTML 的方式来处理用户交互事件,比如点击、输入、悬停等。但语法略有不同,并支持更强的逻辑功能。


1、事件绑定基础

React 使用 onClickonChange 等属性来绑定事件处理函数。

示例:

function MyButton() {
  function handleClick() {
    alert('你点击了我!');
  }

  return (
    <button onClick={handleClick}>
      点击我
    </button>
  );
}

注意:

  • 使用驼峰命名(如 onClick,而不是 onclick
  • 事件处理函数是一个普通的 JavaScript 函数
  • JSX 中不使用字符串绑定函数(不同于 HTML 的 onclick="handleClick()"

2、为什么使用函数名而不是函数调用?

// 正确
onClick={handleClick}

// 错误(会立即执行)
onClick={handleClick()}

你应传递函数的引用,而不是函数的执行结果。


3、使用箭头函数传参

有时你希望传递参数给事件处理函数,可以使用箭头函数:

function handleClick(name) {
  alert(`Hello, ${name}!`);
}

<button onClick={() => handleClick('小明')}>
  Say Hello
</button>

4、在组件中组合事件处理逻辑

React 鼓励你将组件拆成小块,事件处理函数可以在组件内部定义或向下传递:

function Button({ onClick, children }) {
  return <button onClick={onClick}>{children}</button>;
}

function App() {
  function handleClick() {
    alert('Clicked!');
  }

  return (
    <div>
      <Button onClick={handleClick}>按钮1</Button>
      <Button onClick={handleClick}>按钮2</Button>
    </div>
  );
}

5、常见事件类型

React 事件名对应 HTML说明
onClickonclick点击事件
onChangeonchange输入/选择改变
onSubmitonsubmit表单提交
onMouseEnteronmouseenter鼠标进入
onKeyDownonkeydown按键按下

6、阻止默认行为

可以在事件中调用 event.preventDefault()

function handleSubmit(e) {
  e.preventDefault();
  alert('提交已阻止');
}

<form onSubmit={handleSubmit}>
  <button type="submit">提交</button>
</form>

7、React 与原生 DOM 事件的区别

项目React原生 HTML
命名方式驼峰命名,如 onClick小写,如 onclick
传递方式传函数引用传字符串或函数调用
自动阻止冒泡否,你仍需手动阻止冒泡同样需手动处理

8、示例完整代码

function Button({ message, children }) {
  function handleClick() {
    alert(message);
  }

  return (
    <button onClick={handleClick}>
      {children}
    </button>
  );
}

export default function App() {
  return (
    <div>
      <Button message="你好!">点我</Button>
      <Button message="再见!">再点我</Button>
    </div>
  );
}

五、React 哲学

“React 哲学” 教你如何从 UI 设计图开始,一步步将页面拆解为组件,再构建出数据驱动的交互式界面。


示例场景简介

我们要实现一个可搜索的商品表格(Searchable Product Table),它包含:

  • 一个搜索框
  • 一个是否只显示有库存商品的勾选框
  • 一个根据品类分组的商品表格

构建步骤总览

React 官方建议采用 五步法

  1. 将 UI 拆解为组件层级结构
  2. 构建组件的静态版本(无交互)
  3. 确定最小但完整的 UI 状态表示
  4. 确定哪些组件拥有状态(状态提升)
  5. 添加反向数据流(处理用户输入)

1、第一步:将 UI 拆解为组件层级

观察 UI,并根据界面结构拆出以下组件:

组件层级结构

FilterableProductTable (父组件)
├─ SearchBar
└─ ProductTable
   ├─ ProductCategoryRow
   └─ ProductRow

每个组件的职责

组件名作用描述
FilterableProductTable管理所有状态,整合其他组件
SearchBar输入搜索文本与是否过滤库存
ProductTable接收数据与过滤条件,渲染表格
ProductCategoryRow显示每个品类的标题
ProductRow显示单个商品

2、第二步:构建静态版本(无交互)

  • 使用父组件 FilterableProductTable 将假数据通过 props 传给子组件。
  • 每个组件只关注如何显示数据,不包含状态或交互。
  • 假数据示例:
const PRODUCTS = [
  {category: "Fruits", price: "$1", stocked: true, name: "Apple"},
  {category: "Fruits", price: "$1", stocked: true, name: "Dragonfruit"},
  {category: "Fruits", price: "$2", stocked: false, name: "Passionfruit"},
  {category: "Vegetables", price: "$2", stocked: true, name: "Spinach"},
  {category: "Vegetables", price: "$4", stocked: false, name: "Pumpkin"},
  {category: "Vegetables", price: "$1", stocked: true, name: "Peas"}
];

3、第三步:确定最小但完整的 UI 状态(State)

根据界面交互功能,确定需要驱动 UI 的状态

  • 搜索文本(filterText
  • 是否只显示有库存商品(inStockOnly

不是状态的内容(可由 props 或其他状态推导得出):

  • 商品数据(是静态的)
  • 分类标题(可从数据中提取)
  • 筛选后的商品列表(由 filterText + inStockOnly 计算)

4、第四步:决定状态的归属

状态应该放在最“靠上的共同祖先组件”中。

状态名所属组件原因
filterTextFilterableProductTableSearchBar 和 ProductTable 都使用它
inStockOnlyFilterableProductTable同上

5、第五步:添加反向数据流(提升状态 + 子传父)

SearchBar 接收 filterTextinStockOnly 作为 props,并通过 onChange 回调将用户输入传递给父组件修改状态。

function SearchBar({ filterText, inStockOnly, onFilterTextChange, onInStockChange }) {
  return (
    <form>
      <input
        type="text"
        value={filterText}
        onChange={(e) => onFilterTextChange(e.target.value)}
        placeholder="Search..."
      />
      <label>
        <input
          type="checkbox"
          checked={inStockOnly}
          onChange={(e) => onInStockChange(e.target.checked)}
        />
        Only show products in stock
      </label>
    </form>
  );
}

6、组件结构(最终)

<FilterableProductTable products={PRODUCTS} />

// 内部包含
  └── <SearchBar
         filterText={...}
         inStockOnly={...}
         onFilterTextChange={...}
         onInStockChange={...}
       />

  └── <ProductTable
         products={...}
         filterText={...}
         inStockOnly={...}
       />

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

电子行业AI赋能软件开发经典案例——某金融软件公司

01.案例标题 金融行业某金融软件公司通过StarShip CodeSouler达成效率突破性增长&#xff0c;零流程侵入验证AI代码高度可行性 02.执行摘要 某金融软件公司在核心产品研发中引入开放传神&#xff08;OpenCSG&#xff09;的StarShip CodeSouler AI代码生成平台&#xff0c;在无…

摆脱硬件依赖:SkyEye在轨道交通中的仿真应用

在城市轨道交通系统中&#xff0c;信号系统承担着确保列车安全、高效运行的关键任务。从排列进路、信号开放&#xff0c;到终点折返与接发车&#xff0c;几乎每一个调度动作背后都依赖于信号系统的精密控制与实时响应。作为信号系统的重要组成部分&#xff0c;目标控制器&#…

使用变异系数增强 CFD 收敛标准

将描述性统计整合到 CFD 中&#xff0c;以评估可变性和收敛性。 挑战 在工程设计中&#xff0c;尤其是在进行仿真时&#xff0c;我们经常处理描述流体、温度、应力或浓度行为的大型数据集。以有意义的方式解释这些值需要的不仅仅是原始数字;它需要对统计的理解。 统计学在工程…

物联网通信技术全景指南(2025)之如何挑选合适的物联网模块

物联网通信技术全景指南&#xff08;2025&#xff09;之 如何挑选合适的物联网模块 物联网通信技术全景指南&#xff08;2025&#xff09;一、技术代际演进与退网背景二、5G 物联网技术体系&#xff08;Sub-6 GHz 核心&#xff09;1. 技术分层架构2. 蜂窝技术性能矩阵3. Sub-6 …

影楼精修-AI衣服祛褶皱算法解析

注&#xff1a;为避免侵权&#xff0c;本文所用图像均为AIGC生成或无版权网站提供&#xff1b; 衣服祛褶皱功能&#xff0c;目前在像素蛋糕、美图云修、百度网盘AI修图、阿里云都有相关的功能支持&#xff0c;它的价值就是将不平整的衣服图像&#xff0c;变得整齐平整&#xf…

Day46 Python打卡训练营

知识点回顾&#xff1a; 1. 不同CNN层的特征图&#xff1a;不同通道的特征图 2. 什么是注意力&#xff1a;注意力家族&#xff0c;类似于动物园&#xff0c;都是不同的模块&#xff0c;好不好试了才知道。 3. 通道注意力&#xff1a;模型的定义和插入的位置 4. 通道注意力后…

linux安全加固(非常详细)

安全加固方案原则 1.版本升级 对于系统和应用在使用过程中暴露的安全缺陷&#xff0c;系统或应用厂商会及时发布解决问题的升级补丁包。升级系统或应用版本&#xff0c;可有效解决旧版本存在的安全风险。2.关闭端口服务 在不影响业务系统正常运行情况下&#xff0c;停止或禁用承…

动手学深度学习12.7. 参数服务器-笔记练习(PyTorch)

以下内容为结合李沐老师的课程和教材补充的学习笔记&#xff0c;以及对课后练习的一些思考&#xff0c;自留回顾&#xff0c;也供同学之人交流参考。 本节课程地址&#xff1a;35 分布式训练【动手学深度学习v2】_哔哩哔哩_bilibili 本节教材地址&#xff1a;12.7. 参数服务器…

告别数据泥沼,拥抱智能中枢:King’s四位一体重塑科研生产力

在现代科研的战场上&#xff0c;数据堪称科研人员手中的“弹药”。然而&#xff0c;许多实验室却深陷数据管理的泥沼&#xff1a;硬盘里堆满了不同年份的实验记录&#xff0c;U盘里塞着各种格式的谱图&#xff0c;Excel表格里还留着手动计算的痕迹……&#xff0c;当科研人员想…

智绅科技 —— 智慧养老 + 数字健康,构筑银发时代安全防护网

在老龄化率突破 21.3% 的当下&#xff0c;智绅科技以 "科技适老" 为核心理念&#xff0c;构建 "监测 - 预警 - 干预 - 照护" 的智慧养老闭环。 其自主研发的七彩喜智慧康养平台&#xff0c;通过物联网、AI 和边缘计算技术&#xff0c;实现对老年人健康与安…

Code Composer Studio CCS 工程设置,如何设置h文件查找路径?

右键工程,选Properties,在Build>MSP430 Compiler>Optinizution Include Options 设置头文件的搜索路径。 比如我设置了这些: ${CCS_BASE_ROOT}/msp430/include ${PROJECT_ROOT} ${CG_TOOL_ROOT}/include "${workspace_loc:/${ProjName}/F5xx_F6xx_Core_Lib}&quo…

Qt生成日志与以及捕获崩溃文件(mingw64位,winDbg)————附带详细解说

文章目录 Qt生成日志与以及报错文件(mingw64位&#xff0c;winDbg)0 背景与结果0.1 背景0.2 结果1 WinDbg1.1 安装1.2 使用 2 编写代码2.1 ccrashstack类2.2 编写输出捕获异常的dmp文件2.2 编写输出日志文件2.3 调用生成日志和dmp文件 参考 Qt生成日志与以及报错文件(mingw64位…

智能手表健康监测系统的PSRAM存储芯片CSS6404LS-LI—高带宽、耐高温、微尺寸的三重突破

一、直击智能手表三大核心痛点 痛点场景风险传统方案缺陷连续生物数据流存储100Hz PPG信号产生82MB/s数据洪峰SPI NOR Flash带宽不足(≤50MB/s)高温环境稳定性腕表表面温度达50℃&#xff08;烈日/运动场景&#xff09;商用级存储器件(85℃)易触发数据错误极限空间约束PCB面积…

蓝桥杯国赛题2022

首先这个题应该是一个01背包&#xff0c;背包容量为2022&#xff0c;有2022个物品&#xff0c;第i个物品的体积为i&#xff0c;只不过这里有两个限制条件&#xff0c;一个限制条件是和为2022&#xff0c;另一个限制条件为10个数&#xff0c;两个限制条件那就把加一维&#xff0…

关于如何使用VScode编译下载keil工程的步骤演示

1、vscode的插件市场下载keil Assistant 2 、点设置 3、复制keil的地址 4、粘贴到第…

Redis底层数据结构之深入理解跳表(2)

上一篇文章中我们详细讲述了跳表的增添、查找和修改的操作&#xff0c;这篇文章我们来讲解一下跳表在多线程并发时的安全问题。在Redis中&#xff0c;除了网络IO部分和大文件的后台复制涉及到多线程外&#xff0c;其余任务执行时全部都是单线程&#xff0c;这也就意味着在Redis…

[蓝桥杯]兰顿蚂蚁

兰顿蚂蚁 题目描述 兰顿蚂蚁&#xff0c;是于 1986 年&#xff0c;由克里斯兰顿提出来的&#xff0c;属于细胞自动机的一种。 平面上的正方形格子被填上黑色或白色。在其中一格正方形内有一只"蚂蚁"。 蚂蚁的头部朝向为&#xff1a;上下左右其中一方。 蚂蚁的移…

使用 Python 构建并调用 ComfyUI 图像生成 API:完整实战指南

快速打造你自己的本地 AI 图像生成服务&#xff0c;支持 Web 前端一键调用&#xff01; &#x1f4cc; 前言 在 AIGC 快速发展的今天&#xff0c;ComfyUI 作为一款模块化、节点式的图像生成界面&#xff0c;备受开发者青睐。但默认情况下&#xff0c;ComfyUI 主要通过界面交互…

嵌入式学习笔记-freeRTOS taskENTER_CRITICAL(_FROM_ISR)跟taskEXIT_CRITICAL(_FROM_ISR)函数解析

一 函数taskENTER_CRITICAL&#xff0c;taskEXIT_CRITICAL 函数taskENTER_CRITICAL最终实现如下&#xff1a; 第①处按照系统设定的configMAX_SYSCALL_INTERRUPT_PRIORITY值对中断进行屏蔽 第②处调用一次自增一次 第③处检查中断状态寄存器位&#xff0c;如果有任何中断位置…

1panel面板中部署SpringBoot和Vue前后端分离系统 【图文教程】

1panel面板中部署SpringBoot和Vue前后端分离系统 一&#xff0c;1panel面板部署二&#xff0c;安装OpenResty三&#xff0c;安装MySQL&#xff0c;Redis等Spring boot 运行依赖环境四&#xff0c;SpringBoot 应用配置及打包部署配置打包部署 五 &#xff0c;前端VUE应用配置打包…