一篇文章带你入门React

231 阅读8分钟

前言

参考资料:本文根据MDN官方文档进行讲解。

  • 使用前提:React 使用称为 JSX(JavaScript 和 XML)的 HTML-in-JavaScript 语法。熟悉 HTML 和 JavaScript 可以帮助你学习 JSX,并更好地确定应用程序中的错误是与 JavaScript 还是与 React 的更特定领域相关。

  • 学习目标:学习如何设置本地 React 开发环境,创建一个启动应用程序,并了解其工作原理。

创建一个React项目

掌握 React 项目的创建是开启开发之旅的第一步。​

  1. 初始化项目:打开终端,使用npm init vite命令,该命令会按照 Vite 提供的模版初始化项目。执行命令后,系统会提示你填写项目名称并选择项目类型和使用的语言,此时选择react作为项目类型,JavaScript作为开发语言 ,即可得到一个基于 Vite 和 React 的项目模版,后续开发将基于此展开。​
  1. 进入项目目录:项目初始化完成后,在终端输入cd 项目名(将 “项目名” 替换为实际创建的项目名称),进入到项目目录中。​
  1. 安装依赖:在项目目录下,执行npm i(这是npm install的缩写)命令,npm 会自动读取项目中的配置文件,将项目运行所需要的各种依赖包下载并安装到node_modules目录中,该目录专门用于存放项目依赖。​
  1. 启动项目:依赖安装完成后,输入npm run dev命令,会给你一个地址。此时,在浏览器中输入这个地址,就能看到初始的 React 项目页面。

完整过程如下:

image.png

image.png

至此,一个可进行开发的 React 项目就创建完成了。

React 项目的目录结构

通过以上步骤,在我们的指定文件下就会生成一个React项目。

一个典型的 React 项目目录结构如下:

image.png

在这个结构中:

  • node_modules:存放项目依赖的第三方包(如 React 等),由 npm i 命令自动安装,无需手动修改,会根据 package.json 中依赖配置管理包内容。

  • index.html:项目的入口 HTML 文件

  • src:目录是开发的核心目录,所有的源代码都存放在这里。

  • components:建议存放 React 组件文件(如 TodoList 组件、TodoItem 组件等 ),用于组件化开发,将页面拆分为独立可复用的功能单元,方便维护和管理。

image.png

  • App.cssApp.jsx 根组件的样式文件,可编写该组件及相关子组件的 CSS 样式,实现组件样式隔离。

  • App.jsx:React 应用的根组件,是页面组件树的顶层,用于组织、渲染其他子组件,编写应用的整体布局和业务逻辑。

初识React

1. 定义React 是一个用于构建用户界面的库。

2. 目标:最大程度地减少开发人员构建 UI 时发生的错误。

3. 实现:它通过使用组件(描述部分用户界面的、自包含的逻辑代码段)来实现此目的。这些组件可以组合在一起以创建完整的 UI,React 将许多渲染工作进行抽象化,使你可以专注于界面设计。

一、开发工具:npm 与 Vite​

1.1 npm:包管理利器​

npm(Node Package Manager) 是 JavaScript 生态重要的 包管理工具。在 React 开发中,它能轻松安装、更新 Redux、React Router 等第三方依赖包,自动处理依赖关系,保障项目稳定运行,同时也是创建 React 项目的必备工具。​

1.2 Vite:高效工程化套件​

Vite 是 React 项目开发的得力助手,类似 “塔吊” 和 “搅拌机”,能快速搭建项目框架,处理代码转换、打包等复杂工作,提供简洁模版代码,让开发者快速启动项目,专注业务逻辑实现。

二、深入理解 React 组件​

2.1 什么是组件​

在 React 中,组件是将 HTML、JavaScript 和 CSS 组合在一起的开发单元。它就像是构成页面的一个个 “积木块”,每个组件都有自己独立的功能和逻辑。

例如,在一个待办事项应用中,App.jsx 通常是根组件,它就像整个应用的 “总指挥”,负责协调和管理其他组件。

但如果我们将所有的代码都写在根组件中,会导致代码过于庞大和复杂。这时,就需要将功能进行拆分,以TodoList组件为例,它将待办事项相关的功能封装在一起,成为一个独立的工作和功能单位。​

2.2 从 DOM 树编程到组件树编程​

在传统的前端开发中,我们常常直接操作 DOM 树来更新页面内容,这种方式不仅繁琐,而且容易出错。

而 React 采用了组件化思想,将页面抽象为组件树,通过组件的状态和属性变化来自动更新 DOM。这种方式使得开发者可以更专注于业务逻辑的实现,而不需要花费大量精力去操作 DOM API。​

2.3 函数式组件:简洁高效的开发方式​

函数式组件是 React 中最常用的组件形式之一。一个函数式组件本质上就是一个 JavaScript 函数,它接收一些数据(props)作为输入,然后返回一段 JSX 代码(类似 HTML 的语法)。

在函数中,我们可以在return之前声明数据和处理业务逻辑,return时将数据绑定到 JSX 模版中。例如:

function Todos(props){
    // 如何拿到父组件传过来的数据状态呢? - 传参
    const todos = props.todos
    return(
        <ul>
            {
                todos.map(todo=>(
                    <li key={todo.id}>{todo.text}</li>
                ))
            }
        </ul>
    )
}
export default Todos;

代码解析

效果图: image.png

image.png

这段代码实现了一个基础的待办事项列表应用,由三个核心组件构成:AppTodoList 和 TodoForm,我们来看看它们是如何联系起来的:

组件关系概览

  1. App 组件(根组件)

    • 作为整个应用的入口,渲染 TodoList 组件。
    • 无状态,仅负责组件组合。
  2. TodoList 组件(状态管理核心)

    • 管理待办事项的状态(todos)和标题(title)。
    • 提供添加待办的方法(handleAdd)。
    • 渲染 TodoForm(表单输入)和 Todos(列表展示)。
  3. TodoForm 组件(表单输入)

    • 负责处理用户输入和表单提交。
    • 通过回调函数(onAdd)将输入数据传递给父组件(TodoList)。
  4. Todos 组件(列表展示)

    • 接收父组件传递的 todos 数据并渲染列表。

完整代码注解

// App.jsx - 应用根组件
import { useState } from 'react'
import './App.css'
import TodoList from './components/TodoList'

function App() {
  // 作为应用的根组件,负责组合其他核心组件
  // 本应用中只渲染TodoList组件,实际项目可能包含更多组件
  return (
    <>
      {/* 渲染TodoList组件,该组件管理待办事项的核心逻辑 */}
      <TodoList />
    </>
  )
}
export default App
// TodoList.jsx - 待办事项列表的核心管理组件
import { useState } from 'react'
import '../Todo.css'
import TodoForm from './TodoForm' // 导入表单组件
import Todos from './Todos' // 导入列表展示组件

function TodoList() {
    // 状态管理:使用useState钩子创建和管理组件状态
    const [title, setTitle] = useState('Todo List') // 页面标题状态
    const [todos, setTodos] = useState([ // 待办事项列表状态,初始有一个示例项
        {
            id: 1,
            text: '吃饭',
            completed: false
        },
    ])

    // 添加新待办事项的处理函数
    const handleAdd = text => {
        // 使用展开运算符保留原有数据,并添加新的待办事项
        // 自动生成id,使用当前数组长度+1
        setTodos([
            ...todos,
            {
                id: todos.length + 1,
                text, // ES6简写,等同于text: text
                completed: false
            }
        ])
    }
    
    return (
       <div className="container">
            <h1 className="title">{title}</h1>
            {/* 
              渲染表单组件,并通过props传递handleAdd函数
              子组件(TodoForm)可以通过onAdd属性调用此函数
            */}
            <TodoForm onAdd={handleAdd} />
            
            {/* 
              渲染列表展示组件,通过props传递todos数据
              Todos组件将根据这些数据渲染待办事项列表
            */}
            <Todos todos={todos} />
       </div>
    );
}

export default TodoList;
// TodoForm.jsx - 负责处理用户输入的表单组件
import { useState } from "react";

function TodoForm(props) {
    // 从父组件接收onAdd函数,用于提交新待办事项
    const onAdd = props.onAdd;
    
    // 管理输入框的本地状态,初始值为"打豆豆"
    const [text, setText] = useState('打豆豆');
    
    // 表单提交处理函数
    const handleSubmit = e => {
        // 阻止表单默认提交行为,避免页面刷新
        e.preventDefault();
        // 调用父组件传递的回调函数,将当前输入的文本传递给父组件
        onAdd(text);
        // 提交后清空输入框
        setText('');
    }
    
    // 输入框内容变化处理函数
    const handleChange = e => {
        // 获取输入框的当前值,并更新本地状态
        setText(e.target.value);
    }
    
    return (
        <form action="#" onSubmit={handleSubmit}>
            <input
                type="text"
                placeholder="请输入待办事项"
                value={text} // 将输入框的值与状态绑定
                onChange={handleChange} // 绑定变化处理函数
            />
            <button type="submit">添加</button>
        </form>
    )
}

export default TodoForm;
// Todos.jsx - 负责渲染待办事项列表的纯展示组件
function Todos(props) {
    // 从父组件接收todos数据
    const todos = props.todos
    
    return (
        <ul>
            {/* 使用map方法遍历todos数组,为每个待办事项创建一个列表项 */}
            todos.map(todo => (
                // 每个列表项必须有唯一的key属性,优化React渲染性能
                <li key={todo.id}>{todo.text}</li>
            ))
        </ul>
    )
}

export default Todos;

结尾​

要成为一名合格的前端开发者,掌握组件化开发和响应式数据状态管理是关键。通过不断学习和实践,熟练运用 React 的各种特性和工具,就能开发出功能丰富、性能良好的前端应用。​

通过以上内容,相信你对 React 已经有了一个初步的了解。接下来,不妨亲自尝试创建一个简单的 React 项目,在实践中加深对这些概念的理解和掌握。随着学习的深入,你会发现 React 的更多强大功能和应用场景,开启精彩的前端开发之旅。​