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

学习 React【Plan - June - Week 1】

一、使用 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><inputtype="text"value={filterText}onChange={(e) => onFilterTextChange(e.target.value)}placeholder="Search..."/><label><inputtype="checkbox"checked={inStockOnly}onChange={(e) => onInStockChange(e.target.checked)}/>Only show products in stock</label></form>);
}

6、组件结构(最终)

<FilterableProductTable products={PRODUCTS} />// 内部包含└── <SearchBarfilterText={...}inStockOnly={...}onFilterTextChange={...}onInStockChange={...}/>└── <ProductTableproducts={...}filterText={...}inStockOnly={...}/>

相关文章:

  • .net 使用MQTT订阅消息
  • AirSim/Cosys-AirSim 游戏开发(三)打包可执行文件
  • AI代码助手需求说明书架构
  • OPenCV CUDA模块光流------高效地执行光流估计的类BroxOpticalFlow
  • day46python打卡
  • 市面上哪款AI开源软件做ppt最好?
  • 【前端】每日一道面试题6:解释Promise.any和Promise.allSettled的使用场景及区别。
  • T/SAIAS 018—2025《具身智能语料库建设导则》研究报告:体系解构与实施路径
  • Nuxt.js 中的路由配置详解
  • Webhook 配置备忘
  • Chrome 浏览器前端与客户端双向通信实战
  • 前端对WebSocket进行封装,并建立心跳监测
  • 前端项目初始化
  • Web 架构之 CDN 加速原理与落地实践
  • ESP8266(NodeMcu)+GPS模块+TFT屏幕实现GPS码表
  • 32单片机——窗口看门狗
  • 智能终端与边缘计算按章复习
  • Science Robotics:UCLA 贺曦敏团队综述自主软体机器人
  • npm install的原理
  • 【leetcode】3. 无重复字符的最长子串
  • 网站建设前景/抖音广告代运营
  • 建立网站的英文怎么说/seo外链推广工具下载
  • 医疗网站的在线聊天怎么做的/seo关键词的选择步骤
  • b2b2c多用户系统/关键词优化公司电话
  • 做网站的公司苏州/网站制作代码
  • 在国内可以做国外的网站吗/百度快速排名优化技术