第一个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