6606 字
33 分钟
页面浏览--访问次数--
React 基础
gehongyanReactTutorials

本文档是 React 的基础教程,主要包含安装 React 应用程序的开发环境、创建应用程序、根据业务编写代码、测试与部署等内容。

开发环境#

安装 Node.js#

要开发 React 应用程序,首先需要安装 Node.js。Node.js 是一个 JavaScript 运行环境。可以在 Node.js 官网 下载到 Node.js 的开发环境。

开发工具#

主流的 React 开发工具有 Visual Studio Code、JetBrains WebStorm 等。

Visual Studio Code 是一款开源的轻量级的代码编辑器,支持多种语言与扩展,是一款非常适合前端开发的工具。

Visual Studio Code 插件#

以 Visual Studio Code 为例,为了后续开发的遍历,可以安装一些主流的插件,如:

创建 React 应用程序#

Vite 是一个由原生 ESM 驱动的 Web 开发构建工具,它的目标是快速提供合适的开发环境。 此处以使用 Vite 创建 React 应用程序为例,首先通过 npm 包管理器安装 Vite 全局工具。

Terminal window
npm install --global create-vite

然后通过 Vite 创建 React 应用程序。

Terminal window
npm create vite@latest

如果命令中不包含额外的参数,Vite 会进行交互式的操作,根据提示选择创建 React 应用程序。 输入应用程序名称后选择框架和语言,即可在当前工作目录下创建 React 应用程序。 本项目以应用程序名称为 app,框架为 React,语言为 TypeScript 为例。 TypeScript 是 JavaScript 的超集,提供了类型检查的功能,可以提高代码的可维护性。

模板项目结构#

创建 React 应用程序后,会生成如下的项目结构:

app
  • public静态资源
    • vite.svgVite 图标
  • src应用程序源码
    • assets资源
      • react.svgReact 图标
    • App.css组件 App 的样式
    • App.tsx组件 App 的代码
    • index.css入口文件的样式
    • index.tsx入口文件的模块
    • vite-env.d.tsVite 环境变量
  • .eslintrc.cjsESLint 配置
  • .gitignoreGit 忽略文件
  • index.html入口文件
  • package.json包管理文件
  • README.md项目说明
  • tsconfig.jsonTypeScript 配置
  • tsconfig.node.jsonNode.js TypeScript 配置
  • vite.config.tsVite 配置

包管理器#

npm 是 Node.js 的包管理器,用于管理 Node.js 的依赖包。 dependencies 节点下记录的是应用程序的依赖包,devDependencies 节点下记录的是开发环境的依赖包。

版本号前的 ^ 符号表示允许更新到次要版本,~ 符号表示允许更新到补丁版本。 例如,^1.2.3 表示允许更新到 1.x.x 的任意版本,~1.2.3 表示允许更新到 1.2.x 的任意版本, 而 1.2.3 则表示只能使用 1.2.3 版本。

运行示例程序#

运行 React 应用程序,首先需要安装依赖。

Terminal window
cd app
npm install

npm install 命令会安装 package.json 中的依赖,此过程会创建 node_modules 目录,存放依赖的包。 还会创建 package-lock.json 文件,存放依赖的版本信息。package-lock.json 文件记录的是当前实际安装的依赖版本。

安装依赖后,可以运行 React 应用程序。

Terminal window
npm run dev

npm run 命令会执行 package.json 中 scripts 字段中的命令,dev 是其中一个命令,用于启动开发服务器。 此处的 dev 脚本的值是 vite,即启动 Vite 开发服务器,因此该命令实际和 vite 命令等价。

观察控制台输出,可以看到 React 应用程序的启动信息,如 Local: http://localhost:5173/ 便可以在浏览器中打开该地址访问应用程序。

package.json 中的 scripts 字段中还有其他脚本,如 build、lint、preview 等。

  • build 脚本调用了 tsc && vite build,即先对 TypeScript 源码进行编译,然后构建应用程序。
  • lint 脚本调用了 eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0,即对 当前名录下的 .ts 和 .tsx 文件进行 ESLint 检查。--report-unused-disable-directives 用于检查未使用的 ESLint 禁用指令,--max-warnings 0 用于设置最大警告数为 0,即任何警告都会导致脚本失败。
  • preview 脚本调用了 vite preview,即启动 Vite 预览服务器,预览构建后的应用程序。该命令主要用于 预览构建后的应用程序,可以用于测试构建后的应用程序,不应直接用于生产环境。生产环境下应使用一个更完整的服务器应用来托管应用程序。

编写 React 代码#

React 是一个用于构建用户界面的 JavaScript 库。

入口文件#

index.html 是 React 应用程序的入口文件,其中包含一个 div 元素,用于挂载 React 应用程序,以及一个 script 元素,用于加载 React 应用程序的入口模块。

<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>

main.tsx 是 React 应用程序的入口模块,用于在 React 应用程序中渲染一个 App 组件。

ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<App/>
</React.StrictMode>,
)
  • ReactDOM.createRoot(document.getElementById('root')!):这是 React 18 中引入的新的渲染 API。createRoot 方法创建一个根 React 节点,并将其挂载到指定的 DOM 元素上,将 React 应用程序挂载到 id 为 root 的 DOM 元素上。

  • .render(<React.StrictMode><App /></React.StrictMode>):这个方法用于在前面创建的根节点上渲染 React 组件。

  • <React.StrictMode>:React 严格模式,这是一个用于检查 React 应用程序中潜在问题的工具。它不会影响生产构建, 但在开发模式下,它会激活额外的检查和警告。它包裹了 App 组件,所以这些检查和警告将应用于 App 组件及其所有子组件。

  • <App />:这是要渲染的 React 组件。在这个例子中,App 是应用程序的根组件。

组件#

React 应用程序是由组件组成的,组件是 React 应用程序的基本单元。 组件是一个函数或一个类,用于描述用户界面的一部分。组件可以嵌套,形成一个组件树。目前主流的 React 开发方式是函数组件。

函数组件是一个函数,接收一个 props 参数,返回一个 React 元素。React 元素是一个描述用户界面的对象,可以是一个 DOM 元素、一个组件等。

import { useState } from 'react'
import reactLogo from './assets/react.svg'
import viteLogo from '/vite.svg'
import './App.css'
function App() {
const [count, setCount] = useState(0)
return (
<>
<div>
<a href="https://vitejs.dev" target="_blank">
<img src={viteLogo} className="logo" alt="Vite logo"/>
</a>
<a href="https://react.dev" target="_blank">
<img src={reactLogo} className="logo react" alt="React logo"/>
</a>
</div>
<h1>Vite + React</h1>
<div className="card">
<button onClick={() => setCount((count) => count + 1)}>
count is {count}
</button>
<p>
Edit <code>src/App.tsx</code> and save to test HMR
</p>
</div>
<p className="read-the-docs">
Click on the Vite and React logos to learn more
</p>
</>
)
}
export default App

function 用于声明一个函数,App 是函数的名称,函数体是函数的实现。return 返回了一个 React 元素。

useState 是一个 React Hook,用于在函数组件中添加状态。因为函数组件是无状态的,所以需要使用 Hook 来添加状态。 useState(0) 返回一个数组,第一个元素 count 是状态的值,第二个元素 setCount 是更新状态的函数。 这里的状态是一个数字,初始值为 0。useState(0) 的参数是状态的初始值,这里的初始值是 0。

<img src={viteLogo} className="logo" alt="Vite logo" /> 是一个图片元素,src 属性是图片的地址,className 属性是图片的类名,alt 属性是图片的描述。这里的 src 属性使用了一个变量 viteLogo,这个变量是一个图片的地址,通过 import 引入。变量需要使用大括号 {} 包裹。

<button onClick={() => setCount((count) => count + 1)}>count is {count}</button> 是一个按钮元素,onClick 属性是点击事件的处理函数,调用了 setCount 函数,更新了 useState 定义的状态。 按钮的文本 count is {count} 使用了一个变量 count,这个变量是一个状态的值,通过大括号 {} 包裹。 状态的更新会自动触发对应的组件的重新渲染。

<></> 是一个 React 片段,用于包裹多个元素。React 要求一个组件只能返回一个根元素,所以需要使用片段来包裹多个元素。

export default App 用于导出组件,这样其他模块就可以引入该组件。

样式#

App.css 是 App 组件的样式文件,用于描述 App 组件的样式。

默认生成的 App.css 包含了以下几个部分。

#root {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
text-align: center;
}

#root 是一个 ID 选择器,用于选择 id 为 root 的元素。max-width 属性设置元素的最大宽度为 1280 像素, margin 属性设置元素的外边距为 0,padding 属性设置元素的内边距为 2rem,这里的 rem 单位是相对于根元素的字体大小, text-align 属性设置元素的文本对齐方式为居中。

.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: filter 300ms;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.react:hover {
filter: drop-shadow(0 0 2em #61dafbaa);
}

.logo 是一个类选择器,用于选择类名为 logo 的元素。height 属性设置元素的高度为 6em, padding 属性设置元素的内边距为 1.5em,will-change 属性设置元素之后会发生变化的属性为 filter, transition 属性设置元素的过渡效果为 filter 300ms,即 filter 属性的变化时间为 300 毫秒。

.logo:hover 是一个伪类选择器,用于选择鼠标悬停在类名为 logo 的元素上的元素。 filter 属性设置元素的滤镜效果为 drop-shadow(0 0 2em #646cffaa),

@keyframes logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
@media (prefers-reduced-motion: no-preference) {
a:nth-of-type(2) .logo {
animation: logo-spin infinite 20s linear;
}
}

@keyframes logo-spin 是一个关键帧动画,用于定义一个旋转动画。from 关键字表示动画的开始状态, to 关键字表示动画的结束状态。transform 属性设置元素的变换效果为 rotate(0deg),即元素的旋转角度为 0 度到 360 度。

@media (prefers-reduced-motion: no-preference) 是一个媒体查询,用于根据用户的偏好设置应用样式。 prefers-reduced-motion 是一个用户偏好设置,表示用户所设置的是否偏好减弱动画。 根据文档 prefers-reduced-motion - CSS:层叠样式表 | MDN,no-preference 表示用户未修改系统动画相关特性, reduce 意味着用户修改了系统设置,将动画效果最小化,最好所有的不必要的移动都能被移除。 在 Windows 11 中,影响该值的设置位于「设置 - 辅助功能 - 视觉效果 - 动画效果」。

模块样式#

但传统的 CSS 有一个问题,就是全局作用域。一个 CSS 文件中的样式会对整个页面生效,这样会导致样式冲突, 不利于组件化开发,类名称的弱关联也不利于样式的维护。

CSS Modules 是一种解决方案,它是一种 CSS 的模块化方案,可以解决全局作用域的问题。CSS Modules 会将 CSS 文件中的类名转换为一个哈希值,这样就可以保证类名的唯一性,避免样式冲突。

要将 App.css 转换为 CSS Module,首先需要将文件重命名为 App.module.css,然后在 App.tsx 中更改样式文件的引入, 最后根据需要修改样式文件中的类名,例如,将 read-the-docs 类名修改为 readTheDocs。

import './App.css'
import styles from './App.module.css'

这样就可以使用 styles 对象来引用 CSS Module 中的类名。

<>
<div>
<a href="https://vitejs.dev" target="_blank" rel="noopener">
<img src={viteLogo} className={styles.logo} alt="Vite logo" />
<img src={viteLogo} className={styles.logo} alt="Vite logo" />
</a>
<a href="https://react.dev" target="_blank" rel="noopener">
<img src={reactLogo} className="logo react" alt="React logo" />
<img src={reactLogo} className={`${styles.logo} ${styles.react}`} alt="React logo" />
</a>
</div>
<h1>Vite + React</h1>
<div className="card">
<div className={styles.card}>
<button onClick={() => setCount((count) => count + 1)}>
count is {count}
</button>
<p>
Edit <code>src/App.tsx</code> and save to test HMR
</p>
</div>
<p className="read-the-docs">
<p className={styles.readTheDocs}>
Click on the Vite and React logos to learn more
</p>
</>

更改文件后,可以发现 Vite 为我们自动更新了预览视图,这是因为 Vite 支持热模块替换(HMR)。 但修改后的组件并没有像原来一样保持居中,这是因为 CSS Module 会将类名转换为哈希值,不支持现有的 #root ID 选择器。 如果需要使用 ID 选择器,可以使用 :global 关键字,保留样式的原始全局性。

#root {
:global(#root) {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
text-align: center;
}

路由#

安装路由组件#

React 是一个单页面应用程序(SPA)框架,单页面应用程序是指一个页面加载后,不会因为用户的操作而进行页面的重新加载。 当需要切换页面时,只会更新页面的部分内容,而不会重新加载整个页面,这便需要路由来管理页面的切换。

React Router 是一个用于管理 React 应用程序路由的库,它提供了一些组件,用于在 React 应用程序中实现路由功能。

首先需要安装 React Router,这是我们第一次添加依赖。

Terminal window
npm install react-router-dom

这会在 package.json 中的 dependencies 节点下添加 react-router-dom 依赖。

"react-router-dom": "^6.23.0"

现在,我们可以根据文档的指南为我们的应用程序添加路由能力。

整理代码结构#

为了让页面结构更清晰,我们先整理以下目录结构。

在 src 目录下创建 features 文件夹,用于存放各个页面组件。

将组件 App 重命名为 Home,并移动到 features/home 目录下,此操作建议使用 IDE 的重构/重命名功能, 这样,相关的引用也会被自动更新。操作完成后,访问浏览器检查所有的引用是否正常。

重新创建 App 组件,用于包裹整个应用程序,这样可以在 App 组件中添加路由。

import { createBrowserRouter, RouterProvider } from "react-router-dom";
import Home from "./features/home/Home.tsx";
const router = createBrowserRouter(
[
{
path: `/`,
element: <Home/>
}
]
);
export default function App() {
return (
<RouterProvider router={router}
fallbackElement={<p>Loading...</p>}
/>
);
}
if (import.meta.hot) {
import.meta.hot.dispose(() => router.dispose());
}

新的 App 模块道出了一个 RouterProvider 组件,用于提供路由功能。RouterProvider 组件接收一个 router 属性, 这个属性是一个路由对象,用于管理路由。router 对象是通过 createBrowserRouter 函数创建的,这个函数接收一个路由配置数组, 返回一个路由对象。路由配置数组中的每个元素都是一个路由配置对象,包含了路由的路径和对应的元素。

createBrowserRouter 函数返回的路由对象有一个 dispose 方法,用于清理路由对象。在开发模式下,当模块被热替换时, 会调用 dispose 方法,清理路由对象。

现在,应用程序的路由已经配置好了,但是还需要在入口文件中引入 App 组件。由于重构操作,main.tsx 中的原来的 <App /> 也被重命名为 <Home />,所以需要将其改为 <App />。重新导入模块 App 并使用它。

import Home from './features/home/Home.tsx'
import App from './App.tsx'
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<Home />
<App />
</React.StrictMode>,
)

现在,重新访问 http://localhost:5173/ ,可以看到页面上仍然正常显示着 Home 组件的内容,但此时已经是通过路由管理的。

创建新页面#

现在,我们来创建一个新的页面,用于展示一个关于页面。

在 features/about 目录下创建组件 About.tsx。

function About() {
return (
<>
<h1>About</h1>
<p>This is a simple app to demonstrate how to create a simple app using Vite and React.</p>
</>
);
}
export default About;

然后,我们需要在 App 组件中添加一个新的路由配置,用于展示 About 页面。

import About from "./features/about/About.tsx";
const router = createBrowserRouter(
[
{
path: `/`,
element: <Home/>
},
{
path: `/about`,
element: <About/>
}
]
);

钩子#

React Hook 是 React 16.8 中引入的新特性,用于在函数组件中添加状态和副作用。 此处对一些常用的钩子进行简单介绍。

useState#

用于在函数组件中添加状态,可以视为一个组件内部的变量。 状态是一个组件可以改变的值,它可以影响组件的行为和渲染输出。 useState 接受一个参数,这个参数是状态的初始值,然后返回一个包含两个元素的数组。 第一个元素是当前的状态值,第二个元素是一个函数,用于更新状态值。 调用这个更新函数并传入一个新的值时,React 会重新渲染组件,并使用新的值作为状态。

以 Home.tsx 为例。

我们使用 useState 创建了一个新的状态变量 count,并给它设置了初始值 0。 我们还得到了一个函数 setCount,用于更新 count 的值。 当用户点击按钮时,我们调用 setCount 来增加 count 的值,这会触发组件的重新渲染。

useEffect#

用于在函数组件中执行副作用操作。副作用操作包括数据获取、订阅或手动修改 DOM 等等。 这些操作通常在组件渲染后执行,以不影响组件的渲染性能。

useEffect 接受两个参数:一个是执行副作用的函数,另一个是依赖数组。 当依赖数组中的值发生变化时,副作用函数就会被执行。如果不提供依赖数组,那么副作用函数会在每次渲染后都执行。

以 Effect.tsx 为例。

在这个例子中,我们使用 useEffect 来更新 document 的 title。 当 count 变化时,副作用函数就会被重新执行,更新 document 的 title。 当组件卸载或者下一次 useEffect 执行前,清理函数会被调用,将 document 的 title 重置为 React App。

需要注意的是,在开发模式下,我们启用了 React 严格模式,这会导致 useEffect 中的副作用函数被调用两次。 严格模式下,React 会在渲染过程中执行两次副作用函数,以确保副作用函数的纯净性,即相同的输入应始终产生相同的输出, 这有助于帮我们发现一些潜在的问题。

useContext#

用于在函数组件中访问 React 上下文。React 上下文是一个全局的数据存储区,用于在组件树中传递数据, 而无需通过 props 显式传递。

以 Context.tsx 为例。

useContext 接受一个 context 对象(React.createContext 的返回值)作为参数,并返回该 context 的当前值。 当前的 context 值是由上层组件中距离当前组件最近的 <MyContext.Provider> 的 value 决定的。

useReducer#

用于在函数组件中管理复杂的状态逻辑。useReducer 类似于 Redux 中的 reducer,它接受一个 reducer 函数和一个初始状态, 并返回一个当前状态和一个 dispatch 函数。

useReducer 可以理解为是一种状态机,reducer 函数接收当前的状态和一个 action,返回一个新的状态。

以 Reducer.tsx 为例。

我们首先定义了一个 reducer 函数,它接受当前的 state 和一个 action,根据 action 的类型返回新的 state 。然后我们使用 useReducer,传入 reducer 函数和初始状态,得到当前的 state 和一个 dispatch 函数。在按钮的点击事件中,我们调用 dispatch 函数,传入一个 action 对象,触发 state 的更新。

useMemo#

用于在函数组件中缓存计算结果,通过记忆计算结果来避免在每次渲染时都进行重计算,优化性能。 useMemo 接受两个参数:一个是创建记忆值的函数,另一个是依赖数组。当依赖数组中的值发生变化时, useMemo 就会返回一个新的记忆值。如果依赖数组中的值没有变化,那么 useMemo 就会返回上一次的记忆值。

以 Memo.tsx 为例。

我们有一个复杂的计算函数 expensive 和 expensiveWithoutMemo,它们都会根据 count 的值进行计算。expensive 使用了 useMemo,而 expensiveWithoutMemo 没有。当我们改变输入框的值时,组件会重新渲染,但 count 的值并没有改变。对于 expensive 函数,由于 count 没有改变,useMemo 会返回上一次计算的结果,不会重新计算。但对于 expensiveWithoutMemo 函数,每次组件渲染时都会重新计算。因此,通过使用 useMemo,我们可以避免在每次渲染时都进行复杂的计算,从而优化性能。

useCallback#

用于在函数组件中缓存回调函数,通过记忆回调函数来避免在每次渲染时都创建新的回调函数,优化性能。 useCallback 接受两个参数:一个是创建函数的函数,另一个是依赖数组。当依赖数组中的值发生变化时,useCallback 就会返回一个新的函数实例。如果依赖数组中的值没有变化,那么 useCallback 就会返回上一次的函数实例。

以 Callback.tsx 为例。

我们使用 useCallback 创建了一个记忆的 increment 函数。只有当 count 变化时,useCallback 才会返回一个新的 increment 函数。如果 count 没有变化,那么 useCallback 就会返回上一次的 increment 函数。这样,即使组件重新渲染,increment 函数的引用也不会变化,除非 count 变化。

这就是 useCallback 的主要用途:它可以帮助我们避免在每次渲染时都创建新的函数,从而优化性能。但是,需要注意的是,useCallback 本身也有一定的开销,因此,只有在必要的时候(例如,当函数作为依赖项传递给其他 Hooks,或者当函数传递给性能敏感的子组件时)才应该使用它。

useRef#

用于在函数组件中创建一个可变的引用。useRef 返回一个可变的对象,这个对象的 current 属性可以存储任意值。 这个对象在组件的整个生命周期中保持不变,不会因为组件的重新渲染而改变。

以 Ref.tsx 为例。

我们使用 useRef 创建了一个 ref,并将其赋值给了一个输入框。然后,当按钮被点击时,我们使用 ref 来让输入框获取焦点。

需要注意的是,useRef 返回的 ref 对象有一个 current 属性,用于存储 ref 的值。在这个例子中,current 属性的值就是输入框的 DOM 节点。

Redux#

Redux 是一个用于管理 JavaScript 应用程序状态的开源库。它提供了一种在应用程序中以一种可预测的方式来管理和更新状态的方法。Redux 特别适用于那些由于其状态在很多组件之间共享而变得复杂的 JavaScript 应用程序。

Redux 的核心概念包括:

  • Store:在 Redux 中,整个应用程序的状态被存储在一个对象树中,这个对象树被称为 Store。

  • Action:Action 是描述发生了什么的普通对象。它是改变状态的唯一途径。每个 Action 都有一个 type 字段,用来描述 Action 的类型。

  • Reducer:Reducer 是一个纯函数,它接收当前的状态和一个 Action,然后返回一个新的状态。在 Redux 中,所有的状态更新逻辑都在 Reducer 中完成。

Redux 的工作流程如下:

  1. 发起 Action:应用程序中的某个事件触发了一个 Action。

  2. Reducer 计算新的状态:Store 调用 Reducer 函数,并传入当前的状态和触发的 Action。Reducer 函数根据 Action 的类型计算出新的状态。

  3. Store 更新状态:Store 将新的状态保存下来。然后,Store 会通知所有的监听器,状态已经更新。

Redux 的主要优点是它提供了一种可预测的状态管理方法,使得状态的更新在任何时候都是可追踪的。此外,由于 Redux 的状态存储在一个单一的 Store 中,这使得在调试和测试应用程序时更加方便。

安装 Redux Toolkit 和 React Redux#

Redux Toolkit 是一个官方的 Redux 工具包,它提供了一些工具和库,用于简化 Redux 的使用。 React Redux 是一个用于在 React 应用程序中使用 Redux 的库。

Terminal window
npm install @reduxjs/toolkit react-redux
  • 定义根 State 和 Dispatch 类型

创建 src/app/store.ts 文件

import { Action, ThunkAction, configureStore } from '@reduxjs/toolkit'
import counterReducer from '../features/counter/counterSlice'
export const store = configureStore({
reducer: {
counter: counterReducer
}
})
// 从 store 本身推断出 `RootState` 和 `AppDispatch` 类型
export type RootState = ReturnType<typeof store.getState>
// 推断出类型: { counter: CounterState }
export type AppDispatch = typeof store.dispatch
export type AppThunk<ReturnType = void> = ThunkAction<
ReturnType,
RootState,
unknown,
Action<string>
>

定义 Hooks 类型#

创建 src/app/hooks.ts 文件

import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'
import type { RootState, AppDispatch } from './store'
// 在整个应用程序中使用,而不是简单的 `useDispatch` 和 `useSelector`
export const useAppDispatch: () => AppDispatch = useDispatch
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector

定义 Slice State 和 Action#

每个 Slice 都包含了一个 Reducer 函数,用于处理 Action,并且可以包含一些额外的 Reducer 函数,用于处理其他的 Action。

编写模块代码#

可以参考组件 Counter。

API 调用#

axios 是一个基于 Promise 的 HTTP 客户端,用于在浏览器和 Node.js 中发送 HTTP 请求。

Terminal window
npm install axios

可以参考 Timestamp 模块。

在 timestampAPI.ts 文件中,定义了一个异步函数 getTimestamp,用于获取当前时间戳。

import axios from "axios";
export interface WorldTimeApiDto {
abbreviation: string;
client_ip: string;
datetime: string;
day_of_week: number;
day_of_year: number;
dst: boolean;
dst_from: string | null;
dst_offset: number;
dst_until: string | null;
raw_offset: number;
timezone: string;
unixtime: number;
utc_datetime: string;
utc_offset: string;
week_number: number;
}
export async function getTimestamp() {
const response = await axios.get("http://worldtimeapi.org/api/timezone/Asia/Shanghai");
const dto = response.data as WorldTimeApiDto;
return Date.parse(dto.datetime);
}

如果需要配置请求头,可以在 axios 实例中配置。

await axios.get("http://worldtimeapi.org/api/timezone/Asia/Shanghai", {
headers: {
"Content-Type": "application/json"
}
});

组件库#

Ant Design 是一个用于构建 React 应用程序的 UI 组件库。

Terminal window
npm install antd

安装完成后,即可在需要引用 Ant Design 的组件时进行引用,并参考文档进行调用。

可以参考组件 AntDesign。

图表库#

Ant Design Charts 是一个基于 Ant Design 设计体系的图表库,是 AntV 的 React 版本。

Terminal window
npm install @ant-design/charts

安装完成后,即可在需要引用 Ant Design Charts 的组件时进行引用,并参考文档进行调用。

可以参考组件 Chart。

部署#

发布应用程序时,需要将应用程序构建为生产版本,并将构建后的文件部署到服务器上。

构建#

构建应用程序时,需要使用 build 脚本。

Terminal window
npm run build

构建完成后,默认情况下,Vite 会在 dist 目录下生成一个生产版本的应用程序,该位置可以在 vite.config.ts 中配置。

此时,便可以通过 preview 脚本来预览构建后的应用程序。

部署#

部署应用程序时,需要将构建后的文件部署到服务器上。

此处以编写 DockerFile 将应用程序部署到 Docker 容器内的 Nginx 服务器为例。

FROM node:22-alpine as build
WORKDIR /app
COPY /app/package*.json ./
RUN npm install
COPY /app/ ./
RUN npm run build
FROM nginx:stable-alpine
COPY --from=build /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

在 DockerFile 文件中,首先使用 Node 镜像作为构建环境,安装依赖并构建应用程序, 然后使用 Nginx 镜像作为运行环境,将构建后的文件复制到 Nginx 的静态文件目录中,并暴露 80 端口。

React 基础
https://gehongyan.cn/posts/frontend/react-basics/
作者
戈小荷
发布于
2024-05-09
许可协议
CC BY-NC-SA 4.0

分享文章

生成精美分享图或复制链接,与更多人分享本文。

继续阅读

换条路线

从其他文章中稳定抽取

评论

正在加载评论...

最后更新于 ,距今已过 897 天

部分内容可能已过时