第一个React应用 #
一、创建项目 #
1.1 使用Vite创建 #
bash
npm create vite@latest my-first-react-app -- --template react
cd my-first-react-app
npm install
npm run dev
1.2 项目结构 #
text
my-first-react-app/
├── public/
│ └── vite.svg # 静态资源
├── src/
│ ├── App.css # App组件样式
│ ├── App.jsx # App组件
│ ├── index.css # 全局样式
│ └── main.jsx # 应用入口
├── index.html # HTML模板
├── package.json # 项目配置
└── vite.config.js # Vite配置
二、入口文件解析 #
2.1 index.html #
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>My First React App</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>
关键点:
<div id="root">是 React 应用的挂载点<script>引入入口 JS 文件
2.2 main.jsx #
javascript
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App.jsx';
import './index.css';
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<App />
</React.StrictMode>
);
代码解析:
| 代码 | 说明 |
|---|---|
import React |
引入 React 核心库 |
import ReactDOM |
引入 React DOM 渲染器 |
createRoot() |
创建 React 18 的根容器 |
render() |
渲染组件到 DOM |
<React.StrictMode> |
严格模式,检测潜在问题 |
2.3 App.jsx #
javascript
import { useState } from 'react';
import './App.css';
function App() {
const [count, setCount] = useState(0);
return (
<div className="App">
<h1>我的第一个React应用</h1>
<div className="card">
<button onClick={() => setCount((count) => count + 1)}>
点击次数: {count}
</button>
</div>
</div>
);
}
export default App;
三、创建计数器应用 #
让我们创建一个完整的计数器应用,学习 React 的核心概念。
3.1 完整代码 #
javascript
import { useState } from 'react';
import './App.css';
function Counter() {
const [count, setCount] = useState(0);
const increment = () => {
setCount(count + 1);
};
const decrement = () => {
setCount(count - 1);
};
const reset = () => {
setCount(0);
};
return (
<div className="counter-container">
<h1>计数器</h1>
<div className="count-display">
<span className={count >= 0 ? 'positive' : 'negative'}>
{count}
</span>
</div>
<div className="button-group">
<button onClick={decrement}>-1</button>
<button onClick={reset}>重置</button>
<button onClick={increment}>+1</button>
</div>
</div>
);
}
export default Counter;
3.2 样式文件 #
css
.counter-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 100vh;
font-family: system-ui, sans-serif;
}
.count-display {
font-size: 4rem;
margin: 2rem 0;
}
.positive {
color: #4caf50;
}
.negative {
color: #f44336;
}
.button-group {
display: flex;
gap: 1rem;
}
button {
padding: 0.5rem 1.5rem;
font-size: 1rem;
cursor: pointer;
border: none;
border-radius: 4px;
background-color: #2196f3;
color: white;
transition: background-color 0.2s;
}
button:hover {
background-color: #1976d2;
}
四、核心概念解析 #
4.1 组件 #
React 应用由组件构成:
javascript
// 函数组件
function Welcome() {
return <h1>Hello, React!</h1>;
}
// 箭头函数组件
const Welcome = () => <h1>Hello, React!</h1>;
组件规则:
- 组件名必须大写开头
- 返回 JSX 语法
- 只返回一个根元素
4.2 JSX #
JSX 是 JavaScript 的语法扩展:
javascript
// JSX语法
const element = <h1>Hello, React!</h1>;
// 等价于
const element = React.createElement('h1', null, 'Hello, React!');
JSX规则:
javascript
// 1. 使用className代替class
<div className="container"></div>
// 2. 使用camelCase命名事件
<button onClick={handleClick}>点击</button>
// 3. 使用{}嵌入JavaScript表达式
<div>{count}</div>
// 4. 条件渲染
<div>{count > 0 ? '正数' : '非正数'}</div>
// 5. 列表渲染
<ul>
{items.map(item => <li key={item.id}>{item.name}</li>)}
</ul>
4.3 State(状态) #
State 是组件内部的数据:
javascript
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
// ↑状态值 ↑更新函数 ↑初始值
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>
增加
</button>
</div>
);
}
State规则:
- 不要直接修改 state,使用 setState
- state 更新是异步的
- state 更新会触发重新渲染
4.4 Props(属性) #
Props 用于组件间传递数据:
javascript
function Welcome({ name, age }) {
return (
<div>
<h1>Hello, {name}!</h1>
<p>Age: {age}</p>
</div>
);
}
function App() {
return <Welcome name="React" age={10} />;
}
五、创建Todo应用 #
让我们创建一个简单的 Todo 应用:
5.1 完整代码 #
javascript
import { useState } from 'react';
import './App.css';
function TodoApp() {
const [todos, setTodos] = useState([]);
const [inputValue, setInputValue] = useState('');
const addTodo = () => {
if (inputValue.trim() === '') return;
setTodos([
...todos,
{
id: Date.now(),
text: inputValue,
completed: false
}
]);
setInputValue('');
};
const toggleTodo = (id) => {
setTodos(todos.map(todo =>
todo.id === id
? { ...todo, completed: !todo.completed }
: todo
));
};
const deleteTodo = (id) => {
setTodos(todos.filter(todo => todo.id !== id));
};
const handleKeyPress = (e) => {
if (e.key === 'Enter') {
addTodo();
}
};
return (
<div className="todo-app">
<h1>Todo List</h1>
<div className="input-group">
<input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
onKeyPress={handleKeyPress}
placeholder="添加新任务..."
/>
<button onClick={addTodo}>添加</button>
</div>
<ul className="todo-list">
{todos.map(todo => (
<li key={todo.id} className={todo.completed ? 'completed' : ''}>
<input
type="checkbox"
checked={todo.completed}
onChange={() => toggleTodo(todo.id)}
/>
<span>{todo.text}</span>
<button onClick={() => deleteTodo(todo.id)}>删除</button>
</li>
))}
</ul>
{todos.length > 0 && (
<div className="stats">
总计: {todos.length} |
已完成: {todos.filter(t => t.completed).length}
</div>
)}
</div>
);
}
export default TodoApp;
5.2 样式文件 #
css
.todo-app {
max-width: 500px;
margin: 2rem auto;
padding: 1rem;
}
.input-group {
display: flex;
gap: 0.5rem;
margin-bottom: 1rem;
}
.input-group input {
flex: 1;
padding: 0.5rem;
font-size: 1rem;
border: 1px solid #ddd;
border-radius: 4px;
}
.todo-list {
list-style: none;
padding: 0;
}
.todo-list li {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.5rem;
border-bottom: 1px solid #eee;
}
.todo-list li.completed span {
text-decoration: line-through;
color: #999;
}
.stats {
margin-top: 1rem;
font-size: 0.875rem;
color: #666;
}
六、项目运行流程 #
text
┌─────────────────────────────────────────────────────┐
│ React 应用流程 │
├─────────────────────────────────────────────────────┤
│ │
│ 1. index.html │
│ └── 加载 <div id="root"> │
│ │
│ 2. main.jsx │
│ └── createRoot() 创建根容器 │
│ └── render(<App />) 渲染根组件 │
│ │
│ 3. App.jsx │
│ └── 执行组件函数 │
│ └── 返回 JSX │
│ └── useState 初始化状态 │
│ │
│ 4. React DOM │
│ └── 将 JSX 转换为虚拟DOM │
│ └── Diff 算法计算差异 │
│ └── 更新真实DOM │
│ │
│ 5. 用户交互 │
│ └── 触发事件 │
│ └── 调用 setState │
│ └── 重新渲染组件 │
│ │
└─────────────────────────────────────────────────────┘
七、总结 #
创建 React 应用的关键步骤:
| 步骤 | 说明 |
|---|---|
| 创建项目 | 使用 Vite 脚手架 |
| 理解入口 | main.jsx 是应用入口 |
| 编写组件 | 使用函数组件和 JSX |
| 管理状态 | 使用 useState Hook |
| 处理事件 | 绑定事件处理函数 |
核心要点:
- React 应用由组件构成
- JSX 是声明式 UI 语法
- State 驱动 UI 更新
- Props 用于组件通信
最后更新:2026-03-26