React 标准 SPA 项目 入门学习记录
一、React 是什么?
React 是由 Facebook 开发的用于构建用户界面的 JavaScript 库。它采用组件化思想,让 UI 开发更高效、可复用、易维护。
核心特点:
- 组件化开发
- 虚拟 DOM(高性能)
- 单向数据流
- JSX 语法(JavaScript + HTML)
二、标准 React SPA 项目
SPA(Single Page Application)单页应用,整个应用只有一个 HTML 页面(通常是 index.html)。
页面切换时,不刷新整个页面,而是通过 JavaScript 动态替换部分内容(如使用 React Router)。
用户体验更流畅,类似原生 App。首次加载会下载所有(或大部分)JS/CSS 资源,后续路由跳转无需重新请求 HTML。
标准项目结构如下:
my-react-app/
├── public/
│ └── index.html ← 唯一的 HTML 入口(SPA 核心)
├── src/
│ ├── App.jsx ← 根组件
│ ├── main.jsx ← 应用入口(渲染到 #root)
│ ├── components/ ← 可复用 UI 组件
│ ├── pages/ ← 页面级组件(配合路由)
│ ├── hooks/ ← 自定义 Hook
│ ├── assets/ ← 图片、字体等静态资源
│ └── index.css ← 全局样式
├── package.json ← 依赖和脚本
└── vite.config.js ← 构建配置(若使用 Vite)
三、核心概念速览
1. JSX 语法 —— JavaScript 中写 HTML
function App() {return <h1>Hello, React!</h1>;
}
注意:JSX 中 class 要写成
className
,事件用驼峰如onClick
2. 组件 —— UI 的构建块
函数组件(推荐)
function Welcome(props) {return <h2>Hello, {props.name}</h2>;
}// 使用组件
function App() {return (<div><Welcome name="Alice" /><Welcome name="Bob" /></div>);
}
3. 状态管理 —— useState Hook
import { useState } from 'react';function Counter() {const [count, setCount] = useState(0); // 初始化状态return (<div><p>你点击了 {count} 次</p><button onClick={() => setCount(count + 1)}>点我加一</button></div>);
}
✅
useState
返回一个状态变量和更新它的函数
4. 生命周期 & 副作用 —— useEffect Hook
import { useState, useEffect } from 'react';function Timer() {const [seconds, setSeconds] = useState(0);useEffect(() => {const timer = setInterval(() => {setSeconds(s => s + 1);}, 1000);// 清理函数:组件卸载时执行return () => clearInterval(timer);}, []); // 空数组 = 只在组件挂载时执行一次return <div>已运行:{seconds} 秒</div>;
}
✅
useEffect
用于处理副作用(如数据获取、订阅、定时器等)
在 React 中,“副作用”指的是组件渲染之外的操作,比如:
- 发起网络请求(fetch API)
- 订阅事件(WebSocket、键盘事件)
- 操作 DOM(非 React 控制的元素)
- 启动定时器(setInterval / setTimeout) ← 你这个例子!
- 修改全局变量或文档标题
这些操作不应该在组件主体内直接执行(会导致每次渲染都重复执行、内存泄漏等),而应该放在 useEffect 中管理
5. 条件渲染 & 列表渲染
function TodoList({ todos }) {if (todos.length === 0) {return <p>暂无待办事项</p>;}return (<ul>{todos.map(todo => (<li key={todo.id}>{todo.text}</li>))}</ul>);
}
✅ 列表必须加
key
(唯一标识),提升性能和稳定性
四、实战小项目:
创建一个简单的待办事项应用,包含添加、删除、显示功能。
1. 创建 Todo 组件
// src/components/TodoList.jsx
import { useState } from 'react';export default function TodoList() {const [todos, setTodos] = useState([]);const [inputValue, setInputValue] = useState('');const addTodo = () => {if (inputValue.trim()) {setTodos([...todos,{ id: Date.now(), text: inputValue, completed: false }]);setInputValue('');}};const deleteTodo = (id) => {setTodos(todos.filter(todo => todo.id !== id));};return (<div><h2>我的待办事项</h2><inputvalue={inputValue}onChange={e => setInputValue(e.target.value)}placeholder="输入待办事项"/><button onClick={addTodo}>添加</button><ul>{todos.map(todo => (<li key={todo.id}>{todo.text}<button onClick={() => deleteTodo(todo.id)}>删除</button></li>))}</ul></div>);
}
2. 在 App.jsx 中使用
// src/App.jsx
import TodoList from './components/TodoList';function App() {return (<div className="App"><TodoList /></div>);
}export default App;
✅ 运行项目,你就能添加和删除待办事项了!
五、进阶概念
1. 样式处理
- 使用 CSS Modules:
Button.module.css
- 或 Tailwind CSS / Styled-components
CSS Modules:一种在 组件级别 引入 CSS 样式的方案,它通过构建工具(如 Vite、Webpack)在编译时自动为类名生成唯一哈希值,从而实现:
2. 路由(React Router)
路由(Routing):根据不同的 URL 地址,显示不同的页面内容,而无需刷新整个网页。
npm install react-router-dom
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import Home from './pages/Home';
import About from './pages/About';function App() {return (<BrowserRouter><Routes><Route path="/" element={<Home />} /><Route path="/about" element={<About />} /></Routes></BrowserRouter>);
}
3. 状态管理进阶
- 小项目:
useContext
+useReducer
- 大项目:Redux Toolkit / Zustand
4. 数据请求
使用 fetch
或 axios
+ useEffect
useEffect(() => {fetch('/api/todos').then(res => res.json()).then(data => setTodos(data));
}, []);
六、总结
概念 | 作用 | 使用方式 |
---|---|---|
组件 | UI 模块化 | 函数组件 + JSX |
useState | 管理状态 | const [state, setState] = useState() |
useEffect | 处理副作用 | useEffect(() => {}, [deps]) |
条件/列表渲染 | 动态展示内容 | {condition && <Comp />} / map() |
Props | 父传子数据 | <Child name="xxx" /> |