学习 React:中文快速入门指南 – wiki基地


学习 React:中文快速入门指南

欢迎来到 React 的世界!

如果你是前端开发新手,或是希望从其他框架转向 React,那么你来对地方了。React 是一个用于构建用户界面的 JavaScript 库,由 Facebook(现 Meta)及其社区维护。凭借其组件化、声明式和高效的特性,React 已经成为构建现代 Web 应用和移动应用(通过 React Native)的主流选择之一。

本指南将带领你快速掌握 React 的核心概念和基础用法,帮助你迈出学习 React 的第一步。我们将从环境搭建开始,逐步深入组件、JSX、Props、State、事件处理、条件渲染、列表渲染以及 Hooks 这些基石。

准备好了吗?让我们开始吧!

1. React 是什么?为什么选择 React?

React 是什么?

React 不是一个完整的框架,而是一个专注于构建用户界面的 JavaScript 库。它的核心理念是将复杂的 UI 拆分成独立、可复用的组件,通过管理组件的状态来驱动 UI 的更新。

为什么选择 React?

  1. 组件化: React 的核心是组件。你可以将 UI 划分为独立的、可维护的小块,每个组件只关注自身的数据和渲染逻辑。这大大提高了代码的可读性、可维护性和复用性。
  2. 声明式: 你只需要描述你的 UI 在特定状态下应该是什么样子,React 会负责高效地更新和渲染正确的组件。这使得代码更易于理解和调试,因为你不需要关心具体的 DOM 操作步骤。
  3. 高效: React 使用虚拟 DOM (Virtual DOM) 技术。在状态改变时,React 会先在内存中构建一个新的虚拟 DOM 树,然后将其与旧的虚拟 DOM 树进行比较(Diffing),找出差异,最后只更新实际需要修改的真实 DOM 部分。这种方式最大限度地减少了直接操作真实 DOM 的开销,提高了应用性能。
  4. 生态系统丰富: React 拥有庞大而活跃的社区,围绕 React 衍生出了丰富的库和工具,例如用于路由的 React Router、用于状态管理的 Redux、Zustand 等,以及各种 UI 组件库。
  5. 跨平台: 通过 React Native,你可以使用相同的 React 理念和大部分 JavaScript 知识来构建原生 iOS 和 Android 应用程序。

2. 准备工作:你需要知道什么?

在开始学习 React 之前,你需要具备一些基础知识:

  • HTML & CSS: 了解如何构建网页结构和样式。
  • JavaScript (ES6+): 这是 React 的基础语言。你需要熟悉变量、函数、对象、数组等基本概念,以及 ES6+ 的一些常用特性,如箭头函数 (=>)、letconst、模块导入导出 (import/export)、解构赋值、Promise 等。

此外,你还需要安装:

  • Node.js: React 开发环境依赖 Node.js 及其包管理器 npm 或 yarn 或 pnpm。请访问 Node.js 官网(https://nodejs.org/)下载并安装 LTS (长期支持) 版本。安装 Node.js 后,npm (或 yarn/pnpm) 也将一并安装。

3. 搭建开发环境:创建你的第一个 React 应用

创建 React 应用有多种方式,对于初学者和快速开始,推荐使用现代化的构建工具,如 Vite。Vite 是一个非常快速的前端构建工具,它利用浏览器原生的 ES 模块功能,提供了极速的开发服务器启动和热模块更新。

  1. 打开终端或命令行工具。
  2. 使用 npm, yarn 或 pnpm 创建一个新的 Vite 项目:

    “`bash

    使用 npm

    npm create vite@latest my-react-app –template react

    或者 使用 yarn

    yarn create vite my-react-app –template react

    或者 使用 pnpm (如果你安装了 pnpm)

    pnpm create vite my-react-app –template react
    “`

    这里的 my-react-app 是你的项目名称,--template react 指定使用 React 模板。Vite 还会提供一些变种模板,例如 react-swc 通常更快,你可以选择它。按照命令行提示完成项目的创建。

  3. 进入项目目录:

    bash
    cd my-react-app

  4. 安装项目依赖:

    “`bash
    npm install

    或者 yarn

    或者 pnpm install

    “`

  5. 启动开发服务器:

    “`bash
    npm run dev

    或者 yarn dev

    或者 pnpm dev

    “`

    命令执行后,你会在终端看到类似 Local: http://localhost:5173/ 的输出。复制这个地址并在浏览器中打开,你就看到你的第一个 React 应用正在运行了!

4. 项目结构概览

使用 Vite 创建的 React 项目结构通常比较简洁:

my-react-app/
├── node_modules/ # 项目依赖库
├── public/ # 静态文件,如 index.html, favicon.ico
│ └── index.html # 应用的入口 HTML 文件
├── src/ # 源代码目录
│ ├── assets/ # 静态资源,如图片
│ ├── App.css # App 组件的样式文件
│ ├── App.jsx # 主应用组件
│ ├── index.css # 全局样式文件
│ ├── main.jsx # 应用的入口文件,将 App 组件渲染到 DOM
│ └── react.svg # Vite 默认的 SVG 文件
├── .gitignore # Git 忽略文件配置
├── package.json # 项目配置文件,包含依赖和脚本
├── vite.config.js # Vite 配置文件
└── README.md # 项目说明文件

  • public/index.html 是应用的骨架,你的 React 应用最终会渲染到这个 HTML 文件中的一个特定元素(通常是 <div id="root"><div id="app">)。
  • src/main.jsx (或 src/index.jsx) 是应用的入口文件。它负责导入你的根组件 (App.jsx) 并使用 ReactDOM.createRoot 方法将其渲染到 index.html 中的 DOM 元素上。
  • src/App.jsx 是你的主应用组件,你将在这里构建应用的大部分 UI。

5. React 核心概念

5.1 组件 (Components)

组件是 React 应用的基石。它们是独立、可复用的代码块,负责渲染 UI 的一部分。在现代 React 中,我们主要使用函数组件。

函数组件 (Functional Components):

函数组件是一个 JavaScript 函数,它接收一个 props 对象作为参数,并返回 React 元素(通常由 JSX 创建),描述了 UI 的样子。

“`jsx
// src/components/Greeting.jsx
import React from ‘react’;

function Greeting(props) {
// 函数组件接收 props 作为参数
return (

你好,{props.name}!

// 返回 JSX
);
}

// 导出组件,以便在其他地方使用
export default Greeting;
“`

使用组件:

在另一个组件(比如 App.jsx)中导入并使用它:

“`jsx
// src/App.jsx
import React from ‘react’;
import Greeting from ‘./components/Greeting’; // 导入 Greeting 组件
import ‘./App.css’; // 导入样式

function App() {
return (

{/ 使用 Greeting 组件,并通过 name 属性传递数据 /}

欢迎学习 React!

);
}

export default App;
“`

5.2 JSX (JavaScript XML)

JSX 是一种 JavaScript 的语法扩展,它允许你在 JavaScript 代码中书写类似 HTML 的结构。React 强烈推荐使用 JSX 来描述 UI 的外观。

JSX 的特点:

  • 看起来像 HTML: <div className="app">...</div>
  • 是 JavaScript 的语法糖: JSX 会被 Babel 等工具编译成纯 JavaScript 代码 (调用 React.createElement)。
  • 可以在其中嵌入 JavaScript 表达式: 使用花括号 {} 将 JavaScript 表达式嵌入到 JSX 中。

“`jsx
const name = ‘世界’;
const element =

Hello, {name}!

; // 在 JSX 中使用 {} 嵌入变量

function formatUser(user) {
return user.firstName + ‘ ‘ + user.lastName;
}

const user = { firstName: ‘张’, lastName: ‘三’ };
const greetElement = (

你好,{formatUser(user)}! {/* 在 JSX 中调用函数 */}

);
“`

JSX 注意事项:

  • 必须有一个根元素: JSX 代码块必须被一个父元素包裹,或者使用 React Fragment (<><React.Fragment>)。
    “`jsx
    // 错误:没有单一根元素
    // return (
    //

    标题

    //

    段落

    // );

    // 正确:使用 div 作为根元素
    return (

    标题

    段落

    );

    // 正确:使用 Fragment
    return (
    <>

    标题

    段落

    );
    ``
    * **属性使用 camelCase:** HTML 属性在 JSX 中使用驼峰命名法,例如
    className代替classhtmlFor代替foronClick代替onclick
    * **自闭合标签必须闭合:** 例如
    而不是`。

5.3 Props (属性)

Props 是父组件向子组件传递数据的方式。它们是只读的,子组件不应该直接修改接收到的 props。Props 使得组件更具通用性和可复用性。

我们在上面的 Greeting 例子中已经看到了 props 的使用:

“`jsx
// 父组件 App.jsx 传递 props

// 子组件 Greeting.jsx 接收并使用 props
function Greeting(props) { // props 是一个对象 { name: “React 初学者” }
return (

你好,{props.name}!

);
}
“`

通常,我们会使用 ES6 的对象解构来更方便地访问 props:

jsx
function Greeting({ name }) { // 直接解构出 name 属性
return (
<h1>你好,{name}!</h1>
);
}

5.4 State (状态)

State 是组件内部管理的可变数据。当 State 发生变化时,组件会重新渲染。State 使得组件能够记住用户的输入、是否选中、当前计数等信息。

在函数组件中,我们使用 useState 这个 Hook 来管理 State。

“`jsx
import React, { useState } from ‘react’; // 需要从 react 中导入 useState

function Counter() {
// 声明一个名为 count 的 state 变量,初始值为 0
// setCount 是更新 count 的函数
const [count, setCount] = useState(0);

// 定义一个函数来处理点击事件,更新 state
const handleClick = () => {
// 使用 setCount 更新 state
setCount(count + 1);
// 或者使用函数形式,更安全,特别是当新状态依赖于前一个状态时
// setCount(prevCount => prevCount + 1);
};

return (

你点击了 {count} 次按钮。

);
}

export default Counter;
“`

使用 useState 的注意事项:

  • useState 返回一个数组,第一个元素是当前的 state 值,第二个元素是更新 state 的函数。通常使用数组解构来获取它们。
  • 永远不要直接修改 state 变量(例如 count = count + 1),而是使用 state 更新函数 (setCount)。直接修改不会触发组件重新渲染。
  • setCount 是异步的。如果你需要在更新 state 后立即执行某个依赖新 state 的操作,可以使用 useEffectsetCount 的函数形式。

5.5 事件处理 (Event Handling)

在 React 中处理事件与在普通 HTML 中类似,但有一些区别:

  • 事件名使用 camelCase: 例如 onClick 而不是 onclick
  • 事件处理函数作为值传递: 你传递一个 JavaScript 函数作为事件属性的值,而不是一个字符串。

“`jsx
function MyButton() {
function handleClick() {
alert(‘你点击了按钮!’);
}

return (

);
}

// 如果需要传递参数或访问 event 对象
function AnotherButton() {
function handleClick(event, message) {
// event 是浏览器原生事件对象
console.log(‘Event:’, event);
console.log(‘Message:’, message);
alert(message);
}

return (
// 使用箭头函数来包裹事件处理函数,以便传递额外参数或在渲染时调用

);
}
“`

5.6 条件渲染 (Conditional Rendering)

在 React 中,你可以根据条件决定渲染哪些元素。常用的方法有:

  • if 语句 (在 JSX 外):

    jsx
    function Greeting({ isLoggedIn }) {
    if (isLoggedIn) {
    return <h1>欢迎回来!</h1>;
    }
    return <h1>请先登录。</h1>;
    }

    * 三元运算符 (在 JSX 内):

    jsx
    function Greeting({ isLoggedIn }) {
    return (
    <div>
    {isLoggedIn ? (
    <h1>欢迎回来!</h1>
    ) : (
    <h1>请先登录。</h1>
    )}
    </div>
    );
    }

    * 逻辑与 && (用于条件渲染一个元素或不渲染):

    “`jsx
    function WarningBanner({ warn }) {
    // 如果 warn 为 false,组件将不渲染任何东西
    if (!warn) {
    return null; // 返回 null 或 false 表示不渲染任何内容
    }

    return (

    警告!

    );
    }

    // 在另一个组件中使用
    function Page() {
    const [showWarning, setShowWarning] = useState(true);
    const handleToggleClick = () => {
    setShowWarning(prev => !prev);
    };

    return (


    );
    }

    // 或者在 JSX 中使用 &&
    function MyComponent({ isLoggedIn }) {
    return (

    {isLoggedIn &&

    你已登录。

    } {/ 如果 isLoggedIn 为 true,则渲染

    /}
    {!isLoggedIn &&

    请登录。

    }

    );
    }
    “`

5.7 列表渲染 (List Rendering)

渲染列表元素通常使用 JavaScript 的 map() 方法来处理数组,并将每个元素转换成 React 元素。

“`jsx
function NumberList({ numbers }) {
// 使用 map 遍历数组,为每个数字创建一个

  • 元素
    const listItems = numbers.map((number) =>
    // 重要:列表中每个元素都需要一个唯一的 key prop

  • {number}
  • );

    return (

      {listItems}

    );
    }

    // 在另一个组件中使用
    function App() {
    const numbers = [1, 2, 3, 4, 5];
    return (

    数字列表:

    );
    }
    “`

    关于 key Prop 的重要性:

    key prop 帮助 React 识别列表中哪些项目被改变、添加或删除。它应该是一个在列表内唯一且稳定的字符串或数字。通常使用数据的 ID 作为 key。如果列表项没有稳定的 ID,可以使用索引作为 key但只在列表项不变化、不重排或不增删时才推荐,否则可能导致性能问题或状态错乱。

    “`jsx
    // 使用对象的 id 作为 key (推荐)
    const todos = [
    { id: 1, text: ‘学习 React’ },
    { id: 2, text: ‘构建应用’ },
    { id: 3, text: ‘分享经验’ }
    ];

    function TodoList({ todos }) {
    return (

      {todos.map(todo =>

    • {/ 使用 todo.id 作为 key /}
      {todo.text}
    • )}

    );
    }
    “`

    5.8 Hooks (useState, useEffect 简介)

    Hooks 是 React 16.8 引入的一项重要特性,它们让你在不编写 Class 组件的情况下使用 State 和其他 React 特性(如生命周期)。useState 我们已经见过了。另一个常用的 Hook 是 useEffect

    useEffect:

    useEffect 允许你在函数组件中执行副作用 (side effects)。副作用包括数据获取、订阅、手动更改 DOM、设置定时器等。

    useEffect 接收两个参数:一个包含副作用逻辑的函数,以及一个依赖项数组 (可选)。

    “`jsx
    import React, { useState, useEffect } from ‘react’;

    function DataFetcher({ userId }) {
    const [data, setData] = useState(null);
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState(null);

    // useEffect 会在组件渲染后运行
    useEffect(() => {
    // 这是一个副作用:数据获取
    const fetchData = async () => {
    setLoading(true);
    setError(null);
    try {
    const response = await fetch(https://jsonplaceholder.typicode.com/users/${userId});
    if (!response.ok) {
    throw new Error(‘数据获取失败’);
    }
    const result = await response.json();
    setData(result);
    } catch (err) {
    setError(err);
    } finally {
    setLoading(false);
    }
    };

    fetchData();
    
    // 清理函数 (可选): 在组件卸载或依赖项变化时运行
    return () => {
      // 例如:取消订阅,清除定时器等
      console.log(`清理旧的 userId: ${userId}`);
    };
    

    }, [userId]); // 依赖项数组:只有当 userId 变化时,useEffect 才会重新运行

    if (loading) return

    加载中…

    ;
    if (error) return

    加载失败: {error.message}

    ;

    return (

    用户信息:

    姓名: {data.name}

    邮箱: {data.email}

    );
    }
    “`

    useEffect 的依赖项数组:

    • 空数组 [] 副作用只在组件挂载 (mount) 时运行一次,并在组件卸载 (unmount) 时执行清理(如果返回了清理函数)。这常用于一次性的设置或数据获取。
    • 有依赖项的数组 [prop1, state1] 副作用在组件挂载时运行,并在数组中的任何依赖项发生变化时重新运行。
    • 没有依赖项数组 (省略第二个参数): 副作用在每次组件渲染后都会运行。这应该谨慎使用,因为它可能导致性能问题或无限循环。

    6. 动手实践:一个简单的计数器

    现在,让我们综合运用学到的知识,在 App.jsx 中创建一个更完整的计数器组件。

    修改 src/App.jsx 文件:

    “`jsx
    import React, { useState } from ‘react’;
    import ‘./App.css’; // 导入 App 的样式

    function App() {
    // 使用 useState Hook 来管理计数器的状态
    const [count, setCount] = useState(0);

    // 处理点击增加按钮的函数
    const handleIncrement = () => {
    setCount(prevCount => prevCount + 1); // 使用函数形式确保基于最新状态更新
    };

    // 处理点击减少按钮的函数
    const handleDecrement = () => {
    // 也可以直接使用 count,但函数形式更安全
    setCount(count – 1);
    };

    // 处理点击重置按钮的函数
    const handleReset = () => {
    setCount(0);
    };

    // 渲染计数器 UI
    return (

    简单的计数器

    当前计数: {count}

    {/ 显示当前计数 /}

        {/* 按钮区域 */}
        <div className="button-container">
          {/* 减少按钮,当 count <= 0 时禁用 */}
          <button onClick={handleDecrement} disabled={count <= 0}>
            减少
          </button>
    
          {/* 增加按钮 */}
          <button onClick={handleIncrement}>
            增加
          </button>
    
          {/* 重置按钮,当 count === 0 时禁用 */}
          <button onClick={handleReset} disabled={count === 0}>
            重置
          </button>
        </div>
    
        {/* 条件渲染:当计数大于 10 时显示一条消息 */}
        {count > 10 && (
          <p className="warning-message">计数有点高了!</p>
        )}
      </header>
    </div>
    

    );
    }

    export default App;
    “`

    src/App.css 中添加一些简单的样式(可以替换默认的样式):

    “`css
    .App {
    text-align: center;
    }

    .App-header {
    background-color: #282c34;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    font-size: calc(10px + 2vmin);
    color: white;
    }

    .count-display {
    font-size: 3em;
    margin: 20px 0;
    }

    .button-container {
    margin-top: 20px;
    }

    .button-container button {
    font-size: 1em;
    padding: 10px 20px;
    margin: 0 10px;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    background-color: #61dafb;
    color: #282c34;
    transition: background-color 0.3s ease;
    }

    .button-container button:hover:not(:disabled) {
    background-color: #21a1f9;
    }

    .button-container button:disabled {
    background-color: #cccccc;
    cursor: not-allowed;
    }

    .warning-message {
    color: yellow;
    margin-top: 20px;
    font-size: 0.9em;
    }
    “`

    保存文件后,你的开发服务器会自动刷新页面。你现在应该能看到一个简单的计数器界面,可以通过按钮增加、减少或重置计数。

    7. 下一步:继续深入学习

    恭喜你!你已经掌握了 React 的核心基础。这仅仅是一个开始。要成为一名熟练的 React 开发者,你还需要学习更多内容:

    • 更多的 Hooks: useContext, useReducer, useCallback, useMemo, useRef 等。
    • 组件之间的通信: 除了 Props (父传子),还有 Context API、事件总线或状态管理库 (如 Redux, Zustand, Pinia) 处理更复杂的组件通信。
    • 路由: 如何使用 React Router 等库实现页面导航。
    • 状态管理: 学习如何使用 Redux, Zustand, Recoil, Context API 等处理应用全局状态。
    • 数据获取: 使用 fetch, axios 或更现代的库如 React Query, SWR 来管理数据加载、缓存和更新。
    • 样式化: CSS Modules, Styled Components, Tailwind CSS 等多种样式方案。
    • 表单处理: 如何在 React 中处理表单输入和提交。
    • 性能优化: Memoization (React.memo), useCallback, useMemo 等。
    • 错误边界 (Error Boundaries): 处理组件渲染过程中的错误。
    • 测试: 组件测试 (如 Testing Library, Jest)。
    • TypeScript: 为你的 React 应用添加类型检查。
    • 服务端渲染 (SSR) 或静态网站生成 (SSG): 了解 Next.js, Gatsby 等框架。

    8. 学习资源

    • React 官方文档: 这是最权威、最全面的学习资源。强烈推荐阅读新的 Beta 版文档(https://react.dev/),它使用了 Hook 作为主要教学方式,对初学者更友好,并且提供了中文翻译选项。
    • MDN Web Docs: 巩固你的 JavaScript 基础。
    • 社区和论坛: Stack Overflow、React 相关的 Discord 群组或社区论坛。
    • 在线课程平台: Udemy, Coursera, Codecademy 等平台提供了许多优质的 React 课程。
    • 技术博客和文章: 关注一些优秀的 React 开发者或技术社区,阅读他们的分享。

    9. 总结

    通过本指南,你了解了 React 的基本概念:

    • 组件化: UI 的构建块。
    • JSX: 在 JavaScript 中编写类似 HTML 的结构。
    • Props: 从父组件向子组件传递数据(单向数据流)。
    • State: 组件内部管理的可变数据。
    • 事件处理: 如何响应用户交互。
    • 条件渲染和列表渲染: 根据数据动态显示 UI。
    • Hooks: 在函数组件中使用 State 和副作用。

    React 的学习曲线是存在的,特别是 Hooks 的概念可能需要一些时间来消化。最重要的是多加练习,动手构建一些小项目。尝试实现一个简单的待办事项列表、一个计算器、一个天气应用等,将学到的概念应用到实际中。

    希望这篇快速入门指南能帮助你顺利踏入 React 开发的大门。祝你学习愉快,编码顺利!


    发表评论

    您的邮箱地址不会被公开。 必填项已用 * 标注

    滚动至顶部