• React 入门笔记


    前言

    国庆值班把假期拆了个稀碎, 正好不用去看人潮人海, 趁机会赶个晚集入门一下都火这么久的 React 前端技术. 话说其实 n 年前也了解过一丢丢来着, 当时看到一上来就用 JS 写 DOM 的套路直接就给吓退了, 扭头还去看 Vue 了🤣, 现在从市场份额 社区活度来看, 确实 React 还是占有率更高 (数据来源) 加上单位现在也都在推 CloudScape 做项目, 有必要再试一试了.
    在这里插入图片描述
    本次入门主要围绕 React 前端开发的环境准备和基本功能实现, 后端用 https://reqres.in/api/users?page=2 提供的 Mock 数据, 以后有空再尝尝 FastAPI (挖个坑先). Mock 数据长这样:

    {
        "page": 2,
        "per_page": 6,
        "total": 12,
        "total_pages": 2,
        "data": [
            {
                "id": 7,
                "email": "michael.lawson@reqres.in",
                "first_name": "Michael",
                "last_name": "Lawson",
                "avatar": "https://reqres.in/img/faces/7-image.jpg"
            },
            // 省略更多其他相同结构数据
        ],
        "support": {
            "url": "https://reqres.in/#support-heading",
            "text": "To keep ReqRes free, contributions towards server costs are appreciated!"
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    计划使用这些数据制作一个通信录页面, 包含每个人物的基本信息, 以卡片形式排列展示.

    环境准备

    # 检查 nodejs 版本
    node -v
    v20.8.0
    
    # 修改镜像源
    npm config set registry https://registry.npmmirror.com
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    使用 Vite 脚手架创建项目

    # 创建文件夹
    mkdir my-react; cd my-react
    
    # 创建项目
    npm create vite
    
    # 完成向导, 使用 React + TypeScript 组合
    Need to install the following packages:
    create-vite@4.4.1
    Ok to proceed? (y)
    √ Project name: ... frontend
    √ Select a framework: » React
    √ Select a variant: » TypeScript
    
    Scaffolding project in C:\Users\lpwm\Desktop\react-study\my-react\frontend...
    
    Done. Now run:
    
      cd frontend
      npm install
      npm run dev
    
    # 安装基础的 React 依赖
    cd frontend; npm install
    
    # 使用 VScode 打开项目
    code .
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    VScode 插件配置

    安装以下插件可以使 Coding 的快乐(效率)加倍

    • ES7 React/Redux/Styled-components snippets 常用代码片段
    • Prettier - Code formatter 格式化
    • vscode-icons 扩展图标(好看)

    快捷键 Ctrl + , 打开 VScode 设置, 搜索 “format on save”, 勾选上 Editor: Format On Save; 搜索 “default formatter” , Editor: Default Formatter 选择 Prettier - Code formatter

    配置完的项目 Folder 长这个样子:
    在这里插入图片描述
    通过 Vite 脚手架创建的项目中乍一看好多文件, 其实大多数都不需要动, 主要 focus 在 src 里面就中.

    安装 UI 依赖

    React 其实并不会包含和 UI 相关的 Component / Style, 这部分还是需要使用其他的前端 UI 框架, 这里使用老朋友 Bootstrap 适配 React 的版本 React Bootstrap, 在 VScode 中通过快捷键 Ctrl + Shift + ` 打开 PowerShell 终端:

    npm install react-bootstrap bootstrap
    
    • 1

    安装完成后可以检查 package.json 可以看到内容已经自动更新, 非高端玩家其实项目中的大多数配置文件都不需要手动修改的.

    "dependencies": {
        "bootstrap": "^5.3.2",
        "react": "^18.2.0",
        "react-bootstrap": "^2.9.0",
        "react-dom": "^18.2.0"
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    Coding

    Vite 创建的项目中包含了一个演示的页面, 对于新手来说, 看起来会比较混乱, 先删除 src 中的 App.css, index.css 这两个自定义的样式文件.

    修改 src/main.tsx 删除 import './index.css' 这行相关的引用.

    修改 src/App.tsx 删除所有内容, 输入 tsrafce 按 TAB 键自动补全填充代码片段 (其实不用输入完就能联想出来了) 这里其实是调用前面装的插件 ES7 React/Redux/Styled-components snippets

    Creates a React Arrow Function Component with ES7 module system and TypeScript interface (ES7 React/Redux/Styled-components snippets)

    在这里插入图片描述

    自动补全的 React Component 代码(真省事):

    import React from 'react'
    
    interface Props {
      
    }
    
    const App = (props: Props) => {
      return (
        <div>
          
        </div>
      )
    }
    
    export default App
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    其实 JSX 也没有像之前想象的那么晦涩, 当成 XML 来对待就行了. 修改上面的代码, 删除没有用到的部分, 添加一个静态的 Bootstrap Navbar 和 Card. 在 return () 中输入 就会出现自动联想, 按 TAB 键就可以自动补全相关的 import 代码, 就很欢快了有木有! 另外得益于之前在 VScode 中设置的 Editor: Format On Save, 保存文件时会自动通过 Prettier 进行格式化.
    在这里插入图片描述
    参考 React Bootstrap 文档 完成页面设计.

    import { Card, Col, Container, Navbar, Row } from "react-bootstrap";
    // 别忘了添加 Bootstrap CSS 文件引用
    import "bootstrap/dist/css/bootstrap.min.css";
    
    const App = () => {
      return (
        <Container fluid>
          <Row>
            <Navbar expand="lg" className="bg-primary-subtle">
              <Container>
                <Navbar.Brand>Contacts</Navbar.Brand>
              </Container>
            </Navbar>
          </Row>
          <Container className="p-3">
            {/* Container 加上 padding 类 */}
            <Row md="4">
              {/* 在 Row 上定义 Grid Column (每行最多 4 列) */}
              <Col>
                <Card className="m-2">
                  {/* 加上 margin 类 */}
                  <Card.Img variant="top" src="holder.js/100px180"></Card.Img>
                  <Card.Body>
                    <Card.Title>Card Title</Card.Title>
                    <Card.Text>Some text in the card.</Card.Text>
                  </Card.Body>
                </Card>
              </Col>
            </Row>
          </Container>
        </Container>
      );
    };
    
    export default App;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    在 Terminal 中启动开发服务器

    npm run dev
    
      VITE v4.4.9  ready in 200 ms
    
      ➜  Local:   http://localhost:5174/
      ➜  Network: use --host to expose
      ➜  press h to show help
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    浏览器访问 http://localhost:5174/ 预览效果
    在这里插入图片描述
    多复制几个 Card 所在的 查看 Grid Column 效果:
    在这里插入图片描述
    静态页面已经没问题了, 接下来使用 https://reqres.in/api/users?page=2 模拟后端 API 返回的数据进行页面动态渲染, 修改后的 App.tsx

    import { Card, Col, Container, Navbar, Row } from "react-bootstrap";
    // 别忘了添加 Bootstrap CSS 文件引用
    import "bootstrap/dist/css/bootstrap.min.css";
    import { useEffect, useState } from "react";
    import React from "react";
    
    // 使用 Context 管理组件内部的上下文内容
    const AppContext = React.createContext({
      users: [],
      fetchUsers: () => {},
    });
    
    const App = () => {
      // 模拟异步获取 API 数据
      const [users, setUsers] = useState([]);
      const fetchUsers = async () => {
        await fetch("https://reqres.in/api/users?page=2")
          .then((response) => {
            return response.json();
          })
          .then((json_data) => {
            setUsers(json_data["data"]);
          });
      };
      useEffect(() => {
        fetchUsers();
      }, []);
    
      return (
        <AppContext.Provider value={{ users, fetchUsers }}>
          <Container fluid>
            <Row>
              <Navbar expand="lg" className="bg-primary-subtle">
                <Container>
                  <Navbar.Brand>Contacts</Navbar.Brand>
                </Container>
              </Navbar>
            </Row>
            <Container className="p-3">
              {/* Container 加上 padding 类 */}
              <Row md="4">
                {/* 在 Row 上定义 Grid Column (每行最多 4 列) */}
                {users.map((user) => (
                  <Col key={user["id"]}>
                    <Card className="m-2">
                      {/* 加上 margin 类 */}
                      <Card.Img variant="top" src={user["avatar"]}></Card.Img>
                      <Card.Body>
                        <Card.Title>{user["first_name"]}</Card.Title>
                        <Card.Text>Some text in the card.</Card.Text>
                      </Card.Body>
                    </Card>
                  </Col>
                ))}
              </Row>
            </Container>
          </Container>
        </AppContext.Provider>
      );
    };
    
    export default App;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63

    刷新浏览器查看效果:
    在这里插入图片描述
    由于图片的高度不一致, 导致显示的 Card 大小也不一样, 先通过自定义 inline 样式的方式解决, 修改 Card.Img 添加 style 属性

    <Card.Img
      variant="top"
      src={user["avatar"]}
      style={{ height: "100px", objectFit: "cover" }}
    ></Card.Img>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    刷新页面, 制式~
    在这里插入图片描述
    换种方式, 将自定义样式放到单独的文件中, 然后为 Card.Img 添加 className 属性. 创建文件 src/App.css (就是开头删掉的那个🤣)

    .card-avatar {
      height: 100px;
      object-fit: cover;
    }
    
    • 1
    • 2
    • 3
    • 4

    修改 App.tsx, 在开头加入引用 import "./App.css";, 并调整 Card.Img

    <Card.Img
      variant="top"
      src={user["avatar"]}
      className="card-avatar"
    ></Card.Img>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    再次刷新浏览器, 格式保持一致. 至此, 一个简单的 React 页面就开发完成了. 其实后面涉及到的 React.createContext, useState, useEffect 还属于一知半解, 也没好意思展开强行解释. 能先跑出来效果就打消了不少之前对 React 的恐惧了, 后面还是得花时间好好看一遍文档和基础学习.

    项目部署

    现在都是在本地通过 npm run dev 跑的开发测试环境, 生产部署的简单过程:

    1. Build, 会在项目文件夹中创建 dist 目录
    npm run build
    
    • 1
    1. dist 目录中的文件部署到 Web Server, 以 WSL2 (Ubuntu 22.04) 中的 nginx 为例
    # 先安装 nginx
    sudo apt install nginx -y
    
    # 从 Windows 的资源管理器中
    # 将 dist 文件夹复制到 WSL2 的 Home 文件夹: /home/lpwm/dist
    # 修改 nginx 配置
    sudo vim /etc/nginx/sites-enabled/default
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    nginx 配置文件简单示意:

    server {
    	listen 80;
    	root /home/lpwm/dist;
    }
    
    • 1
    • 2
    • 3
    • 4

    启动 nginx 服务

    sudo systemctl restart nginx
    
    • 1

    此时通过浏览器访问 http://localhost 返回 403 Forbidden, 查看 /var/log/nginx/error.log 发现:

    2023/10/01 01:09:59 [error] 1117#1117: *1 “/home/lpwm/dist/index.html” is forbidden (13: Permission denied), client: 127.0.0.1, server: , request: “GET / HTTP/1.1”, host: “localhost”

    使用 sudo ps -ef |grep nginx 检查当前运行 nginx 的用户是 www-data, 没有对 /home/lpwm/dist 文件夹的访问权限. 这个好说, 把 www-data 用户添加到我自己用户的 lpwm 组就行了呗

    sudo usermod -aG lpwm www-data
    sudo nginx -s reload
    
    • 1
    • 2

    齐活儿~

    在这里插入图片描述
    本次入门就先到这里吧, 后面抽时间再细琢磨 React 里面的各种基础概念.

    参考资料

    React Tutorial for Beginners - Programming with Mosh

  • 相关阅读:
    yolov8训练初体验
    【kafka】可视化工具KAFKA EAGLE安装分享
    SaaSBase:AlphaFlow RPA是什么?
    Spring Securit OAuth 2.0整合—核心的接口和类
    Seata概述基础
    基于单片机的超声波探伤仪设计
    实现Promise所有核心功能和方法
    解决 uni-app app使用 onBackPress 监听返回后关闭popup 以及使用 uni-simple-router 有冲突问题
    Redis分布式锁实现
    Linux文件管理知识:文本处理
  • 原文地址:https://blog.csdn.net/lpwmm/article/details/133441067