<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>React on 编程那些事儿</title><link>https://before80.github.io/prgms/Js/frameworks/react/</link><description>Recent content in React on 编程那些事儿</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Fri, 27 Mar 2026 21:25:30 +0800</lastBuildDate><atom:link href="https://before80.github.io/prgms/Js/frameworks/react/index.xml" rel="self" type="application/rss+xml"/><item><title>第1章 前端基础与React概述</title><link>https://before80.github.io/prgms/Js/frameworks/react/Chapter-01-Frontend-Basics-and-React-Overview/</link><pubDate>Wed, 25 Mar 2026 12:56:00 +0800</pubDate><guid>https://before80.github.io/prgms/Js/frameworks/react/Chapter-01-Frontend-Basics-and-React-Overview/</guid><description>&lt;h1 id="chapter-01---前端基础与-react-概述"&gt;Chapter-01 - 前端基础与 React 概述&lt;/h1&gt;
&lt;h2 id="11-网页是如何工作的"&gt;1.1 网页是如何工作的&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;你有没有想过，当你往浏览器地址栏里敲下 &lt;code&gt;www.baidu.com&lt;/code&gt;，按下回车的那一瞬间，到底发生了什么？是什么力量让那些文字、图片、视频神奇地出现在你的屏幕上？是什么让一个&amp;quot;白纸一张&amp;quot;的浏览器变成了一个五彩斑斓的网页？这一切的幕后英雄，就是我们今天要揭开的秘密。&lt;/p&gt;</description></item><item><title>第2章 Node.js与包管理器</title><link>https://before80.github.io/prgms/Js/frameworks/react/Chapter-02-Node.js-and-Package-Managers/</link><pubDate>Wed, 25 Mar 2026 12:56:00 +0800</pubDate><guid>https://before80.github.io/prgms/Js/frameworks/react/Chapter-02-Node.js-and-Package-Managers/</guid><description>&lt;h1 id="chapter-02---nodejs-与包管理器"&gt;Chapter-02 - Node.js 与包管理器&lt;/h1&gt;
&lt;h2 id="21-nodejs-简介"&gt;2.1 Node.js 简介&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;你有没有想过这样一个问题：JavaScript 这门语言，不是只能在浏览器里运行吗？它是怎么跑到服务器上去的？Node.js 就是这个&amp;quot;魔法&amp;quot;的化身——它把 Chrome 浏览器的 V8 引擎单独拎出来，放到一个没有浏览器的环境里运行，于是 JavaScript 第一次能够在服务器端大展拳脚。&lt;/p&gt;</description></item><item><title>第3章 开发工具配置</title><link>https://before80.github.io/prgms/Js/frameworks/react/Chapter-03-Development-Tools-Setup/</link><pubDate>Wed, 25 Mar 2026 12:56:00 +0800</pubDate><guid>https://before80.github.io/prgms/Js/frameworks/react/Chapter-03-Development-Tools-Setup/</guid><description>&lt;h1 id="chapter-03---开发工具配置"&gt;Chapter-03 - 开发工具配置&lt;/h1&gt;
&lt;h2 id="31-vs-code-下载与安装"&gt;3.1 VS Code 下载与安装&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;工欲善其事，必先利其器。作为 React 开发者，我们的&amp;quot;器&amp;quot;就是代码编辑器。目前市面上最流行的前端代码编辑器，当属 &lt;strong&gt;Visual Studio Code&lt;/strong&gt;（简称 VS Code）——它免费、开源、轻量、功能强大，而且是微软出品，质量有保证（这次真的是微软出品，不像某些别的产品……）。&lt;/p&gt;</description></item><item><title>第4章 第一个React项目——Vite与React 19</title><link>https://before80.github.io/prgms/Js/frameworks/react/Chapter-04-First-React-Project-Vite-React-19/</link><pubDate>Wed, 25 Mar 2026 12:56:00 +0800</pubDate><guid>https://before80.github.io/prgms/Js/frameworks/react/Chapter-04-First-React-Project-Vite-React-19/</guid><description>&lt;h1 id="chapter-04---第一个-react-项目vite--react-19"&gt;Chapter-04 - 第一个 React 项目——Vite + React 19&lt;/h1&gt;
&lt;h2 id="41-为什么选-vite"&gt;4.1 为什么选 Vite？&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;在正式开始写代码之前，我们先来聊聊为什么是 Vite。可能有些同学听说过 Webpack，这个老牌构建工具曾经统治前端江湖近十年。而 Vite 是 2020 年才诞生的&amp;quot;小鲜肉&amp;quot;，但它一出场就以&amp;quot;闪电般的速度&amp;quot;征服了无数开发者。&lt;/p&gt;</description></item><item><title>第5章 JSX语法</title><link>https://before80.github.io/prgms/Js/frameworks/react/Chapter-05-JSX-React-Syntax/</link><pubDate>Wed, 25 Mar 2026 12:56:00 +0800</pubDate><guid>https://before80.github.io/prgms/Js/frameworks/react/Chapter-05-JSX-React-Syntax/</guid><description>&lt;h1 id="chapter-05---jsxreact-的语法糖"&gt;Chapter-05 - JSX——React 的语法糖&lt;/h1&gt;
&lt;h2 id="51-jsxreact-的语法糖"&gt;5.1 JSX——React 的语法糖&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;终于到了 React 最独特、最让人&amp;quot;又爱又恨&amp;quot;的部分——JSX。如果你之前没接触过 JSX，第一次看到它的时候可能会产生一种&amp;quot;这到底是 HTML 还是 JavaScript&amp;quot;的困惑。没错，这就是 JSX 的魔力所在——它让 HTML 和 JavaScript 共处一室，在同一个文件里眉来眼去。&lt;/p&gt;</description></item><item><title>第6章 组件——React核心概念</title><link>https://before80.github.io/prgms/Js/frameworks/react/Chapter-06-Components-The-Core-of-React/</link><pubDate>Wed, 25 Mar 2026 12:56:00 +0800</pubDate><guid>https://before80.github.io/prgms/Js/frameworks/react/Chapter-06-Components-The-Core-of-React/</guid><description>&lt;h1 id="chapter-06---组件react-的核心"&gt;Chapter-06 - 组件——React 的核心&lt;/h1&gt;
&lt;h2 id="61-组件化开发的思想"&gt;6.1 组件化开发的思想&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;如果把 React 应用比作一座城市，那组件就是这座城市的每一栋建筑。有的建筑是摩天大楼（页面组件），有的是小卖部（按钮组件），有的是公交站牌（导航组件）。每一栋建筑都有自己的职责，自己的一亩三分地，不会跑去管别人的闲事——这就是组件化开发的核心思想。&lt;/p&gt;</description></item><item><title>第7章 Props与组件参数</title><link>https://before80.github.io/prgms/Js/frameworks/react/Chapter-07-Props-Component-Parameters/</link><pubDate>Wed, 25 Mar 2026 12:56:00 +0800</pubDate><guid>https://before80.github.io/prgms/Js/frameworks/react/Chapter-07-Props-Component-Parameters/</guid><description>&lt;h1 id="chapter-07---props组件的参数"&gt;Chapter-07 - Props——组件的&amp;quot;参数&amp;quot;&lt;/h1&gt;
&lt;h2 id="71-props-基础"&gt;7.1 Props 基础&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;如果把 React 组件比作一台饮料机，那 &lt;strong&gt;Props&lt;/strong&gt; 就是投进去的硬币和选择按钮——它们是组件的&amp;quot;输入参数&amp;quot;，决定了组件最终输出什么样的&amp;quot;饮料&amp;quot;。 Props 是 React 组件之间传递数据的主要方式，也是 React 单向数据流的核心载体。&lt;/p&gt;</description></item><item><title>第8章 State与组件生命周期</title><link>https://before80.github.io/prgms/Js/frameworks/react/Chapter-08-State-and-Component-Lifecycle/</link><pubDate>Wed, 25 Mar 2026 12:56:00 +0800</pubDate><guid>https://before80.github.io/prgms/Js/frameworks/react/Chapter-08-State-and-Component-Lifecycle/</guid><description>&lt;p&gt;﻿# Chapter-08 - State 与组件生命周期&lt;/p&gt;
&lt;h2 id="81-state-基础"&gt;8.1 State 基础&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Props 是从外部传入的数据，那组件内部自己产生的数据存在哪里呢？答案就是 &lt;strong&gt;State&lt;/strong&gt;。如果说 Props 是组件的&amp;quot;身份证&amp;quot;（由父母给的，不能自己改），那 State 就是组件的&amp;quot;钱包&amp;quot;（自己挣的，自己管）。State 是组件内部的可变数据，当 State 变化时，组件会自动重新渲染。&lt;/p&gt;</description></item><item><title>第9章 useEffect与副作用</title><link>https://before80.github.io/prgms/Js/frameworks/react/Chapter-09-useEffect-Side-Effects/</link><pubDate>Wed, 25 Mar 2026 12:56:00 +0800</pubDate><guid>https://before80.github.io/prgms/Js/frameworks/react/Chapter-09-useEffect-Side-Effects/</guid><description>&lt;h1 id="chapter-09---useeffect副作用的正确打开方式"&gt;Chapter-09 - useEffect——副作用的正确打开方式&lt;/h1&gt;
&lt;h2 id="91-useeffect-基础"&gt;9.1 useEffect 基础&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;如果把 React 组件比作一个&amp;quot;加工厂&amp;quot;，那 &lt;strong&gt;useEffect&lt;/strong&gt; 就是这个加工厂的&amp;quot;生产许可证&amp;quot;——它告诉 React：&amp;ldquo;除了正常生产产品（渲染 UI）之外，我还需要做一些别的事情，比如：采购原材料（请求数据）、处理废水废气（清理订阅）、和外面的世界打交道（操作 DOM、播放音乐、记录日志）。&amp;rdquo; useEffect 让函数组件拥有了&amp;quot;和外界互动&amp;quot;的能力。&lt;/p&gt;</description></item><item><title>第10章 useState深入与自定义Hooks</title><link>https://before80.github.io/prgms/Js/frameworks/react/Chapter-10-useState-Deep-Dive-and-Custom-Hooks/</link><pubDate>Wed, 25 Mar 2026 12:56:00 +0800</pubDate><guid>https://before80.github.io/prgms/Js/frameworks/react/Chapter-10-useState-Deep-Dive-and-Custom-Hooks/</guid><description>&lt;h1 id="chapter-10---usestate-深入与自定义-hook"&gt;Chapter-10 - useState 深入与自定义 Hook&lt;/h1&gt;
&lt;h2 id="101-函数式更新"&gt;10.1 函数式更新&lt;/h2&gt;
&lt;h3 id="1011-什么是函数式更新setstateprevstate--"&gt;10.1.1 什么是函数式更新：&lt;code&gt;setState(prevState =&amp;gt; ...)&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;函数式更新是 &lt;code&gt;setState&lt;/code&gt; 的一种特殊用法——传入一个以&lt;strong&gt;前一个状态&lt;/strong&gt;为参数的函数，返回新的状态。&lt;/p&gt;</description></item><item><title>第11章 useContext与跨组件传值</title><link>https://before80.github.io/prgms/Js/frameworks/react/Chapter-11-useContext-and-Cross-Component-Data-Passing/</link><pubDate>Wed, 25 Mar 2026 12:56:00 +0800</pubDate><guid>https://before80.github.io/prgms/Js/frameworks/react/Chapter-11-useContext-and-Cross-Component-Data-Passing/</guid><description>&lt;h1 id="chapter-11---usecontext-与跨层级数据传递"&gt;Chapter-11 - useContext 与跨层级数据传递&lt;/h1&gt;
&lt;h2 id="111-context-基础"&gt;11.1 Context 基础&lt;/h2&gt;
&lt;h3 id="1111-props-层层传递的痛苦props-drilling"&gt;11.1.1 Props 层层传递的痛苦：Props Drilling&lt;/h3&gt;
&lt;p&gt;在第六章我们学过，数据通过 props 从父组件传给子组件。但如果组件嵌套得很深（层级很多），数据就需要一层一层地往下传——这叫 &lt;strong&gt;Props Drilling&lt;/strong&gt;（props 层层向下钻）。&lt;/p&gt;</description></item><item><title>第12章 useReducer与复杂状态管理</title><link>https://before80.github.io/prgms/Js/frameworks/react/Chapter-12-useReducer-Complex-State-Management/</link><pubDate>Wed, 25 Mar 2026 12:56:00 +0800</pubDate><guid>https://before80.github.io/prgms/Js/frameworks/react/Chapter-12-useReducer-Complex-State-Management/</guid><description>&lt;h1 id="chapter-12---usereducer复杂状态逻辑管理"&gt;Chapter-12 - useReducer——复杂状态逻辑管理&lt;/h1&gt;
&lt;h2 id="121-usestate-vs-usereducer"&gt;12.1 useState vs useReducer&lt;/h2&gt;
&lt;h3 id="1211-usestate-适用场景简单独立的状态"&gt;12.1.1 useState 适用场景：简单、独立的状态&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;useState&lt;/code&gt; 适合管理&lt;strong&gt;简单的、相互独立的状态&lt;/strong&gt;。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-jsx" data-lang="jsx"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8a93a5;font-style:italic"&gt;// useState 最适合的场景：单个的、简单的状态
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#76a9f9"&gt;const&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;[&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;name&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;,&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;setName&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;]&lt;/span&gt; &lt;span style="color:#54b1c7"&gt;=&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;useState&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#76a9f9"&gt;const&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;[&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;isLoading&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;,&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;setIsLoading&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;]&lt;/span&gt; &lt;span style="color:#54b1c7"&gt;=&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;useState&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;false&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#76a9f9"&gt;const&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;[&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;count&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;,&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;setCount&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;]&lt;/span&gt; &lt;span style="color:#54b1c7"&gt;=&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;useState&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#d19a66"&gt;0&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="1212-usereducer-适用场景状态逻辑复杂多个子值相关联"&gt;12.1.2 useReducer 适用场景：状态逻辑复杂、多个子值相关联&lt;/h3&gt;
&lt;p&gt;当状态满足以下条件时，&lt;code&gt;useReducer&lt;/code&gt; 比 &lt;code&gt;useState&lt;/code&gt; 更好：&lt;/p&gt;</description></item><item><title>第13章 useMemo、useCallback与性能优化</title><link>https://before80.github.io/prgms/Js/frameworks/react/Chapter-13-useMemo-useCallback-and-React.memo-Performance-Optimization/</link><pubDate>Wed, 25 Mar 2026 12:56:00 +0800</pubDate><guid>https://before80.github.io/prgms/Js/frameworks/react/Chapter-13-useMemo-useCallback-and-React.memo-Performance-Optimization/</guid><description>&lt;h1 id="chapter-13---usememousecallback-与-reactmemo性能优化"&gt;Chapter-13 - useMemo、useCallback 与 React.memo——性能优化&lt;/h1&gt;
&lt;h2 id="131-usememo缓存计算结果"&gt;13.1 useMemo：缓存计算结果&lt;/h2&gt;
&lt;h3 id="1311-为什么需要-usememo"&gt;13.1.1 为什么需要 useMemo？&lt;/h3&gt;
&lt;p&gt;假设你有一个组件，每次渲染时都需要对大量数据做过滤、排序、统计——这些计算可能很耗时（想象一下对10万条数据排序）。问题是：&lt;strong&gt;即使数据没变，这些计算在每次渲染时都会重复执行&lt;/strong&gt;。&lt;/p&gt;</description></item><item><title>第14章 useLayoutEffect与Suspense基础</title><link>https://before80.github.io/prgms/Js/frameworks/react/Chapter-14-useLayoutEffect-and-Suspense-Basics/</link><pubDate>Wed, 25 Mar 2026 12:56:00 +0800</pubDate><guid>https://before80.github.io/prgms/Js/frameworks/react/Chapter-14-useLayoutEffect-and-Suspense-Basics/</guid><description>&lt;h1 id="chapter-14---uselayouteffect-与-suspense-基础"&gt;Chapter-14 - useLayoutEffect 与 Suspense 基础&lt;/h1&gt;
&lt;h2 id="141-uselayouteffect"&gt;14.1 useLayoutEffect&lt;/h2&gt;
&lt;h3 id="1411-uselayouteffect-与-useeffect-的时机差异"&gt;14.1.1 useLayoutEffect 与 useEffect 的时机差异&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;useLayoutEffect&lt;/code&gt; 和 &lt;code&gt;useEffect&lt;/code&gt; 的签名完全一样，但&lt;strong&gt;执行时机完全不同&lt;/strong&gt;：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-jsx" data-lang="jsx"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#aa89ea"&gt;useEffect&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(()&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#8a93a5;font-style:italic"&gt;// 在渲染内容显示到屏幕之后异步执行
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#aa89ea"&gt;console&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;log&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;useEffect: 渲染后异步执行&amp;#39;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#abb2bf"&gt;},&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;[])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#aa89ea"&gt;useLayoutEffect&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(()&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#8a93a5;font-style:italic"&gt;// 在渲染后但浏览器绘制之前同步执行
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#aa89ea"&gt;console&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;log&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;useLayoutEffect: 渲染后同步执行&amp;#39;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#abb2bf"&gt;},&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;[])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;执行顺序：&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>第15章 组件设计模式</title><link>https://before80.github.io/prgms/Js/frameworks/react/Chapter-15-Component-Design-Patterns/</link><pubDate>Wed, 25 Mar 2026 12:56:00 +0800</pubDate><guid>https://before80.github.io/prgms/Js/frameworks/react/Chapter-15-Component-Design-Patterns/</guid><description>&lt;h1 id="chapter-15---组件设计模式"&gt;Chapter-15 - 组件设计模式&lt;/h1&gt;
&lt;h2 id="151-高阶组件hoc"&gt;15.1 高阶组件（HOC）&lt;/h2&gt;
&lt;h3 id="1511-hoc-的概念接收组件返回新组件"&gt;15.1.1 HOC 的概念：接收组件，返回新组件&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;高阶组件（Higher-Order Component）&lt;/strong&gt; 是一个函数，接收一个组件作为参数，返回一个&lt;strong&gt;增强后的新组件&lt;/strong&gt;。&lt;/p&gt;</description></item><item><title>第16章 React样式全指南</title><link>https://before80.github.io/prgms/Js/frameworks/react/Chapter-16-React-Styling-Comprehensive-Guide/</link><pubDate>Wed, 25 Mar 2026 12:56:00 +0800</pubDate><guid>https://before80.github.io/prgms/Js/frameworks/react/Chapter-16-React-Styling-Comprehensive-Guide/</guid><description>&lt;h1 id="chapter-16---react-样式全解"&gt;Chapter-16 - React 样式全解&lt;/h1&gt;
&lt;h2 id="161-内联样式"&gt;16.1 内联样式&lt;/h2&gt;
&lt;h3 id="1611-内联样式的基本写法"&gt;16.1.1 内联样式的基本写法&lt;/h3&gt;
&lt;p&gt;内联样式直接在 JSX 元素的 &lt;code&gt;style&lt;/code&gt; 属性中传入 JavaScript 对象：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;12
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;13
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;14
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;15
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;16
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;17
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;18
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;19
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;20
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;21
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;22
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;23
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-jsx" data-lang="jsx"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#76a9f9"&gt;function&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;InlineStyleDemo&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;()&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#76a9f9"&gt;const&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;styles&lt;/span&gt; &lt;span style="color:#54b1c7"&gt;=&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#aa89ea"&gt;container&lt;/span&gt;&lt;span style="color:#54b1c7"&gt;:&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#aa89ea"&gt;padding&lt;/span&gt;&lt;span style="color:#54b1c7"&gt;:&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;20px&amp;#39;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#aa89ea"&gt;backgroundColor&lt;/span&gt;&lt;span style="color:#54b1c7"&gt;:&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;#f5f5f5&amp;#39;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#aa89ea"&gt;borderRadius&lt;/span&gt;&lt;span style="color:#54b1c7"&gt;:&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;8px&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#abb2bf"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#aa89ea"&gt;title&lt;/span&gt;&lt;span style="color:#54b1c7"&gt;:&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#aa89ea"&gt;fontSize&lt;/span&gt;&lt;span style="color:#54b1c7"&gt;:&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;24px&amp;#39;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#aa89ea"&gt;fontWeight&lt;/span&gt;&lt;span style="color:#54b1c7"&gt;:&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;bold&amp;#39;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#aa89ea"&gt;color&lt;/span&gt;&lt;span style="color:#54b1c7"&gt;:&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;#333&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#abb2bf"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#abb2bf"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#76a9f9"&gt;return&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#abb2bf"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#76a9f9"&gt;div&lt;/span&gt; &lt;span style="color:#cebc3a"&gt;style&lt;/span&gt;&lt;span style="color:#54b1c7"&gt;=&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;{&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;styles&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;container&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;}&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#abb2bf"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#76a9f9"&gt;h1&lt;/span&gt; &lt;span style="color:#cebc3a"&gt;style&lt;/span&gt;&lt;span style="color:#54b1c7"&gt;=&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;{&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;styles&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;title&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;}&amp;gt;&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;内联样式演示&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#76a9f9"&gt;h1&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#abb2bf"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#76a9f9"&gt;p&lt;/span&gt; &lt;span style="color:#cebc3a"&gt;style&lt;/span&gt;&lt;span style="color:#54b1c7"&gt;=&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;{{&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;color&lt;/span&gt;&lt;span style="color:#54b1c7"&gt;:&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;#666&amp;#39;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;,&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;fontSize&lt;/span&gt;&lt;span style="color:#54b1c7"&gt;:&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;14px&amp;#39;&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;}}&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#aa89ea"&gt;这是一段内联样式的文字&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#abb2bf"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#76a9f9"&gt;p&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#abb2bf"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#76a9f9"&gt;div&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#abb2bf"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#abb2bf"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="1612-动态样式的实现"&gt;16.1.2 动态样式的实现&lt;/h3&gt;
&lt;p&gt;内联样式的优势是可以轻松实现动态样式：&lt;/p&gt;</description></item><item><title>第17章 React Router v7路由管理</title><link>https://before80.github.io/prgms/Js/frameworks/react/Chapter-17-React-Router-v7-Routing-Management/</link><pubDate>Wed, 25 Mar 2026 12:56:00 +0800</pubDate><guid>https://before80.github.io/prgms/Js/frameworks/react/Chapter-17-React-Router-v7-Routing-Management/</guid><description>&lt;h1 id="chapter-17---react-router-v7路由管理"&gt;Chapter-17 - React Router v7——路由管理&lt;/h1&gt;
&lt;h2 id="171-spa-与路由基础"&gt;17.1 SPA 与路由基础&lt;/h2&gt;
&lt;h3 id="1711-传统多页应用-vs-spa"&gt;17.1.1 传统多页应用 vs SPA&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;传统多页应用（MPA）&lt;/strong&gt;：每次路由跳转，浏览器都会向服务器请求一个新的 HTML 页面。整个页面刷新，体验不流畅。&lt;/p&gt;</description></item><item><title>第18章 表单处理与数据验证</title><link>https://before80.github.io/prgms/Js/frameworks/react/Chapter-18-Form-Handling-and-Data-Validation/</link><pubDate>Wed, 25 Mar 2026 12:56:00 +0800</pubDate><guid>https://before80.github.io/prgms/Js/frameworks/react/Chapter-18-Form-Handling-and-Data-Validation/</guid><description>&lt;h1 id="chapter-18---表单处理与数据验证"&gt;Chapter-18 - 表单处理与数据验证&lt;/h1&gt;
&lt;h2 id="181-受控组件"&gt;18.1 受控组件&lt;/h2&gt;
&lt;h3 id="1811-受控组件的概念表单数据由-react-控制"&gt;18.1.1 受控组件的概念：表单数据由 React 控制&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;受控组件（Controlled Component）&lt;/strong&gt; 是指表单元素的值完全由 React 的 state 来控制的组件。用户的输入会触发 onChange 事件，更新 state，state 更新导致组件重新渲染，渲染出新的值。&lt;/p&gt;</description></item><item><title>第19章 HTTP请求与数据获取</title><link>https://before80.github.io/prgms/Js/frameworks/react/Chapter-19-HTTP-Requests-and-Data-Fetching/</link><pubDate>Wed, 25 Mar 2026 12:56:00 +0800</pubDate><guid>https://before80.github.io/prgms/Js/frameworks/react/Chapter-19-HTTP-Requests-and-Data-Fetching/</guid><description>&lt;h1 id="chapter-19---http-请求与数据获取"&gt;Chapter-19 - HTTP 请求与数据获取&lt;/h1&gt;
&lt;h2 id="191-fetch-api"&gt;19.1 fetch API&lt;/h2&gt;
&lt;h3 id="1911-fetch-的基本用法"&gt;19.1.1 fetch 的基本用法&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;fetch&lt;/code&gt; 是浏览器原生的网络请求 API，不需要安装任何库。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;12
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8a93a5;font-style:italic"&gt;// 基本语法
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#aa89ea"&gt;fetch&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;url&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;,&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;options&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;then&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;response&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#8a93a5;font-style:italic"&gt;// 处理响应
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#76a9f9"&gt;return&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;response&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;json&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;()&lt;/span&gt; &lt;span style="color:#8a93a5;font-style:italic"&gt;// 解析 JSON
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#abb2bf"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;then&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;data&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#aa89ea"&gt;console&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;log&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;data&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#abb2bf"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#76a9f9"&gt;catch&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;error&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#aa89ea"&gt;console&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;error&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;请求失败:&amp;#39;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;,&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;error&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#abb2bf"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="1912-get-请求与查询参数拼接"&gt;19.1.2 GET 请求与查询参数拼接&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;12
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;13
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;14
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;15
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;16
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;17
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;18
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;19
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8a93a5;font-style:italic"&gt;// 简单的 GET 请求
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#aa89ea"&gt;fetch&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;https://api.example.com/users&amp;#39;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;then&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;res&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;res&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;json&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;then&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;data&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;console&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;log&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;data&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8a93a5;font-style:italic"&gt;// 带查询参数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#76a9f9"&gt;const&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;params&lt;/span&gt; &lt;span style="color:#54b1c7"&gt;=&lt;/span&gt; &lt;span style="color:#76a9f9"&gt;new&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;URLSearchParams&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#aa89ea"&gt;page&lt;/span&gt;&lt;span style="color:#54b1c7"&gt;:&lt;/span&gt; &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#aa89ea"&gt;limit&lt;/span&gt;&lt;span style="color:#54b1c7"&gt;:&lt;/span&gt; &lt;span style="color:#d19a66"&gt;10&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#aa89ea"&gt;category&lt;/span&gt;&lt;span style="color:#54b1c7"&gt;:&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;tech&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#abb2bf"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#aa89ea"&gt;fetch&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#98c379"&gt;`https://api.example.com/articles?&lt;/span&gt;&lt;span style="color:#98c379"&gt;${&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;params&lt;/span&gt;&lt;span style="color:#98c379"&gt;}&lt;/span&gt;&lt;span style="color:#98c379"&gt;`&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;then&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;res&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;res&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;json&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;then&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;data&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;console&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;log&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;data&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8a93a5;font-style:italic"&gt;// 或者手动拼接
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#aa89ea"&gt;fetch&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;https://api.example.com/users?page=1&amp;amp;limit=10&amp;#39;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;then&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;res&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;res&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;json&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="1913-post-请求与请求体json--formdata"&gt;19.1.3 POST 请求与请求体（JSON / FormData）&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;12
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;13
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;14
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;15
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;16
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;17
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;18
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;19
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;20
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;21
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;22
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;23
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;24
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;25
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;26
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;27
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;28
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;29
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;30
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;31
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;32
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;33
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8a93a5;font-style:italic"&gt;// POST JSON
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#aa89ea"&gt;fetch&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;https://api.example.com/users&amp;#39;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;,&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#aa89ea"&gt;method&lt;/span&gt;&lt;span style="color:#54b1c7"&gt;:&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;POST&amp;#39;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#aa89ea"&gt;headers&lt;/span&gt;&lt;span style="color:#54b1c7"&gt;:&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;Content-Type&amp;#39;&lt;/span&gt;&lt;span style="color:#54b1c7"&gt;:&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;application/json&amp;#39;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;Authorization&amp;#39;&lt;/span&gt;&lt;span style="color:#54b1c7"&gt;:&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;Bearer token123&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#abb2bf"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#aa89ea"&gt;body&lt;/span&gt;&lt;span style="color:#54b1c7"&gt;:&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;JSON&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;stringify&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#aa89ea"&gt;name&lt;/span&gt;&lt;span style="color:#54b1c7"&gt;:&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;小明&amp;#39;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#aa89ea"&gt;email&lt;/span&gt;&lt;span style="color:#54b1c7"&gt;:&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;xiaoming@example.com&amp;#39;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#aa89ea"&gt;age&lt;/span&gt;&lt;span style="color:#54b1c7"&gt;:&lt;/span&gt; &lt;span style="color:#d19a66"&gt;25&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#abb2bf"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#abb2bf"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;then&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;res&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#76a9f9"&gt;if&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#54b1c7"&gt;!&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;res&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;ok&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;)&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#76a9f9"&gt;throw&lt;/span&gt; &lt;span style="color:#76a9f9"&gt;new&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;Error&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#98c379"&gt;`HTTP 错误！状态码：&lt;/span&gt;&lt;span style="color:#98c379"&gt;${&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;res&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;status&lt;/span&gt;&lt;span style="color:#98c379"&gt;}&lt;/span&gt;&lt;span style="color:#98c379"&gt;`&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#abb2bf"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#76a9f9"&gt;return&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;res&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;json&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#abb2bf"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;then&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;data&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;console&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;log&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;创建成功:&amp;#39;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;,&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;data&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#76a9f9"&gt;catch&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;err&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;console&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;error&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;请求失败:&amp;#39;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;,&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;err&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8a93a5;font-style:italic"&gt;// POST FormData（文件上传等）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#76a9f9"&gt;const&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;formData&lt;/span&gt; &lt;span style="color:#54b1c7"&gt;=&lt;/span&gt; &lt;span style="color:#76a9f9"&gt;new&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;FormData&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#aa89ea"&gt;formData&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;append&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;,&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;小明&amp;#39;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#aa89ea"&gt;formData&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;append&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;avatar&amp;#39;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;,&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;fileInput&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;files&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;[&lt;/span&gt;&lt;span style="color:#d19a66"&gt;0&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#aa89ea"&gt;fetch&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;https://api.example.com/upload&amp;#39;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;,&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#aa89ea"&gt;method&lt;/span&gt;&lt;span style="color:#54b1c7"&gt;:&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;POST&amp;#39;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#aa89ea"&gt;body&lt;/span&gt;&lt;span style="color:#54b1c7"&gt;:&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;formData&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#8a93a5;font-style:italic"&gt;// 注意：FormData 不需要手动设置 Content-Type
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#abb2bf"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;then&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;res&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;res&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;json&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="1914-fetch-的错误处理responseok-与-try-catch"&gt;19.1.4 fetch 的错误处理：response.ok 与 try-catch&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;12
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;13
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;14
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;15
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;16
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;17
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;18
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;19
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;20
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;21
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;22
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;23
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;24
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;25
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;26
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#76a9f9"&gt;async&lt;/span&gt; &lt;span style="color:#76a9f9"&gt;function&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;fetchUser&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;id&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;)&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#76a9f9"&gt;try&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#76a9f9"&gt;const&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;res&lt;/span&gt; &lt;span style="color:#54b1c7"&gt;=&lt;/span&gt; &lt;span style="color:#76a9f9"&gt;await&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;fetch&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#98c379"&gt;`https://api.example.com/users/&lt;/span&gt;&lt;span style="color:#98c379"&gt;${&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;id&lt;/span&gt;&lt;span style="color:#98c379"&gt;}&lt;/span&gt;&lt;span style="color:#98c379"&gt;`&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#8a93a5;font-style:italic"&gt;// 检查 HTTP 状态码
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#76a9f9"&gt;if&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#54b1c7"&gt;!&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;res&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;ok&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;)&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#76a9f9"&gt;if&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;res&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;status&lt;/span&gt; &lt;span style="color:#54b1c7"&gt;===&lt;/span&gt; &lt;span style="color:#d19a66"&gt;404&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;)&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#76a9f9"&gt;throw&lt;/span&gt; &lt;span style="color:#76a9f9"&gt;new&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;Error&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;用户不存在&amp;#39;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#abb2bf"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#76a9f9"&gt;if&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;res&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;status&lt;/span&gt; &lt;span style="color:#54b1c7"&gt;===&lt;/span&gt; &lt;span style="color:#d19a66"&gt;401&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;)&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#76a9f9"&gt;throw&lt;/span&gt; &lt;span style="color:#76a9f9"&gt;new&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;Error&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;未授权，请重新登录&amp;#39;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#abb2bf"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#76a9f9"&gt;throw&lt;/span&gt; &lt;span style="color:#76a9f9"&gt;new&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;Error&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#98c379"&gt;`请求失败：&lt;/span&gt;&lt;span style="color:#98c379"&gt;${&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;res&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;status&lt;/span&gt;&lt;span style="color:#98c379"&gt;}&lt;/span&gt;&lt;span style="color:#98c379"&gt; &lt;/span&gt;&lt;span style="color:#98c379"&gt;${&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;res&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;statusText&lt;/span&gt;&lt;span style="color:#98c379"&gt;}&lt;/span&gt;&lt;span style="color:#98c379"&gt;`&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#abb2bf"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#76a9f9"&gt;const&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;data&lt;/span&gt; &lt;span style="color:#54b1c7"&gt;=&lt;/span&gt; &lt;span style="color:#76a9f9"&gt;await&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;res&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;json&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#76a9f9"&gt;return&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;data&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#abb2bf"&gt;}&lt;/span&gt; &lt;span style="color:#76a9f9"&gt;catch&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;error&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;)&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#8a93a5;font-style:italic"&gt;// 捕获网络错误（如断网）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#76a9f9"&gt;if&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;error&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;name&lt;/span&gt; &lt;span style="color:#54b1c7"&gt;===&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;TypeError&amp;#39;&lt;/span&gt; &lt;span style="color:#54b1c7"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;error&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;message&lt;/span&gt; &lt;span style="color:#54b1c7"&gt;===&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;Failed to fetch&amp;#39;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;)&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#76a9f9"&gt;throw&lt;/span&gt; &lt;span style="color:#76a9f9"&gt;new&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;Error&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;网络连接失败，请检查网络&amp;#39;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#abb2bf"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#76a9f9"&gt;throw&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;error&lt;/span&gt; &lt;span style="color:#8a93a5;font-style:italic"&gt;// 其他错误重新抛出
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#abb2bf"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#abb2bf"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="1915-fetch-的超时处理abortcontroller"&gt;19.1.5 fetch 的超时处理：AbortController&lt;/h3&gt;
&lt;p&gt;fetch 默认没有超时机制，需要用 AbortController 实现：&lt;/p&gt;</description></item><item><title>第20章 Redux Toolkit完整状态管理</title><link>https://before80.github.io/prgms/Js/frameworks/react/Chapter-20-Redux-Toolkit-Complete-State-Management/</link><pubDate>Wed, 25 Mar 2026 12:56:00 +0800</pubDate><guid>https://before80.github.io/prgms/Js/frameworks/react/Chapter-20-Redux-Toolkit-Complete-State-Management/</guid><description>&lt;h1 id="chapter-20---redux-toolkit最完整的全局状态方案"&gt;Chapter-20 - Redux Toolkit——最完整的全局状态方案&lt;/h1&gt;
&lt;h2 id="201-redux-核心概念"&gt;20.1 Redux 核心概念&lt;/h2&gt;
&lt;h3 id="2011-redux-的三大原则单一数据源state-只读纯函数"&gt;20.1.1 Redux 的三大原则：单一数据源、state 只读、纯函数&lt;/h3&gt;
&lt;p&gt;Redux 是 React 生态中最经典的状态管理库，基于三大原则：&lt;/p&gt;</description></item><item><title>第21章 Zustand轻量级状态管理</title><link>https://before80.github.io/prgms/Js/frameworks/react/Chapter-21-Zustand-Lightweight-State-Management/</link><pubDate>Wed, 25 Mar 2026 12:56:00 +0800</pubDate><guid>https://before80.github.io/prgms/Js/frameworks/react/Chapter-21-Zustand-Lightweight-State-Management/</guid><description>&lt;h1 id="chapter-21---zustand轻量级状态管理"&gt;Chapter-21 - Zustand——轻量级状态管理&lt;/h1&gt;
&lt;h2 id="211-zustand-基础"&gt;21.1 Zustand 基础&lt;/h2&gt;
&lt;h3 id="2111-安装与-store-创建"&gt;21.1.1 安装与 store 创建&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Zustand&lt;/strong&gt; 是一个超轻量的状态管理库，比 Redux 简洁得多，但功能同样强大。&lt;/p&gt;
&lt;p&gt;什么场景需要它？想象一下：你的应用有&amp;quot;主题切换&amp;quot;功能，用户在设置页改了深色模式，头部组件、侧边栏组件、底部组件&amp;hellip;十几个组件都要响应这个变化。用 Context 要层层嵌套，用 Redux 又太重。&lt;strong&gt;Zustand 就是来解决这种&amp;quot;中等规模&amp;quot;状态共享问题的&lt;/strong&gt;——比 Context 强大（细粒度订阅），比 Redux 简单（不用写模板代码）。&lt;/p&gt;</description></item><item><title>第22章 TypeScript与React</title><link>https://before80.github.io/prgms/Js/frameworks/react/Chapter-22-TypeScript-and-React/</link><pubDate>Wed, 25 Mar 2026 12:56:00 +0800</pubDate><guid>https://before80.github.io/prgms/Js/frameworks/react/Chapter-22-TypeScript-and-React/</guid><description>&lt;h1 id="chapter-22---typescript-与-react"&gt;Chapter-22 - TypeScript 与 React&lt;/h1&gt;
&lt;h2 id="221-为什么用-typescript"&gt;22.1 为什么用 TypeScript？&lt;/h2&gt;
&lt;h3 id="2211-类型安全带来的开发体验提升"&gt;22.1.1 类型安全带来的开发体验提升&lt;/h3&gt;
&lt;p&gt;TypeScript 是 JavaScript 的超集，它在 JavaScript 的基础上添加了&lt;strong&gt;静态类型检查&lt;/strong&gt;。在开发阶段就能发现错误，而不是等到运行时才崩溃。&lt;/p&gt;</description></item><item><title>第23章 Vite深入配置</title><link>https://before80.github.io/prgms/Js/frameworks/react/Chapter-23-Vite-Advanced-Configuration/</link><pubDate>Wed, 25 Mar 2026 12:56:00 +0800</pubDate><guid>https://before80.github.io/prgms/Js/frameworks/react/Chapter-23-Vite-Advanced-Configuration/</guid><description>&lt;h1 id="chapter-23---vite-深入配置"&gt;Chapter-23 - Vite 深入配置&lt;/h1&gt;
&lt;h2 id="231-vite-原理"&gt;23.1 Vite 原理&lt;/h2&gt;
&lt;h3 id="2311-开发环境基于-esm-的按需编译"&gt;23.1.1 开发环境：基于 ESM 的按需编译&lt;/h3&gt;
&lt;p&gt;Vite 的开发环境利用浏览器的原生 ES Module 支持，&lt;strong&gt;不需要打包&lt;/strong&gt;。源文件按需编译，服务启动速度极快。&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart LR
 A[&amp;#34;浏览器请求\nimport App from &amp;#39;./App.jsx&amp;#39;&amp;#34;] --&amp;gt; B[&amp;#34;Vite 拦截请求&amp;#34;]
 B --&amp;gt; C[&amp;#34;查找源文件&amp;#34;]
 C --&amp;gt; D[&amp;#34;编译\n（仅此文件）&amp;#34;]
 D --&amp;gt; E[&amp;#34;返回编译后的 JS\n（含 HMR 客户端代码）&amp;#34;]&lt;/pre&gt;
&lt;h3 id="2312-生产环境rollup-打包"&gt;23.1.2 生产环境：Rollup 打包&lt;/h3&gt;
&lt;p&gt;Vite 在生产环境使用 &lt;strong&gt;Rollup&lt;/strong&gt; 进行打包，生成优化的静态资源。&lt;/p&gt;</description></item><item><title>第24章 测试——React应用质量保障</title><link>https://before80.github.io/prgms/Js/frameworks/react/Chapter-24-Testing-Quality-Assurance-for-React-Apps/</link><pubDate>Wed, 25 Mar 2026 12:56:00 +0800</pubDate><guid>https://before80.github.io/prgms/Js/frameworks/react/Chapter-24-Testing-Quality-Assurance-for-React-Apps/</guid><description>&lt;h1 id="chapter-24---测试react-应用的质量保障"&gt;Chapter-24 - 测试——React 应用的质量保障&lt;/h1&gt;
&lt;h2 id="241-测试概念"&gt;24.1 测试概念&lt;/h2&gt;
&lt;h3 id="2411-单元测试最小可测试单元"&gt;24.1.1 单元测试：最小可测试单元&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;单元测试（Unit Test）&lt;/strong&gt; 针对代码的最小单元进行测试，通常是一个函数或一个组件。&lt;/p&gt;</description></item><item><title>第25章 React性能优化全解</title><link>https://before80.github.io/prgms/Js/frameworks/react/Chapter-25-React-Performance-Optimization-Comprehensive/</link><pubDate>Wed, 25 Mar 2026 12:56:00 +0800</pubDate><guid>https://before80.github.io/prgms/Js/frameworks/react/Chapter-25-React-Performance-Optimization-Comprehensive/</guid><description>&lt;h1 id="chapter-25---react-性能优化全解"&gt;Chapter-25 - React 性能优化全解&lt;/h1&gt;
&lt;h2 id="251-react-devtools-profiler"&gt;25.1 React DevTools Profiler&lt;/h2&gt;
&lt;h3 id="2511-安装-profiler-插件"&gt;25.1.1 安装 Profiler 插件&lt;/h3&gt;
&lt;p&gt;在 Chrome 扩展商店搜索&amp;quot;React Developer Tools&amp;quot;，安装后打开 DevTools（F12），切换到 &amp;ldquo;Profiler&amp;rdquo; 标签。&lt;/p&gt;</description></item><item><title>第26章 项目一——Todo App增强版</title><link>https://before80.github.io/prgms/Js/frameworks/react/Chapter-26-Project-One-Todo-App-Enhanced/</link><pubDate>Wed, 25 Mar 2026 12:56:00 +0800</pubDate><guid>https://before80.github.io/prgms/Js/frameworks/react/Chapter-26-Project-One-Todo-App-Enhanced/</guid><description>&lt;h1 id="chapter-26---项目一todo-app-增强版"&gt;Chapter-26 - 项目一——Todo App 增强版&lt;/h1&gt;
&lt;h2 id="261-项目需求分析与结构设计"&gt;26.1 项目需求分析与结构设计&lt;/h2&gt;
&lt;h3 id="2611-功能列表增删改查筛选分类持久化"&gt;26.1.1 功能列表：增删改查、筛选、分类、持久化&lt;/h3&gt;
&lt;p&gt;一个完整的 Todo App 增强版不只是&amp;quot;能记事情&amp;quot;这么简单——它要像一个小型的效率工具，让用户感受到&amp;quot;我在掌控我的任务&amp;quot;。&lt;/p&gt;</description></item><item><title>第27章 项目二——社交类应用</title><link>https://before80.github.io/prgms/Js/frameworks/react/Chapter-27-Project-Two-Social-App/</link><pubDate>Wed, 25 Mar 2026 12:56:00 +0800</pubDate><guid>https://before80.github.io/prgms/Js/frameworks/react/Chapter-27-Project-Two-Social-App/</guid><description>&lt;h1 id="chapter-27---项目二社交类应用"&gt;Chapter-27 - 项目二——社交类应用&lt;/h1&gt;
&lt;h2 id="271-项目架构设计"&gt;27.1 项目架构设计&lt;/h2&gt;
&lt;h3 id="2711-页面划分feed--详情--个人页--消息"&gt;27.1.1 页面划分：Feed / 详情 / 个人页 / 消息&lt;/h3&gt;
&lt;p&gt;社交应用的核心页面设计，某种程度上决定了整个应用的用户体验基线。&lt;/p&gt;</description></item><item><title>第28章 项目三——电商后台管理系统</title><link>https://before80.github.io/prgms/Js/frameworks/react/Chapter-28-Project-Three-Ecommerce-Admin-System/</link><pubDate>Wed, 25 Mar 2026 12:56:00 +0800</pubDate><guid>https://before80.github.io/prgms/Js/frameworks/react/Chapter-28-Project-Three-Ecommerce-Admin-System/</guid><description>&lt;h1 id="chapter-28---项目三电商后台管理系统"&gt;Chapter-28 - 项目三——电商后台管理系统&lt;/h1&gt;
&lt;h2 id="281-组件库选型"&gt;28.1 组件库选型&lt;/h2&gt;
&lt;h3 id="2811-ant-design-入门开箱即用的企业级组件"&gt;28.1.1 Ant Design 入门：开箱即用的企业级组件&lt;/h3&gt;
&lt;p&gt;Ant Design（简称 AntD）是蚂蚁金服开源的企业级 React 组件库，提供丰富的企业级组件。&lt;/p&gt;</description></item><item><title>第29章 React运行机制</title><link>https://before80.github.io/prgms/Js/frameworks/react/Chapter-29-React-Internal-Mechanism/</link><pubDate>Wed, 25 Mar 2026 12:56:00 +0800</pubDate><guid>https://before80.github.io/prgms/Js/frameworks/react/Chapter-29-React-Internal-Mechanism/</guid><description>&lt;h1 id="chapter-29---react-运行机制"&gt;Chapter-29 - React 运行机制&lt;/h1&gt;
&lt;h2 id="291-virtual-dom-原理"&gt;29.1 Virtual DOM 原理&lt;/h2&gt;
&lt;h3 id="2911-dom-的性能问题"&gt;29.1.1 DOM 的性能问题&lt;/h3&gt;
&lt;p&gt;直接操作真实 DOM 是昂贵的——每次 DOM 修改都会触发浏览器的重排（Reflow）和重绘（Repaint）。&lt;/p&gt;
&lt;h3 id="2912-虚拟-dom-的数据结构"&gt;29.1.2 虚拟 DOM 的数据结构&lt;/h3&gt;
&lt;p&gt;虚拟 DOM 是一个 JavaScript 对象树，描述真实 DOM 的结构。&lt;/p&gt;</description></item><item><title>第30章 React 19新特性</title><link>https://before80.github.io/prgms/Js/frameworks/react/Chapter-30-React-19-New-Features/</link><pubDate>Wed, 25 Mar 2026 12:56:00 +0800</pubDate><guid>https://before80.github.io/prgms/Js/frameworks/react/Chapter-30-React-19-New-Features/</guid><description>&lt;h1 id="chapter-30---react-19-新特性"&gt;Chapter-30 - React 19 新特性&lt;/h1&gt;
&lt;h2 id="301-use-hookreact-19-最重大的-api"&gt;30.1 use() Hook：React 19 最重大的 API&lt;/h2&gt;
&lt;h3 id="3011-use-的基本用法"&gt;30.1.1 use() 的基本用法&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;use()&lt;/code&gt; 是 React 19 引入的最重要新 API，它允许在组件内部读取 Promise 和 Context。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-jsx" data-lang="jsx"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#76a9f9"&gt;import&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;{&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;use&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;}&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;from&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;react&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8a93a5;font-style:italic"&gt;// use() 读取 Promise
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#76a9f9"&gt;function&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;UserProfile&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;({&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;userPromise&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;})&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#76a9f9"&gt;const&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;user&lt;/span&gt; &lt;span style="color:#54b1c7"&gt;=&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;use&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;userPromise&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#76a9f9"&gt;return&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#76a9f9"&gt;h1&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;&amp;gt;{&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;user&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;name&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;}&amp;lt;/&lt;/span&gt;&lt;span style="color:#76a9f9"&gt;h1&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#abb2bf"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="3012-use-在-render-中读取-promise--context"&gt;30.1.2 use() 在 render 中读取 Promise / Context&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;use()&lt;/code&gt; 可以在渲染阶段读取 Promise，并在 Promise resolve 后自动重新渲染。&lt;/p&gt;</description></item><item><title>第31章 React并发模式</title><link>https://before80.github.io/prgms/Js/frameworks/react/Chapter-31-React-Concurrency-Mode/</link><pubDate>Wed, 25 Mar 2026 12:56:00 +0800</pubDate><guid>https://before80.github.io/prgms/Js/frameworks/react/Chapter-31-React-Concurrency-Mode/</guid><description>&lt;h1 id="chapter-31---react-并发模式"&gt;Chapter-31 - React 并发模式&lt;/h1&gt;
&lt;h2 id="311-并发渲染原理"&gt;31.1 并发渲染原理&lt;/h2&gt;
&lt;h3 id="3111-并发渲染的内部机制"&gt;31.1.1 并发渲染的内部机制&lt;/h3&gt;
&lt;p&gt;React 18 引入了&lt;strong&gt;并发渲染（Concurrent Rendering）&lt;/strong&gt;，它让 React 能够同时准备多个版本的 UI，根据优先级选择先渲染哪个。&lt;/p&gt;</description></item><item><title>第32章 Next.js全栈开发</title><link>https://before80.github.io/prgms/Js/frameworks/react/Chapter-32-Next.js-Fullstack-Development/</link><pubDate>Wed, 25 Mar 2026 12:56:00 +0800</pubDate><guid>https://before80.github.io/prgms/Js/frameworks/react/Chapter-32-Next.js-Fullstack-Development/</guid><description>&lt;h1 id="chapter-32---nextjs-全栈开发"&gt;Chapter-32 - Next.js 全栈开发&lt;/h1&gt;
&lt;h2 id="321-nextjs-概述"&gt;32.1 Next.js 概述&lt;/h2&gt;
&lt;h3 id="3211-nextjs-app-router-vs-pages-router"&gt;32.1.1 Next.js App Router vs Pages Router&lt;/h3&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;对比项&lt;/th&gt;
 &lt;th&gt;Pages Router&lt;/th&gt;
 &lt;th&gt;App Router&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;路由&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;基于文件系统&lt;/td&gt;
 &lt;td&gt;基于文件系统&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;组件&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;客户端组件&lt;/td&gt;
 &lt;td&gt;服务端组件优先&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;数据获取&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;getServerSideProps&lt;/td&gt;
 &lt;td&gt;async Server Components&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;推荐场景&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;现有项目&lt;/td&gt;
 &lt;td&gt;新项目&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="3212-app-router-的新特性"&gt;32.1.2 App Router 的新特性&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;服务端组件默认&lt;/strong&gt;：组件默认是服务端的&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;React 19 支持&lt;/strong&gt;：App Router 是 React 19 特性的完整支持&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;嵌套布局&lt;/strong&gt;：layout.tsx 实现嵌套布局&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="3213-迁移策略"&gt;32.1.3 迁移策略&lt;/h3&gt;
&lt;p&gt;从 Pages Router 迁移到 App Router：&lt;/p&gt;</description></item><item><title>第33章 React生态系统与优秀库</title><link>https://before80.github.io/prgms/Js/frameworks/react/Chapter-33-React-Ecosystem-Best-Libraries/</link><pubDate>Wed, 25 Mar 2026 12:56:00 +0800</pubDate><guid>https://before80.github.io/prgms/Js/frameworks/react/Chapter-33-React-Ecosystem-Best-Libraries/</guid><description>&lt;h1 id="chapter-33---react-生态精选库"&gt;Chapter-33 - React 生态精选库&lt;/h1&gt;
&lt;h2 id="331-动画framer-motion"&gt;33.1 动画：Framer Motion&lt;/h2&gt;
&lt;h3 id="3311-motion-组件的基本用法"&gt;33.1.1 motion 组件的基本用法&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;为什么需要动画库？&lt;/strong&gt; 想象没有动画库的时候，你想让一个 div 淡入+移动+缩放，要写一堆 &lt;code&gt;setInterval&lt;/code&gt; + &lt;code&gt;CSS transition&lt;/code&gt;，还要手动管理动画状态。代码又臭又长，动画间的协调更是噩梦。&lt;/p&gt;</description></item><item><title>第34章 React与AI</title><link>https://before80.github.io/prgms/Js/frameworks/react/Chapter-34-React-and-AI/</link><pubDate>Wed, 25 Mar 2026 12:56:00 +0800</pubDate><guid>https://before80.github.io/prgms/Js/frameworks/react/Chapter-34-React-and-AI/</guid><description>&lt;h1 id="chapter-34---react-与-ai"&gt;Chapter-34 - React 与 AI&lt;/h1&gt;
&lt;h2 id="341-ai-api-集成"&gt;34.1 AI API 集成&lt;/h2&gt;
&lt;h3 id="3411-openai-api-的基本调用"&gt;34.1.1 OpenAI API 的基本调用&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;React + AI 可以做什么？&lt;/strong&gt; 这是个开放问题，答案很多：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;AI 聊天机器人&lt;/strong&gt;：像 ChatGPT 一样的对话界面&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;内容生成&lt;/strong&gt;：输入标题 AI 生成文章、输入描述生成图片&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;智能客服&lt;/strong&gt;：理解用户问题，自动回复或转人工&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;代码助手&lt;/strong&gt;：解释代码、debug、生成代码&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;多模态&lt;/strong&gt;：输入图片+文字，AI 理解图片内容&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;本质上，AI API 让 React 应用有了&amp;quot;理解&amp;quot;和&amp;quot;生成&amp;quot;的能力——不只是展示静态内容，而是能对话、能思考、能创造。&lt;/p&gt;</description></item><item><title>第35章 跨平台桌面开发</title><link>https://before80.github.io/prgms/Js/frameworks/react/Chapter-35-Cross-Platform-Desktop-Development/</link><pubDate>Wed, 25 Mar 2026 12:56:00 +0800</pubDate><guid>https://before80.github.io/prgms/Js/frameworks/react/Chapter-35-Cross-Platform-Desktop-Development/</guid><description>&lt;h1 id="chapter-35---跨平台桌面开发"&gt;Chapter-35 - 跨平台桌面开发&lt;/h1&gt;
&lt;h2 id="351-electron"&gt;35.1 Electron&lt;/h2&gt;
&lt;h3 id="3511-electron-架构主进程--渲染进程"&gt;35.1.1 Electron 架构：主进程 + 渲染进程&lt;/h3&gt;
&lt;p&gt;Electron 使用 Chromium + Node.js，分为：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;主进程（Main Process）&lt;/strong&gt;：Node.js 环境，管理窗口、系统操作&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;渲染进程（Renderer Process）&lt;/strong&gt;：Chromium 环境，运行 React 应用&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="3512-react--electron-项目搭建"&gt;35.1.2 React + Electron 项目搭建&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8a93a5;font-style:italic"&gt;# npm create electron-vite@latest：调用 npm 执行 electron-vite 脚手架工具&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8a93a5;font-style:italic"&gt;# my-app：项目名称（会创建一个同名文件夹）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8a93a5;font-style:italic"&gt;# electron-vite 集成了 Vite + Electron，比纯 Electron 配置少很多&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;npm create electron-vite@latest my-app
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="3513-ipc-通信主进程与渲染进程数据交换"&gt;35.1.3 IPC 通信：主进程与渲染进程数据交换&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;12
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8a93a5;font-style:italic"&gt;// 主进程（main/index.ts）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#76a9f9"&gt;import&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;{&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;app&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;,&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;ipcMain&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;}&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;from&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;electron&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#aa89ea"&gt;ipcMain&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;handle&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;get-app-version&amp;#39;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;,&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;()&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#76a9f9"&gt;return&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;app&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;getVersion&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#abb2bf"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#aa89ea"&gt;ipcMain&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;handle&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;open-file-dialog&amp;#39;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;,&lt;/span&gt; &lt;span style="color:#76a9f9"&gt;async&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;()&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#76a9f9"&gt;const&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;{&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;dialog&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;}&lt;/span&gt; &lt;span style="color:#54b1c7"&gt;=&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;require&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;electron&amp;#39;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#76a9f9"&gt;const&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;result&lt;/span&gt; &lt;span style="color:#54b1c7"&gt;=&lt;/span&gt; &lt;span style="color:#76a9f9"&gt;await&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;dialog&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;showOpenDialog&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;({&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;properties&lt;/span&gt;&lt;span style="color:#54b1c7"&gt;:&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;[&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;openFile&amp;#39;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;]&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#76a9f9"&gt;return&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;result&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;filePaths&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#abb2bf"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8a93a5;font-style:italic"&gt;// 渲染进程（ preload.cjs，用于安全暴露 API）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#76a9f9"&gt;const&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;{&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;contextBridge&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;,&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;ipcRenderer&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;}&lt;/span&gt; &lt;span style="color:#54b1c7"&gt;=&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;require&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;electron&amp;#39;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#aa89ea"&gt;contextBridge&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;exposeInMainWorld&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;electronAPI&amp;#39;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;,&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#aa89ea"&gt;getAppVersion&lt;/span&gt;&lt;span style="color:#54b1c7"&gt;:&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;()&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;ipcRenderer&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;invoke&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;get-app-version&amp;#39;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#aa89ea"&gt;openFileDialog&lt;/span&gt;&lt;span style="color:#54b1c7"&gt;:&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;()&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;ipcRenderer&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;invoke&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;(&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;open-file-dialog&amp;#39;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#abb2bf"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8a93a5;font-style:italic"&gt;// React 组件中调用
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#76a9f9"&gt;const&lt;/span&gt; &lt;span style="color:#aa89ea"&gt;version&lt;/span&gt; &lt;span style="color:#54b1c7"&gt;=&lt;/span&gt; &lt;span style="color:#76a9f9"&gt;await&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;window&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;electronAPI&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;.&lt;/span&gt;&lt;span style="color:#aa89ea"&gt;getAppVersion&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="3514-electron-builder-打包发布"&gt;35.1.4 electron-builder 打包发布&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;npm install -D electron-builder
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;12
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;13
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;14
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;15
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;16
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;17
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;18
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;19
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;20
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;21
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;22
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8a93a5;font-style:italic"&gt;// electron-builder.json
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#abb2bf"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#8a93a5;font-style:italic"&gt;// 应用唯一标识符，格式通常为 com.公司名.产品名，用于系统安装和卸载
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#76a9f9"&gt;&amp;#34;appId&amp;#34;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;:&lt;/span&gt; &lt;span style="color:#63c381"&gt;&amp;#34;com.myapp.desktop&amp;#34;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#8a93a5;font-style:italic"&gt;// 打包后显示的应用名称（即开始菜单/程序列表中的名字）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#76a9f9"&gt;&amp;#34;productName&amp;#34;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;:&lt;/span&gt; &lt;span style="color:#63c381"&gt;&amp;#34;MyApp&amp;#34;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#8a93a5;font-style:italic"&gt;// 打包输出目录，&amp;#34;release&amp;#34; 文件夹下会生成各平台的安装包
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#76a9f9"&gt;&amp;#34;directories&amp;#34;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;:&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;{&lt;/span&gt; &lt;span style="color:#76a9f9"&gt;&amp;#34;output&amp;#34;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;:&lt;/span&gt; &lt;span style="color:#63c381"&gt;&amp;#34;release&amp;#34;&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#8a93a5;font-style:italic"&gt;// 需要打包进应用的文件或目录（** 通配符表示递归匹配）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#8a93a5;font-style:italic"&gt;// 此处将 Vite 构建产物 dist 目录下的所有文件打包
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#76a9f9"&gt;&amp;#34;files&amp;#34;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;:&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;[&lt;/span&gt;&lt;span style="color:#63c381"&gt;&amp;#34;dist/**/*&amp;#34;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#8a93a5;font-style:italic"&gt;// Windows 平台打包配置
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#8a93a5;font-style:italic"&gt;// target 指定打包格式：nsis = 安装向导格式（.exe），portable = 单文件便携版
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#8a93a5;font-style:italic"&gt;// 可选值还有：portable、appx、msi 等
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#76a9f9"&gt;&amp;#34;win&amp;#34;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;:&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;{&lt;/span&gt; &lt;span style="color:#76a9f9"&gt;&amp;#34;target&amp;#34;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;:&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;[&lt;/span&gt;&lt;span style="color:#63c381"&gt;&amp;#34;nsis&amp;#34;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;]&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#8a93a5;font-style:italic"&gt;// macOS 平台打包配置
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#8a93a5;font-style:italic"&gt;// target 可选：dmg（磁盘镜像）、pkg（安装包）、zip（压缩包）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#76a9f9"&gt;&amp;#34;mac&amp;#34;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;:&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;{&lt;/span&gt; &lt;span style="color:#76a9f9"&gt;&amp;#34;target&amp;#34;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;:&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;[&lt;/span&gt;&lt;span style="color:#63c381"&gt;&amp;#34;dmg&amp;#34;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;]&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#8a93a5;font-style:italic"&gt;// Linux 平台打包配置
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#8a93a5;font-style:italic"&gt;// target 可选：AppImage（通用可执行格式）、deb（Debian/Ubuntu）、rpm（Fedora/RHEL）、tar.gz
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#76a9f9"&gt;&amp;#34;linux&amp;#34;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;:&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;{&lt;/span&gt; &lt;span style="color:#76a9f9"&gt;&amp;#34;target&amp;#34;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;:&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;[&lt;/span&gt;&lt;span style="color:#63c381"&gt;&amp;#34;AppImage&amp;#34;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;]&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#abb2bf"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="352-tauri"&gt;35.2 Tauri&lt;/h2&gt;
&lt;h3 id="3521-tauri-的优势体积小安全rust-后端"&gt;35.2.1 Tauri 的优势：体积小、安全、Rust 后端&lt;/h3&gt;
&lt;p&gt;Tauri 用 Rust 替代 Node.js 作为后端，产物极小（~3MB vs Electron 的 100MB+）。包体积小的代价是：Node.js 生态不可用，系统级 API 需要额外配置。&lt;/p&gt;</description></item><item><title>第36章 React工程化与架构</title><link>https://before80.github.io/prgms/Js/frameworks/react/Chapter-36-React-Engineering-and-Architecture/</link><pubDate>Wed, 25 Mar 2026 12:56:00 +0800</pubDate><guid>https://before80.github.io/prgms/Js/frameworks/react/Chapter-36-React-Engineering-and-Architecture/</guid><description>&lt;h1 id="chapter-36---react-工程化与架构"&gt;Chapter-36 - React 工程化与架构&lt;/h1&gt;
&lt;h2 id="361-项目目录结构设计"&gt;36.1 项目目录结构设计&lt;/h2&gt;
&lt;h3 id="3611-feature-based-结构"&gt;36.1.1 feature-based 结构&lt;/h3&gt;
&lt;p&gt;按功能/业务模块组织代码，适合中大型项目。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;src/
├── features/
│ ├── auth/
│ │ ├── components/
│ │ ├── hooks/
│ │ └── api/
│ └── products/
└── shared/
 ├── components/
 ├── hooks/
 └── utils/
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="3612-常用目录划分"&gt;36.1.2 常用目录划分&lt;/h3&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;目录&lt;/th&gt;
 &lt;th&gt;职责&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;components/&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;公共 UI 组件&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;pages/&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;页面组件&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;hooks/&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;自定义 Hooks&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;utils/&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;工具函数&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;api/&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;API 请求&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;stores/&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;状态管理&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;types/&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;TypeScript 类型&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;constants/&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;常量配置&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="362-代码质量"&gt;36.2 代码质量&lt;/h2&gt;
&lt;h3 id="3621-eslint--prettier-配置"&gt;36.2.1 ESLint + Prettier 配置&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;div style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;npm install -D eslint prettier
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;npm install -D eslint-config-prettier eslint-plugin-prettier
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;12
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;13
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;14
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#58626f"&gt;15
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#b0c4de;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#8a93a5;font-style:italic"&gt;// .eslintrc.json
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#abb2bf"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#76a9f9"&gt;&amp;#34;extends&amp;#34;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;:&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#63c381"&gt;&amp;#34;eslint:recommended&amp;#34;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#63c381"&gt;&amp;#34;plugin:react/recommended&amp;#34;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#63c381"&gt;&amp;#34;plugin:@typescript-eslint/recommended&amp;#34;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#63c381"&gt;&amp;#34;eslint-config-prettier&amp;#34;&lt;/span&gt; &lt;span style="color:#8a93a5;font-style:italic"&gt;// prettier 必须放在最后，用于关闭与 Prettier 冲突的 ESLint 规则
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#abb2bf"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#76a9f9"&gt;&amp;#34;plugins&amp;#34;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;:&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;[&lt;/span&gt;&lt;span style="color:#63c381"&gt;&amp;#34;prettier&amp;#34;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#76a9f9"&gt;&amp;#34;rules&amp;#34;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;:&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#76a9f9"&gt;&amp;#34;prettier/prettier&amp;#34;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;:&lt;/span&gt; &lt;span style="color:#63c381"&gt;&amp;#34;error&amp;#34;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;,&lt;/span&gt; &lt;span style="color:#8a93a5;font-style:italic"&gt;// 将 Prettier 格式化问题报告为 ESLint 错误
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#76a9f9"&gt;&amp;#34;react/react-in-jsx-scope&amp;#34;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;:&lt;/span&gt; &lt;span style="color:#63c381"&gt;&amp;#34;off&amp;#34;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#76a9f9"&gt;&amp;#34;@typescript-eslint/no-unused-vars&amp;#34;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;:&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;[&lt;/span&gt;&lt;span style="color:#63c381"&gt;&amp;#34;error&amp;#34;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;,&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;{&lt;/span&gt; &lt;span style="color:#76a9f9"&gt;&amp;#34;argsIgnorePattern&amp;#34;&lt;/span&gt;&lt;span style="color:#abb2bf"&gt;:&lt;/span&gt; &lt;span style="color:#63c381"&gt;&amp;#34;^_&amp;#34;&lt;/span&gt; &lt;span style="color:#abb2bf"&gt;}]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#abb2bf"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#abb2bf"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;注意&lt;/strong&gt;：&lt;code&gt;eslint-config-prettier&lt;/code&gt; 必须放在 &lt;code&gt;extends&lt;/code&gt; 数组的&lt;strong&gt;最后一位&lt;/strong&gt;！否则它会覆盖其他规则，让你的 Prettier 配置失效。同理，&lt;code&gt;eslint-plugin-prettier&lt;/code&gt; 建议配合 &lt;code&gt;eslint-config-prettier&lt;/code&gt; 使用，否则可能重复检查。&lt;/p&gt;</description></item><item><title>第37章 CI/CD与自动化</title><link>https://before80.github.io/prgms/Js/frameworks/react/Chapter-37-CI-CD-and-Automation/</link><pubDate>Wed, 25 Mar 2026 12:56:00 +0800</pubDate><guid>https://before80.github.io/prgms/Js/frameworks/react/Chapter-37-CI-CD-and-Automation/</guid><description>&lt;h1 id="chapter-37---cicd-与自动化"&gt;Chapter-37 - CI/CD 与自动化&lt;/h1&gt;
&lt;h2 id="371-github-actions"&gt;37.1 GitHub Actions&lt;/h2&gt;
&lt;h3 id="3711-cicd-的概念"&gt;37.1.1 CI/CD 的概念&lt;/h3&gt;
&lt;p&gt;在没有 CI/CD 的年代，开发者手动打包、上传服务器、盯着日志——听起来像远古 rituals，实际上也没好到哪里去。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;CI（Continuous Integration，持续集成）&lt;/strong&gt;：你的代码每次 push 到仓库，自动化流水线立即启动——安装依赖、运行测试、构建产物。任何一个人提交的代码有问题，都会第一时间暴露，而不是等到上线前夜才发现一团乱麻。&lt;/p&gt;</description></item><item><title>第38章 React未来展望</title><link>https://before80.github.io/prgms/Js/frameworks/react/Chapter-38-React-Future-Outlook/</link><pubDate>Wed, 25 Mar 2026 12:56:00 +0800</pubDate><guid>https://before80.github.io/prgms/Js/frameworks/react/Chapter-38-React-Future-Outlook/</guid><description>&lt;h1 id="chapter-38---react-未来展望"&gt;Chapter-38 - React 未来展望&lt;/h1&gt;
&lt;h2 id="381-react-compiler实验性"&gt;38.1 React Compiler（实验性）&lt;/h2&gt;
&lt;h3 id="3811-自动记忆化的编译器原理"&gt;38.1.1 自动记忆化的编译器原理&lt;/h3&gt;
&lt;p&gt;React Compiler（最初代号 React Forget）是一个实验性编译器，能够在编译时自动识别可以安全 memoize 的代码片段，插入 &lt;code&gt;useMemo&lt;/code&gt; / &lt;code&gt;useCallback&lt;/code&gt;，让你从&amp;quot;手动优化地狱&amp;quot;中解放出来。&lt;/p&gt;</description></item></channel></rss>