React快速了解

项目构建

创建react项目

npm create vite

之后选择框架 react,之后选择自己熟悉的语言,之后的项目构建使用的是TypeScript

cd react-app //进入项目目录
npm i       //安装第三方依赖
npm run dev //启动本地服务器

编译项目

npm run build
yarn build

启动开发服务器

npm run dev

React目录结构

image-20250308220730414.png

src

这是项目的“心脏”,你写的代码和资源都在这里。src 是“source”(源代码)的缩写。

  • assets:放静态资源,比如图片、字体这些东西

  • components:常用命名习惯。存放一个个组件。组件相当于一个功能,比如一个按钮、一个消息框

  • vite-env.d.ts:vite-env.d.ts 是一个专门用来声明 Vite 项目中环境类型定义的文件。通常,Vite 项目会自动生成这个文件,并默认包含这行指令。

    这个文件初始的代码

    /// <reference types="vite/client" />

    这行代码的主要目的是让 TypeScript 能够识别和使用 Vite 在客户端(client-side)提供的类型定义。vite/client 是 Vite 内置的一个类型声明文件,里面包含了 Vite 在客户端运行时提供的全局变量、函数和模块的类型信息。

public

这个文件夹放了一些不会被代码加工的文件,比如图片、图标或者 HTML 模板,这些是“静态”的东西。

React文件结构

index.html

<!DOCTYPE html> //声明这是一个 HTML5 文档
<html lang="en"> //lang="en" 表示页面语言为英语。
  <head> //标签包含页面的元数据和外部资源
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" /> //设置浏览器标签页的图标(favicon),这里使用 Vite 的 SVG 图标
    <meta name="viewport" content="width=device-width, initial-scale=1.0" /> //控制移动设备上的视口,使页面宽度适配设备屏幕,默认缩放比例为 1。
    <title>Vite + React + TS</title> //定义浏览器标签页的标题,这里是 “Vite + React + TS”
  </head>
  <body> //标签包含页面的可见内容和脚本加载逻辑
    <div id="root"></div> 一个空的 <div> 元素,ID 为 root,是 React 应用的挂载点
    <script type="module" src="/src/main.tsx"></script> //引入 React 应用的入口文件 /src/main.tsx,并以 ES 模块方式加载。
  </body>
</html>
  1. 提供 HTML 结构:为 React 应用提供一个基本的 HTML 框架,作为应用的“外壳”。
  2. 设置元数据:通过 head 中的标签,确保页面在不同设备和浏览器中正确显示。
  3. 挂载 React 应用:通过 div id="root" 提供一个 DOM 节点,供 React 渲染组件。
  4. 加载脚本:通过 script 标签引入应用的入口文件,启动 React 的运行逻辑。换句话讲,就是所有组件的集合文件,所有单个组件的逻辑融合在一起,被加载出来。

main.tsx

import React from 'react' // 导入了 React 库,它提供了创建组件、使用 JSX 语法以及管理虚拟 DOM 的能力
import ReactDOM from 'react-dom/client' // ReactDOM 库的 client 模块,ReactDOM 是 React 和浏览器 DOM(文档对象模型)之间的桥梁。createRoot 方法来自这个模块,用于创建 React 应用的根节点,从这里开始渲染组件。
import App from './App' //App 是应用的根组件,包含了整个应用的结构和逻辑,其他子组件会嵌套在其中。这个是我们后续完善单个组件融合之后的子集合文件。
import 'bootstrap/dist/css/bootstrap.css' //Bootstrap 的 CSS 文件

ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
)

Bootstrap 是一个流行的 CSS 框架,提供了预定义的样式类(比如按钮、网格、表单等),导入后可以在项目中直接使用这些样式来美化界面。

安装命令

npm i bootstrap@5.2.3

我们这里将原来的 index.css 文件删除了。组件使用预定义好的css样式。

App.tsx

这是一个根组件文件,Button 和 Alert 是两个子组件。

import Button from "./components/Button";
import Alert from "./components/Alert";
import { useState } from "react"; //React 提供的一个 Hook,专门用于在函数组件中管理状态(state)

function App() {
  const [alert,setalert] = useState(false);
  return (
    <div>
      {alert && <Alert onClose={() => setalert(false)}>My alert</Alert>}
      <Button color = "secondary" onClick={() => setalert(true)}>MY Button</Button>
    </div>
  );
}

export default App;
  • const [alert,setalert] = useState(false);

    它返回一个数组,数组中有两个元素,第一个元素是状态变量(这里是 alert),表示当前的状态值。第二个元素是更新状态的函数(这里是 setAlert),用于修改状态变量的值。

    这里定义了一个状态变量 alert,它的初始值被设置为 false,setAlert 是一个函数,通过调用它可以更新 alert 的值。就比如 onClick={() => setalert(true)} ,我们向 setalert 函数传入true参数来更改 alert 的值

ListGroup.tsx

这一个列表功能的组件。我们这里只定义了组件的逻辑,而参数是通过接口 Props 传入的。

import { Fragment, useState } from "react";

interface Props {
    items : string[];
    heading: string;
    onselect:(item: string) => void
};

function ListGroup({items,heading,onselect}:Props) {

  //Hook
  const [selectedIndex, setSelectedIndex] = useState(-1);

  const handleSelectItem = (item : string) => {
    console.log(item);
  }

  const getMessage = () => {
    return items.length === 0 ? <p>No item found</p> : null;
  };

  return (
    <>
      <h1>{heading}</h1>
      {items.length === 0 && <p>No item found</p>}
      <ul className="list-group">
        {items.map((item, index) => (
          <li
            className={
              selectedIndex === index
                ? "list-group-item active"
                : "list-group-item"
            }
            key={item}
            onClick={() => {
                setSelectedIndex(index);
                onselect(item)
            }}
          >
            {item}
          </li>
        ))}
      </ul>
    </>
  );
}

export default ListGroup;
  • className命名

    在 React 中,要给 HTML 元素添加 CSS 类,必须使用 className,而不是 HTML 中的 class。这是因为 class 是 JavaScript 的保留关键字,在 React 的 JSX 语法中会引起冲突, class 不是有效的属性。

  • {items.length === 0 && <p>No item found</p>}

    • 在 React 的 JSX 语法中,花括号 {} 是用来嵌入 JavaScript 表达式的。当你需要在 JSX 中运行 JavaScript 代码并将结果插入到标记中时,必须用 {} 包裹它。这样 JSX 解析器就知道这里是 JavaScript,而不是普通的文本。
    • 这里使用了逻辑与进行运算
  • Fragment 的用法

    Fragment 允许你将多个元素分组,而不在 DOM 中添加额外节点。一个组件return只能返回一个节点,节点也就是指元素:如 &lt;div>、&lt;h1>、&lt;p> ,或者是文本节点&lt;ul>等。相比使用&lt;div>来包裹返回一个对象,使用 &lt;Fragment>&lt;/Fragment> 或者简写为  &lt;>&lt;/>。使用 &lt;div> 作为根元素时,会在最终的 DOM 树中多出一个 &lt;div> 节点,而使用 Fragment(可以用 &lt;>...&lt;/> 表示)时,不会生成额外的节点。最终只会返回下面的结构
    
    &lt;h1>标题&lt;/h1>
    &lt;p>内容&lt;/p>
  • map方法

    map 方法的作用是将 items 数组中的每个字符串转换为一个带有动态样式和点击事件的 li 元素,并将这些元素组合成一个列表渲染到页面。自动遍历数组里面的元素。

  • key 属性的作用

    在 React 中,当你用 map 方法渲染一个列表时,比如显示一组数据,React 需要知道每个列表项的“身份”。key 就是一个唯一的标识符,帮助 React 高效地追踪和管理这些列表项。

    假设待办事项是这样的

    const items = ["买牛奶", "写作业", "打扫房间"];

    用户把“打扫房间”移到第一位,列表变成:

    const items = [  { id: 3, text: "打扫房间" },  { id: 1, text: "买牛奶" },  { id: 2, text: "写作业" } ];

    React 看到 key=3 跑到第一位,key=1 和 key=2 跟着调整位置。它知道这些项只是换了顺序,不会重新渲染内容,而是直接移动现有的 DOM 节点,结果是:

    - 打扫房间 (key=3) - 买牛奶 (key=1) - 写作业 (key=2)

    如果不使用key

    React 会认为:

    • 第一项从“买牛奶”变成了“打扫房间”
    • 第二项从“写作业”变成了“买牛奶”
    • 第三项从“打扫房间”变成了“写作业”

    结果是 React 可能会重新更新所有项的内容,而不是简单地调整顺序,这样效率很低。 避免问题:如果列表项有状态(比如输入框),key 确保状态跟正确的项绑定,不会错乱

Alert.tsx

import React, { ReactNode } from "react";

interface Props {
  children: ReactNode;//表示 Alert 组件可以接受子元素。
  onClose: () => void;//表示 Alert 组件接受一个名为 onClose 的函数
}

const Alert = ({ children, onClose }: Props) => {
  return (
    &lt;div className="alert alert-primary d-flex justify-content-between align-items-center">
      &lt;span>{children}&lt;/span>
      &lt;button
        type="button"
        className="btn-close"
        data-bs-dismiss="alert"
        data-bs-target="#my-alert"
        aria-label="Close"
        onClick={onClose} // 将 onClick 移到按钮上
      >&lt;/button>
    &lt;/div>
  );
};

export default Alert;

这里规定了参数的格式。接口 Props 定义了 Alert 组件所接受的 props 的类型

  • children: ReactNode

    当使用 TypeScript 开发 React 组件时,为了确保代码的类型安全,必须为组件的 props 定义类型。如果不给 children 指定类型,TypeScript 无法推断它是什么,可能会导致类型错误,或者 IDE 无法提供准确的代码提示。因此,显式声明 children 的类型是必要的

    ReactNode 是 React 提供的一个类型别名(type alias),它描述了 React 组件可以接受的所有可能的 children 类型。具体来说,ReactNode 包括:

    • ReactElement:如 <div /> 或 <span />
    • string:纯文本内容
    • number:数字
    • boolean:布尔值(通常不会直接渲染)
    • nullundefined:空值
    • ReactFragment:如 <></>
    • ReactPortal:React 传送门
    • ReactNode[]:多个子元素的数组
  • className="btn-close"

    这里的样式是Bootstrap提供的。

Button.tsx

import React from "react";

interface Props {
  children: string;
  onClick: () => void;
  color: string;
}

const Button = ({ children, onClick, color }: Props) => {
  return (
    &lt;button className={"btn btn-" + color} onClick={onClick}>
      {children}
    &lt;/button>
  );
};

export default Button;
点赞 1
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
浪迹陨灭
浪迹陨灭
0x0c37...a92b
专注于solidity智能合约的开发