引言
适合人群 :完全没接触过 React 的前端小白
学习目标:理解 React 的核心思想,掌握 JSX、组件化、状态管理等基本概念,并能运行自己的第一个 React 应用!
第一章:React 是什么?为什么我们要学它?
在传统的网页开发中,我们写 HTML 搭结构,写 CSS 调样式,再用 JavaScript 加点交互。这种方式对于小页面没问题,但一旦项目变大,代码就会变得混乱、难以维护。
而 React 是由 Facebook(现 Meta)推出的一个用于构建用户界面的 JavaScript 库。它的最大特点就是:
"一切皆组件"
想象一下乐高积木:每个小块都有固定形状和功能,你可以把它们拼成房子、汽车、飞船......
React 就是让你用"组件"这种"智能积木"来搭建网页!
第二章:如何初始化一个 React 项目?
现代前端工程离不开构建工具。目前最流行、速度最快的工具之一是 Vite。它由 Vue 作者尤雨溪开发,但对 React 支持极佳。
初始化步骤(一字不差照做即可):
打开终端(Mac/Linux 用 Terminal,Windows 用 PowerShell 或 CMD),输入:
npm init vite
然后你会看到一系列提示:
- Project name: 输入项目名,比如
my-first-react-app - Select a framework: 选择
react - Select a variant: 选择
javascript(因为我们还没学 TypeScript)
完成后,进入项目目录并安装依赖:
cd my-first-react-app
npm install
最后启动开发服务器:
npm run dev
你会看到类似这样的输出:
VITE v5.0.0 ready in 300 ms
➜ Local: http://localhost:5173/
打开浏览器访问 http://localhost:5173,恭喜!你已经成功运行了第一个 React 应用!🎉
完整项目链接:lesson_zp/react/jsx/jsx-demo:AI + 全栈学习仓库
项目结构如图:

第三章:项目文件结构初探
一个典型的 Vite + React 项目包含以下关键文件,其中 App2.jsx 是我们另外创建的:
main.jsx:程序入口文件index.css:全局样式重置App.jsx和App2.jsx:两个不同的根组件示例App.css:组件专属样式readme.md:知识点说明文档
接下来,我们将逐个深入分析这些文件,并配上详细解释。
第四章:入口文件 main.jsx ------ 把组件"挂"到网页上
javascript
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import App2 from './App2.jsx'
import App from './App.jsx'
// 组件 = UI + 交互 + 状态
// 组件化开发
// 挂载根组件
// react 一开始就是组件思想,非常的纯粹
createRoot(document.getElementById('root')).render(
<StrictMode>
{/* <App2 /> */}
<App />
</StrictMode>,
)
逐行解析:
-
import { StrictMode } from 'react'引入 React 的严格模式,帮助你在开发时发现潜在问题(比如废弃 API 的使用)。
-
import { createRoot } from 'react-dom/client'这是 React 18 引入的新渲染方式。
createRoot创建一个"根容器",用于管理整个应用的渲染。 -
document.getElementById('root')找到
index.html中的<div id="root"></div>------ 这是 React 应用的"舞台"。 -
import App from './App2.jsx'和import App1 from './App.jsx'同时引入了两个根组件。注意:变量名可以任意取,这里
App1实际指向App.jsx。 -
<StrictMode> ... </StrictMode>包裹整个应用,开启开发辅助检查。
-
{/* <App /> */}这是 JSX 的注释语法(类似 HTML 的
<!-- -->,但在{}内)。 -
<App1 />当前实际渲染的是
App.jsx的内容(因为App1是它的别名)。
关键知识点:
- React 应用必须通过
createRoot(...).render(...)挂载到 DOM 节点上。- 你可以在
main.jsx中自由切换使用App2(静态页面)或App(动态页面)。
第五章:静态页面示例 ------ App2.jsx(组件化思维)
javascript
function JuejinHeader() {
// jsx 最外层只能有一个元素,需要一个包裹元素,例如一个div
return (
<div>
<header>
<h1>掘金首页</h1>
</header>
</div>
)
}
const Ariticles = () => {
return (
<div>
<section>
<h2>文章列表</h2>
<ul>
<li>文章1</li>
<li>文章2</li>
<li>文章3</li>
</ul>
</section>
</div>
)
}
const Checkin = () => {
return (
<div>
<section>
<h2>签到组件</h2>
<button>签到</button>
</section>
</div>
)
}
const HotArticles = () => {
return (
<div>
<section>
<h2>热门文章</h2>
<ul>
<li>热门文章1</li>
<li>热门文章2</li>
<li>热门文章3</li>
</ul>
</section>
</div>
)
}
function App() {
// 子组件们(JuejinHeader、Ariticles、Checkin、HotArticles)构成父组件(App)
return (
<div>
{/* <h1>Hello <b>React</b></h1> */}
{/* 头部组件 */}
<JuejinHeader />
<main>
{/* 组件也和html一样申明,自定义组件 */}
{/* 组件化让我们像搭积木一样组合成页面 */}
<Ariticles />
<aside>
<Checkin />
<HotArticles />
</aside>
</main>
</div>
)
}
// 导出组件
export default App
核心概念详解:
1. 函数就是组件
在 React 中,任何返回 JSX 的函数就是一个组件 。你可以用 function 声明,也可以用箭头函数(const MyComponent = () => {...})。
✅ 规则:组件名必须以大写字母开头(如
JuejinHeader),否则 React 会把它当作普通 HTML 标签!
2. JSX 最外层只能有一个根元素
每个组件的 return 必须是一个单一的 JSX 元素。如果想返回多个兄弟元素,必须用 <div>、<section> 或 <>...</>(Fragment)包裹。
3. 组件组合 = 页面搭建
App 组件没有写具体 UI,而是直接"调用"了四个子组件:
<JuejinHeader />:头部<Ariticles />:主内容区<Checkin />和<HotArticles />:侧边栏
这就像:
- 你设计一栋楼(
App) - 让工人分别建厨房、卧室、客厅(子组件)
- 最后拼在一起
优势 :每个组件独立开发、测试、复用。比如
Checkin组件以后可以用在其他页面!
4. JSX 注释语法
在 JSX 中写注释要用 {/* 注释内容 */},不能用 // 或 <!-- -->。
第六章:动态交互页面 ------ App.jsx(状态与响应式)
javascript
// 为什么函数就是组件? 因为函数将JSX + 逻辑 封装起来了,这就是组件
// JSX 负责UI
// 样式可在外面引入
import './App.css';
// 引入响应式
// use使用 state数据状态 useState 使用状态
import { createElement, useState } from 'react';
function App() {
// 组件的数据业务逻辑、交互等可以写在前面
// const name = 'React';
// useState 返回一个数组,数组第一个元素是状态值,第二个元素是修改状态值的函数
const [name, setName] = useState('React');
const [todos, seTodos] = useState([
{ id:1, title:"学习React", done:false },
{ id:2, title:"学习Node", done:false },
{ id:3, title:"学习Vue", done:false },
])
const [isLoggedIn, setisLoggedIn] = useState(false)
const toggleLogin = () => {
setisLoggedIn(!isLoggedIn)
};
// 语法糖,主要是简化模板开发,提升代码的可读性
// 所以这就是一段JSX,可作为一个子组件放在UI中运行,但由于是const申明,所以用{}包裹
// 此处用的就是createElement的语法糖
const element = <h2>JSX 是React中用于描述用户界面的语法拓展</h2>
// 与上句效果相同,但此句用了createElement
const element2 = createElement('h2', null, 'JSX 是React中用于描述用户界面的语法拓展2')
setTimeout(() => {
setName('React1');
}, 2000);
return (
// 返回JSX,即组件的UI结构
// 在JSX中 {} 内可以写js表达式或者变量,等同于vue模板语法中的 {{ }}
// <h1>Hello <span>{name}!</span></h1>
// <> </> 是文档碎片标签,用来作为最外层的包裹元素
<>
{element}
{element2}
{/* JSX的js中,class是关键字,所以不能用,要用className代替 */}
<h1>Hello <span className="title">{name}!</span></h1>
{
todos.length > 0 ? (
<ul>
{
// 原生JS react能不用新语法就不用
// xml in js = jsx
// 需要加key属性,帮助react识别每个元素,提升渲染性能
todos.map((todo) => (
<li key={todo.id}>
{todo.title} - {todo.done ? '已完成' : '未完成'}
</li>
))
}
</ul>
) : (<div>暂无待办事项</div>)
}
{isLoggedIn ? <div>已登录</div> : <div>未登录</div>}
<button onClick={toggleLogin}>
{isLoggedIn ? "退出登录" : "登录"}
</button>
</>
)
}
export default App
// 组件拆分
// 组件复用
// 组件组合
重点知识点深度解析:
1. useState:让数据"活"起来
javascript
const [name, setName] = useState('React');
useState是 React 提供的 Hook(钩子),用于在函数组件中添加状态。- 它返回一个数组:
[当前状态值, 更新函数] - 初始值是
'React' - 调用
setName('新名字')会触发组件重新渲染,并更新 UI
神奇之处:你不需要手动操作 DOM!只要改状态,React 自动更新页面。
2. 状态可以是任何类型
name是字符串todos是对象数组isLoggedIn是布尔值
3. JSX 中嵌入 JavaScript 表达式
用 {} 包裹任何 JS 表达式:
- 变量:
{name} - 三元运算:
{isLoggedIn ? "退出" : "登录"} - 函数调用:
{todos.map(...)}
注意:不能直接写
if语句,但可以用三元运算或逻辑与&&。
4. className 替代 class
因为 class 是 JavaScript 的保留关键字,所以在 JSX 中必须写成:
javascript
<span className="title">...</span>
对应的 CSS 在 App.css 中:
css
.title {
color: red;
}
5. 列表渲染与 key 属性
javascript
todos.map((todo) => (
<li key={todo.id}>...</li>
))
map是数组方法,用于遍历生成 JSX 元素- 必须加
key!React 用它来识别哪些项发生了变化、添加或删除 - 最佳实践:使用唯一 ID(如数据库主键),不要用数组索引!
6. 事件处理:onClick
html
<button onClick={toggleLogin}>登录</button>
- 事件名采用驼峰命名(
onClick而不是onclick) - 传入的是函数引用(不加括号!)
- 函数内部调用
setisLoggedIn(!isLoggedIn)切换状态
7. Fragment:<> </>
当不想多一层 <div> 时,用空标签包裹多个兄弟元素:
html
<>
<h1>标题</h1>
<p>段落</p>
</>
编译后不会产生额外 DOM 节点。
8. 两种写 JSX 的方式
-
语法糖(推荐) :
javascriptconst element = <h2>内容</h2> -
原生 API :
javascriptconst element2 = createElement('h2', null, '内容')
JSX 本质是 React.createElement() 的语法糖,但更直观易读。
9. 副作用示例:setTimeout
javascript
setTimeout(() => {
setName('React1');
}, 2000);
2 秒后自动把标题从 "React" 改成 "React1"。这展示了 状态驱动 UI 更新 的核心思想。
💡 注意:在真实项目中,这类副作用应使用
useEffectHook 管理,但入门阶段可以先这样理解。
第七章:样式文件 index.css 与 App.css
index.css(全局重置)
css
* {
margin: 0;
padding: 0;
}
这是最简单的 CSS 重置,消除浏览器默认间距,让布局更可控。
App.css(组件样式)
css
.title {
color: red;
}
通过 import './App.css' 引入,作用于整个组件。未来你可以学习 CSS Modules 实现样式局部作用域。
第八章:总结所有核心知识点
根据以上所有代码,我们整理出 React 入门必知概念:
| 知识点 | 说明 |
|---|---|
| JSX | JavaScript 的语法扩展,允许在 JS 中写类似 HTML 的结构(XML in JS) |
| 组件 = UI + 交互 + 状态 | 组件是封装了界面、逻辑和数据的独立单元 |
| 函数就是组件 | 只要函数返回 JSX,它就是一个 React 组件 |
| 组件化开发 | 将页面拆分为多个组件,像搭积木一样组合 |
| 组件树代替 DOM 树 | React 内部维护虚拟 DOM 树,高效更新真实 DOM |
| 响应式(Reactive) | 数据变化自动触发 UI 更新 |
| 数据绑定(Data Binding) | 通过状态(state)实现单向数据流 |
useState |
用于在函数组件中声明和更新状态 |
key 属性 |
帮助 React 识别列表中每个元素的唯一性,提升性能 |
className |
JSX 中替代 HTML 的 class 属性 |
Fragment <> |
用于包裹多个兄弟元素而不产生额外 DOM 节点 |
| 事件处理 | 使用 onClick 等驼峰命名事件,传入函数引用 |
第九章:动手实验建议
-
切换组件
修改
main.jsx,注释掉<App2 />,取消注释<App />,观察静态页面效果。 -
添加新功能
在
App.jsx中:- 添加一个"添加待办"按钮
- 实现点击"签到"按钮改变文字
-
调试技巧
在
return前加console.log(name, todos),观察状态变化。 -
样式实验
修改
App.css,给按钮加背景色:cssbutton { background: blue; color: white; border: none; padding: 8px 16px; cursor: pointer; }
第十章:结语 ------ 你已经迈出了第一步!
React 的学习曲线看似陡峭,但只要你理解了:
"组件是积木,状态是魔法,JSX 是桥梁"
你就已经掌握了现代前端开发的核心范式。
记住:
- 不要怕犯错,React 的错误提示非常友好
- 多动手,少死记
- 组件化思维会让你受益终身
现在,关掉这篇文章,打开你的代码编辑器,亲手敲一遍这些代码。你会发现,React 并不可怕,反而充满乐趣!🚀
"编程不是关于写代码,而是关于解决问题。" ------ 而 React,给了你一套优雅的工具箱。