学习 React:第一步指南
欢迎来到 React 的世界!如果你正在阅读这篇文章,很可能你已经对前端开发有所了解,或者对构建现代、交互性强的用户界面充满好奇。React,这个由 Facebook(现在是 Meta)创建和维护的 JavaScript 库,已经成为构建用户界面的主流选择之一。它的强大、灵活和高效,让无数开发者为之着迷。
但这“第一步”该如何迈出呢?对于初学者来说,面对 React 丰富的生态系统、JSX 语法、组件化思维、状态管理等概念,可能会感到有些不知所措。别担心,这篇指南将带你系统地踏出学习 React 的第一步,从零开始,一步一步理解 React 的核心概念,并亲手搭建一个简单的 React 应用。
我们将从基础知识开始,涵盖环境搭建、核心语法、组件概念,并通过实际代码示例来巩固理解。请准备好你的热情和好奇心,让我们一起开启 React 的学习之旅!
为什么选择 React?
在深入学习之前,我们先来快速了解一下为什么 React 如此受欢迎:
- 声明式编程 (Declarative): React 提倡声明式地描述你的 UI。你只需要告诉 React 你想要什么状态下的 UI 是什么样子,而不用关心如何一步一步地去实现它。React 会负责高效地更新和渲染组件,让你的代码更易于理解和调试。
- 组件化 (Component-Based): React 的核心思想是将 UI 拆分成独立、可复用的组件。每个组件管理自己的状态,并且可以像乐高积木一样组合起来构建复杂的 UI。这极大地提高了代码的可维护性和复用性。
- 高效的性能 (Efficient Performance): React 使用虚拟 DOM (Virtual DOM) 来优化渲染。当数据发生变化时,React 会先在内存中构建一个新的虚拟 DOM 树,然后与旧的虚拟 DOM 树进行比较(diffing),找出需要更新的部分,最后只更新真实 DOM 中变化的部分。这比直接操作真实 DOM 要高效得多。
- 强大的生态系统 (Strong Ecosystem): 作为一个流行的库,React 拥有庞大且活跃的社区。这意味着你可以轻松找到各种第三方库、工具、教程和解决方案,无论是状态管理 (Redux, Zustand)、路由 (React Router)、数据获取还是其他需求,几乎都有成熟的方案。
- 跨平台 (Cross-Platform): 除了 Web 开发 (React DOM),React 的思想还可以用于构建原生移动应用 (React Native)、VR 应用 (React VR) 等,这为开发者提供了更广阔的发展空间。
了解了这些优势,相信你已经迫不及待想要开始学习了。
学习 React 的先决条件
在你开始学习 React 之前,需要确保你具备一些基础知识:
- HTML: 理解 HTML 的基本结构和常用标签。
- CSS: 理解 CSS 的基本语法和布局概念。
- JavaScript (ES6+): 这是最重要的一环。你需要扎实的 JavaScript 基础,包括但不限于:
- 变量、数据类型、运算符
- 函数(包括箭头函数)
- 对象和数组
- 条件语句和循环
- ES6+ 特性:
let
、const
、箭头函数、模块导入导出 (import
/export
)、解构赋值 (Destructuring)、展开运算符 (Spread operator) 等。React 代码大量使用了这些现代 JavaScript 特性。 - 对异步编程(Promises,
async
/await
)有基本了解会很有帮助,尤其是在处理数据请求时。
- Node.js 和 npm/yarn: React 的开发依赖于 Node.js 环境来运行构建工具和包管理器。你需要安装 Node.js,它会自动安装 npm (Node Package Manager)。或者你也可以选择使用 yarn 或 pnpm 作为包管理器。
如果你在这些方面感到不足,建议先花一些时间巩固你的 HTML、CSS 和 JavaScript 基础。特别是 JavaScript,它是学习 React 的基石。
搭建开发环境
学习 React 的第一步是搭建一个可以运行 React 应用的环境。最常见的入门方式是使用官方推荐的脚手架工具:create-react-app
或更现代的 Vite
。它们可以帮助你快速搭建一个包含必要配置(如 Webpack, Babel 等)的项目骨架,让你无需关心复杂的构建细节,直接开始编写 React 代码。
我们以 create-react-app
为例,因为它在初学者中依然非常流行且文档丰富。
步骤 1:安装 Node.js
访问 Node.js 官方网站 (https://nodejs.org/),下载并安装适合你操作系统的最新 LTS (长期支持) 版本。安装完成后,打开终端或命令行工具,输入以下命令检查 Node.js 和 npm 是否安装成功:
bash
node -v
npm -v
如果能正确显示版本号,说明安装成功。
步骤 2:使用 create-react-app 创建项目
打开你的终端或命令行工具,切换到你想创建项目的目录,然后运行以下命令:
bash
npx create-react-app my-react-app
npx
是 npm 5.2+ 版本自带的工具,它可以直接运行 npm 仓库中的可执行文件,而不需要全局安装。这里它用来运行create-react-app
工具。create-react-app
是用来创建 React 应用的脚手架名称。my-react-app
是你的项目名称,你可以换成任何你喜欢的名字。
这个命令会做很多事情:创建一个名为 my-react-app
的文件夹,在里面初始化一个 Git 仓库,然后下载并安装 React 以及所有必要的依赖。这个过程可能需要几分钟,请耐心等待。
步骤 3:进入项目目录并启动开发服务器
项目创建完成后,按照终端的提示,进入项目目录:
bash
cd my-react-app
然后启动开发服务器:
bash
npm start
或者如果你使用 yarn:
bash
yarn start
执行 npm start
后,你的浏览器会自动打开一个新的页面,通常是 http://localhost:3000
,显示一个旋转的 React Logo 和“Edit src/App.js
and save to reload.”的文本。恭喜你,你已经成功运行了你的第一个 React 应用!
开发服务器会自动监听你代码的变化,并在你保存文件后自动刷新浏览器,这极大地提高了开发效率。
项目文件结构简介
使用 create-react-app
创建的项目通常包含以下重要的文件和目录:
my-react-app/
├── node_modules/ # 项目依赖的第三方库
├── public/ # 公共资源,如 index.html, favicon.ico
│ └── index.html # 应用的 HTML 模板
├── src/ # 源代码目录
│ ├── App.css # App 组件的样式
│ ├── App.js # 根组件 App 的代码
│ ├── App.test.js # App 组件的测试文件
│ ├── index.css # 全局样式
│ ├── index.js # 应用的入口文件,将根组件渲染到 HTML
│ ├── logo.svg # React Logo
│ └── reportWebVitals.js # 性能报告
│ └── setupTests.js # 测试设置
├── .gitignore # Git 忽略文件配置
├── package.json # 项目配置文件,包含依赖和脚本命令
└── README.md # 项目说明
对于初学者,主要关注 src
目录。index.js
是应用的入口,它负责将根组件 (App
) 渲染到 public/index.html
中的一个特定 DOM 元素(通常是 <div id="root"></div>
)。App.js
是你的应用的起点,你将在其中构建你的 UI。
核心概念:JSX
打开 src/App.js
文件,你可能会看到类似这样的代码:
“`javascript
import logo from ‘./logo.svg’;
import ‘./App.css’;
function App() {
return (
Edit src/App.js
and save to reload.
);
}
export default App;
“`
在这段代码中,return
语句中的 <div className="App">...</div>
部分看起来像是 HTML,但它实际上是 JSX (JavaScript XML)。
JSX 是一种 JavaScript 的语法扩展,它允许你在 JavaScript 代码中书写类似 HTML 的结构。React 推荐使用 JSX 来描述 UI 的样子。
为什么使用 JSX?
React 认为渲染逻辑(UI 长什么样)与 UI 逻辑(如何处理事件、如何随状态变化)本质上是耦合的。将它们放在一起,可以使组件的代码更易于理解和维护。JSX 就是实现这一点的工具。它看起来像模板语言,但它拥有 JavaScript 的全部能力。
JSX 的基本规则和语法:
-
根元素: 每个 JSX 表达式必须有一个单一的根元素。例如:
“`jsx
// 正确
return (Hello
World
);
// 错误
// return (
//Hello
//
World
// );
// 你可以使用 React.Fragment 或 <> (短语法) 作为根元素,它不会在 DOM 中生成额外的节点
return (
<>Hello
World
);
“` -
属性 (Attributes): 在 JSX 中使用属性时,大部分与 HTML 相同,但有一些例外:
- HTML 中的
class
属性在 JSX 中使用className
代替,因为class
是 JavaScript 的保留关键字。 - HTML 中的
for
属性在 JSX 中使用htmlFor
代替。 - 属性值如果是字符串常量,使用双引号或单引号:
<img src="logo.png" />
。 - 属性值如果是 JavaScript 变量或表达式,使用花括号
{}
包裹:<img src={logo} alt="Logo" />
。 - 布尔属性(如
disabled
,checked
)如果值为true
,可以只写属性名:<button disabled>Disabled Button</button>
。如果值为false
,不写该属性即可。
- HTML 中的
-
嵌入 JavaScript 表达式: 你可以在 JSX 中使用花括号
{}
嵌入任何有效的 JavaScript 表达式(变量、函数调用、三元运算符等)。“`jsx
const name = ‘React’;
const element =Hello, {name}!
; // 嵌入变量
function formatName(user) {
return user.firstName + ‘ ‘ + user.lastName;
}
const user = { firstName: ‘John’, lastName: ‘Doe’ };
const greeting = (Hello, {formatName(user)}! {/ 嵌入函数调用 /}
);
const isLoggedIn = true;
const content = ({isLoggedIn ?Welcome back!
: } {/ 嵌入三元运算符 /}
);
“` -
注释: 在 JSX 中写注释需要使用
{/* ... */}
的格式。jsx
return (
<div>
{/* 这是一个 JSX 注释 */}
<p>Hello</p>
</div>
); -
自闭合标签: 没有子元素的标签必须自闭合,例如
<img />
,<input />
,<br />
。
理解并熟练使用 JSX 是学习 React 的关键第一步,因为它直接关系到你如何描述 UI。
核心概念:组件 (Components)
组件是 React 的核心构建块。它们是独立、可复用的代码块,负责渲染 UI 的一部分。想象一下网页是一个由不同部分组成的整体:导航栏、侧边栏、文章列表、评论区等等。在 React 中,你可以把这些部分都定义成独立的组件。
组件有两种主要类型:函数组件 (Functional Components) 和类组件 (Class Components)。在现代 React 开发中,函数组件配合 Hooks 是主流推荐的方式,因为它更简洁且易于理解。我们将重点介绍函数组件。
函数组件 (Functional Components):
函数组件是简单的 JavaScript 函数,它接收一个 props
对象作为参数,并返回一个 React 元素(通常是由 JSX 描述的 UI)。
“`javascript
import React from ‘react’; // 在使用 JSX 的文件中,虽然不直接使用 React 变量,但在背后 JSX 会被转换成 React.createElement 调用,所以需要导入 React
// 这是一个简单的函数组件
function Welcome(props) {
return
Hello, {props.name}
;
}
// 使用箭头函数定义组件也是常见的方式
const Goodbye = (props) => {
return
Goodbye, {props.name}
;
};
// 使用解构赋值获取 props 更简洁
const Greeting = ({ name }) => {
return
Nice to meet you, {name}
;
};
“`
如何使用组件?
一旦定义了一个组件,你可以在其他组件中像使用普通 HTML 标签一样使用它。请注意,自定义组件的名称必须以大写字母开头,这是 React 区分自定义组件和原生 HTML 元素的方式。
“`javascript
import React from ‘react’;
import Welcome from ‘./Welcome’; // 假设 Welcome 组件在 Welcome.js 文件中
function App() {
return (
{/ 你可以在同一个应用中多次使用同一个组件,并传入不同的数据 (props) /}
);
}
export default App;
“`
这样,你在 App
组件中就使用了 Welcome
组件两次,每次都传入了不同的 name
数据。
组件的优点:
- 复用性: 同一个组件可以在应用的不同地方多次使用。
- 可维护性: UI 被拆分成独立的单元,更容易管理和修改。
- 可读性: 代码结构更清晰,更容易理解。
- 分离关注点: 每个组件只关注渲染自己的那一小块 UI。
理解组件的概念以及如何创建和使用它们,是掌握 React 最重要的一步。
核心概念:Props (属性)
Props (properties 的缩写) 是组件之间传递数据的方式。当父组件需要向子组件传递数据或配置信息时,就使用 props。
就像 HTML 标签有属性一样(如 <img src="..." alt="..." />
),React 组件也可以有属性。你在使用组件时,通过给它添加属性来传递数据:
jsx
<Welcome name="Alice" age={30} isStudent={false} />
然后在 Welcome
组件内部,通过函数的参数 props
来接收这些数据:
javascript
function Welcome(props) {
// props 是一个对象,包含所有传递给组件的属性
console.log(props); // 例如:{ name: "Alice", age: 30, isStudent: false }
return (
<div>
<h1>Hello, {props.name}</h1>
<p>Age: {props.age}</p>
{props.isStudent ? <p>Student</p> : <p>Not a student</p>}
</div>
);
}
或者使用解构赋值让代码更简洁:
javascript
function Welcome({ name, age, isStudent }) {
return (
<div>
<h1>Hello, {name}</h1>
<p>Age: {age}</p>
{isStudent ? <p>Student</p> : <p>Not a student</p>}
</div>
);
}
Props 的重要特性:
- 单向数据流: 数据总是从父组件流向子组件(自上而下)。子组件不能直接修改父组件传递过来的 props。这有助于理清数据流,使应用的状态更可预测。
- 只读性 (Immutable): 在组件内部,你不应该修改接收到的 props。如果一个组件需要改变数据,它应该使用状态 (State),或者调用父组件传递下来的函数来请求父组件进行数据修改。
Props 是构建组件树和实现数据流的基础。
核心概念:State (状态)
与 props 不同,State 是组件自身管理的数据,并且这些数据是可能随着时间而改变的。当组件的状态发生变化时,React 会重新渲染该组件及其子组件,以反映最新的状态。
在函数组件中,我们使用 useState
Hook 来管理状态。Hooks 是 React 16.8 引入的新特性,它们允许你在函数组件中使用状态和其他 React 特性,而无需编写类。
使用 useState
Hook:
useState
是一个函数,它接收状态的初始值作为参数,并返回一个包含两个元素的数组:
- 当前的状态值。
- 一个更新状态的函数。
“`javascript
import React, { useState } from ‘react’; // 导入 useState Hook
function Counter() {
// 使用 useState Hook 声明一个状态变量 ‘count’
// 初始值为 0
// useState 返回一个数组: [当前状态值, 更新状态的函数]
const [count, setCount] = useState(0);
// 事件处理函数
const increment = () => {
// 调用 setCount 来更新 count 的值
// 传递新的值 (当前值 + 1)
setCount(count + 1);
// 注意:setCount 是异步的,多次调用 setCount(count + 1) 可能不会如预期那样立即连续增加
// 如果新的状态依赖于前一个状态,推荐使用函数形式的更新:
// setCount(prevCount => prevCount + 1);
};
const decrement = () => {
setCount(count – 1);
};
return (
Count: {count}
{/ 显示当前状态值 /}
{/ 点击按钮触发状态更新 /}
);
}
export default Counter;
“`
将 Counter
组件放到 App.js
中渲染,然后在浏览器中点击按钮,你会看到 Count
的值发生变化,页面也会随之更新。
State 的重要特性:
- 组件私有: State 通常是组件内部私有的,不能直接从外部访问或修改(除非通过父组件传递的回调函数)。
- 触发重新渲染: 调用状态更新函数(如
setCount
)会告诉 React 这个组件的状态发生了变化,React 会重新渲染这个组件。 - 异步更新: 状态更新函数(如
setCount
)的调用可能是异步的,React 可能会批量处理多个状态更新,以提高性能。如果你需要基于前一个状态来更新状态,应该使用函数形式的更新。
State 是构建动态、交互性 UI 的关键。它允许组件记住一些信息并在这些信息改变时更新界面。
核心概念:事件处理 (Event Handling)
在 React 中处理事件(如点击按钮、输入文本、鼠标移动等)与在原生 HTML 中略有不同。React 事件处理与 DOM 事件类似,但采用驼峰命名法 (onClick
, onChange
),并且传递的是函数引用而不是字符串。
jsx
<button onClick={handleClick}>Click me</button>
这里的 handleClick
是一个 JavaScript 函数,当按钮被点击时,这个函数会被执行。
事件处理函数:
事件处理函数会接收一个事件对象作为参数,这个对象是 React 合成的事件对象 (SyntheticEvent)。它封装了原生浏览器事件对象,并提供了跨浏览器的一致性。
“`javascript
function MyButton() {
const handleClick = (event) => {
// event 是 React 合成的事件对象
console.log(‘Button clicked!’);
console.log(‘Event type:’, event.type); // ‘click’
// 阻止默认行为 (例如,阻止表单提交或链接跳转)
// event.preventDefault();
};
return (
);
}
“`
向事件处理函数传递参数:
有时你需要在调用事件处理函数时传递额外的参数。常见的做法是使用箭头函数或 Function.prototype.bind
。
使用箭头函数(推荐):
“`jsx
// 事件处理函数定义
const handleClick = (p1, p2) => {
console.log(‘Params:’, p1, p2);
};
“`
这种方式简洁明了,并且可以确保参数被正确传递。事件对象 event
会作为最后一个参数被隐式传递(如果你的处理函数只接收额外参数而没有显式声明 event,它依然可以接收到 event)。如果你需要同时接收额外参数和事件对象,可以这样写:
“`jsx
const handleClick = (p1, p2, event) => {
console.log(‘Params:’, p1, p2);
console.log(‘Event:’, event);
};
“`
事件处理是实现用户交互的基础,掌握它对于构建任何实际应用都至关重要。
构建一个简单的例子:计数器
现在,让我们综合运用 JSX、组件、State 和事件处理,来构建一个简单的计数器应用。
修改 src/App.js
文件,清空其中的内容,然后粘贴以下代码:
“`javascript
import React, { useState } from ‘react’; // 导入 React 和 useState Hook
import ‘./App.css’; // 导入样式文件
function App() {
// 使用 useState 定义一个名为 ‘count’ 的状态变量,初始值为 0
const [count, setCount] = useState(0);
// 定义增加计数器的函数
const increment = () => {
setCount(count + 1); // 调用 setCount 更新状态
};
// 定义减少计数器的函数
const decrement = () => {
// 确保计数器不会小于 0
if (count > 0) {
setCount(count – 1);
}
};
// 定义重置计数器的函数
const reset = () => {
setCount(0); // 将计数器重置为 0
};
return (
Simple Counter
{/* 显示当前计数值 */}
<p>Count: <span style={{ color: '#61dafb', fontWeight: 'bold' }}>{count}</span></p> {/* 嵌入 JavaScript 表达式,内联样式使用对象 */}
{/* 按钮,绑定点击事件 */}
<div>
<button onClick={increment} style={{ margin: '5px' }}>Increment (+)</button> {/* 内联样式 */}
<button onClick={decrement} style={{ margin: '5px' }}>Decrement (-)</button>
<button onClick={reset} style={{ margin: '5px' }}>Reset</button>
</div>
{/* 简单的条件渲染:当计数器大于 10 时显示提示 */}
{count > 10 && <p style={{ color: 'lightgreen' }}>Count is getting high!</p>}
</header>
</div>
);
}
export default App; // 导出 App 组件
“`
保存文件,浏览器会自动刷新。现在你应该能看到一个简单的计数器界面,包含当前计数显示以及三个按钮。点击按钮,观察计数器的变化。
这个简单的例子包含了我们学习的所有核心概念:
- JSX: 用来描述 UI 的结构 (
<h1>
,<p>
,<button>
). - 函数组件:
App
就是一个函数组件。 - State: 使用
useState
管理count
的状态。 - 事件处理: 使用
onClick
绑定increment
,decrement
,reset
函数来响应用户点击。 - 嵌入 JS 表达式: 在 JSX 中使用
{count}
显示状态值,使用{count > 10 && ...}
进行条件渲染。 - Props (虽然在这个例子中 App 没有接收 props,但我们在之前的 Welcome 例子中展示了).
通过这个例子,你应该对 React 如何工作有了更直观的感受。UI 是通过组件构建的,组件通过 props 接收数据,通过 state 管理自身的可变数据,并通过事件处理响应用户交互,最终根据 state 的变化自动更新 UI。
接下来的学习路线
掌握了环境搭建、JSX、组件、Props、State 和事件处理这些基本概念,你已经迈出了坚实的第一步。但 React 的世界还有很多内容值得探索:
- Hooks (更深入): 除了
useState
,还有useEffect
(处理副作用,如数据获取、订阅、手动改变 DOM)、useContext
(跨组件共享状态)、useReducer
(管理复杂状态逻辑) 等等。Hooks 是现代 React 开发的核心。 - 条件渲染 (Conditional Rendering): 根据条件显示或隐藏不同的 UI 元素 (如我们计数器例子中的提示)。
- 列表渲染 (Lists and Keys): 如何高效地渲染一个列表(如待办事项列表),以及
key
属性的重要性。 - 表单处理 (Forms): 如何在 React 中构建和处理表单,包括受控组件和非受控组件。
- 组件生命周期 (Component Lifecycle): (对于函数组件主要是通过
useEffect
来模拟) 理解组件在不同阶段(挂载、更新、卸载)如何执行逻辑。 - 路由 (Routing): 构建多页面应用或单页应用 (SPA) 中的页面切换,通常使用
react-router-dom
库。 - 状态管理 (State Management): 对于大型应用,组件间的状态共享和管理变得复杂。学习 Context API 或 Redux、Zustand 等状态管理库。
- 数据获取 (Data Fetching): 在组件中获取后端数据,使用
fetch
API、Axios 或 SWR/React Query 等库。 - PropTypes 或 TypeScript: 验证组件接收到的 props 的数据类型,提高代码健壮性。
- 测试 (Testing): 学习如何测试你的 React 组件。
这些概念会在你构建更复杂应用时逐渐遇到和掌握。不要试图一次学完所有东西,保持好奇心,一步一步来。
学习资源推荐
- React 官方文档 (强烈推荐): https://reactjs.org/ (或中文版:https://zh-hans.reactjs.org/) 这是最权威、最详细的学习资源。从 “Main Concepts” (核心概念) 部分开始阅读。
- MDN Web 文档: 对于巩固 JavaScript 和 Web API 基础非常有帮助。
- freeCodeCamp, Codecademy, Coursera, Udemy, egghead.io: 许多在线平台提供高质量的 React 课程,可以根据自己的学习风格选择。
- YouTube 上的技术频道: 许多开发者分享 React 教程和实战经验。
- GitHub: 查看开源的 React 项目代码,学习他人的实践。
- 技术社区: Stack Overflow, Reddit 的 r/reactjs 板块,各种技术论坛和 Discord 群组,在遇到问题时寻求帮助或与他人交流。
总结
恭喜你!通过阅读这篇指南并跟随实践,你已经迈出了学习 React 的第一步。我们了解了 React 的优势,搭建了开发环境,学习了 JSX 语法、组件、Props 和 State 这些核心概念,并亲手构建了一个简单的计数器应用。
学习是一个持续的过程。React 知识体系庞大,但只要掌握了核心思想,剩下的知识点都是在此基础上展开的。记住:
- 多动手实践: 理论结合实践才能真正掌握。尝试修改我们创建的计数器,或者自己构建一个简单的待办事项列表应用。
- 阅读文档: 遇到问题时,查阅官方文档是最好的习惯。
- 不要害怕犯错: 编程就是在不断试错中进步。
- 保持耐心和热情: 学习曲线可能有时会比较陡峭,但坚持下去,你会发现 React 的魅力。
祝你在 React 的学习旅程中一切顺利!