<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Feichuan&apos;s Blog</title><description>Frontend developer blog sharing tutorials on JavaScript, React, Astro, AI development, and web technologies. Learn about modern frontend development, streaming rendering, and more.</description><link>https://feichuans.com/</link><language>zh-CN</language><item><title>Buffin Assistant 过程区折叠设计</title><link>https://feichuans.com/blogs/02-projects/eyrie/buffin-assistant-%E8%BF%87%E7%A8%8B%E5%8C%BA%E6%8A%98%E5%8F%A0%E8%AE%BE%E8%AE%A1/</link><guid isPermaLink="true">https://feichuans.com/blogs/02-projects/eyrie/buffin-assistant-%E8%BF%87%E7%A8%8B%E5%8C%BA%E6%8A%98%E5%8F%A0%E8%AE%BE%E8%AE%A1/</guid><description>For future Claude 这页沉淀 Buffin 桌面端「assistant 回复过程区折叠」的最终设计（2026 08 08，经 Deepseek V4 Flash 设计 + Claude Opus 5 独立评审交叉验证，代码证据抽查属实）。核心：无协议层 phase 时用「尾部反向扫」判定正文…</description><pubDate>Sat, 08 Aug 2026 07:24:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;for-future-claude&quot;&gt;For future Claude&lt;/h2&gt;
&lt;p&gt;这页沉淀 Buffin 桌面端「assistant 回复过程区折叠」的最终设计（2026-08-08，经 Deepseek V4 Flash 设计 + Claude Opus 5 独立评审交叉验证，代码证据抽查属实）。核心：无协议层 phase 时用「尾部反向扫」判定正文区，异常/中断路径不折叠，纯前端实现。实现此功能或讨论 session 折叠/分层呈现时先读这页，与 [[Codex App 过程输出与最终回答分层]] 对照。&lt;/p&gt;
&lt;h1 id=&quot;buffin-assistant-过程区折叠设计&quot;&gt;Buffin Assistant 过程区折叠设计&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;[!abstract] 当前结论
折叠单位是&lt;strong&gt;单条 assistant 消息内部&lt;/strong&gt;：尾部正文（narrative）始终展开，之前的过程区（reasoning / 中间文本 / 工具调用 / control-receipt）折叠为一行 ToolGroup 风格摘要。正文判定用&lt;strong&gt;尾部反向扫&lt;/strong&gt;（不是「最后一个 text part」）。仅正常完成（status=completed）且开关开启时自动折叠；interrupted / failed / 待响应交互禁止折叠。纯前端，不改 @buffin/api / daemon / provider。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;需求演进用户原话要点&quot;&gt;需求演进（用户原话要点）&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;「session 单次会话结束的时候，把上面输出合并成一小块，输出一个总结，类似 CodeX 分层回答」&lt;/li&gt;
&lt;li&gt;「只把最后一次，状态变更成已完成时，把最后一次以外的内容进行折叠，纯前端」&lt;/li&gt;
&lt;li&gt;「做成设置项，可能是一个开关」&lt;/li&gt;
&lt;li&gt;最终澄清：「折叠的是 assistant 回复，不是 user 回复。assistant 回复有工具调用、思考、正文输出，最后一段正文最长最有价值。把上面的输出折叠，就像现有 ToolGroup 一样，用户可收缩展开。纯前端展示，不需要派生新的数据模型」&lt;/li&gt;
&lt;li&gt;补充：「还要考虑错误情况——用户手动暂停或出错时，折叠行为应该怎样」&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;已知客观事实代码证据&quot;&gt;已知客观事实（代码证据）&lt;/h2&gt;
&lt;h3 id=&quot;正文判定的三种失效形状claude-评审发现抽查属实&quot;&gt;正文判定的三种失效形状（Claude 评审发现，抽查属实）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;run 以 tool-call 结尾&lt;/strong&gt;：&lt;code&gt;mapTurnStatus&lt;/code&gt;（apps/daemon/src/agent/providers/codex/protocol.ts:774-779）对 unknown/inProgress 一律判 &lt;code&gt;failed&lt;/code&gt;，中断/失败 run 常以工具收尾 → 「最后一个 text part」是中间文本，语义反了&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;零 text part&lt;/strong&gt;：&lt;code&gt;handleControlCompleted&lt;/code&gt;（session-store.ts:451-482）无 open message 时新建只含 control-receipt 的 complete message → 正文区为空，整条被藏&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;late delta&lt;/strong&gt;：&lt;code&gt;run.completed&lt;/code&gt; 后迟到事件仍被 reduce（session-runtime-store.ts:102-111 无 terminal gate）→ 新建 text part 使原正文塌进折叠区&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;status-链路现状&quot;&gt;status 链路现状&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;三个 provider（codex/claude/scripted）全部发送 &lt;code&gt;run.completed&lt;/code&gt; 的 status，类型为必填 4 值 union（apps/daemon/src/agent/types.ts:589-591；发出点 protocol.ts:283、translator.ts:358、scripted/runner.ts:106/215）&lt;/li&gt;
&lt;li&gt;wire 契约已有 &lt;code&gt;status?: string&lt;/code&gt;（packages/api/src/session-events.ts:41），&lt;strong&gt;协议包不用改&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;前端丢弃点：&lt;code&gt;handleRunCompleted(state, _event, ...)&lt;/code&gt;（session-store.ts:199-219）形参 &lt;code&gt;_event&lt;/code&gt; 从未解引用，所有 message 一律标 &lt;code&gt;complete&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;陷阱①：&lt;code&gt;interrupted&lt;/code&gt; 混合用户中断与进程崩溃（drizzle-repository.ts:114-120 把 crashed 和 interrupted 都映到 Interrupted，仅 &lt;code&gt;reason&lt;/code&gt; 能区分）&lt;/li&gt;
&lt;li&gt;陷阱②：中断不发 &lt;code&gt;input.resolved&lt;/code&gt;（service.ts:1196-1199），前端 &lt;code&gt;inputAction&lt;/code&gt; 永久停在 &lt;code&gt;pending&lt;/code&gt; —— 待响应判定必须用 message 终态短路，而非仅 &lt;code&gt;isRunning&lt;/code&gt;（deriveSessionDomain 已有同款先例 session-domain.ts:19-24）&lt;/li&gt;
&lt;li&gt;手动中断链路完整：use-session-actions.ts:48 → interruptCurrentRun → terminateAndBroadcast(run.id, ‘interrupted’)（service.ts:1200）；&lt;strong&gt;pause/resume 不存在&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;组件现状&quot;&gt;组件现状&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ToolRowBase&lt;/code&gt; 受控/非受控双支持、懒挂载 + 关闭动画保挂载（ToolRowBase.tsx:55-69），6 例权威测试&lt;/li&gt;
&lt;li&gt;折叠动效用 Base UI Collapsible + CSS 高度过渡（styles/index.css:184-194），&lt;strong&gt;不是 framer-motion AnimatePresence&lt;/strong&gt;（后者只用于消息列表 SessionThread.tsx:80）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;useAutoOpenDisclosure&lt;/code&gt;（use-auto-open-disclosure.ts:8-10）只有 &lt;code&gt;setOpen(true)&lt;/code&gt;，&lt;strong&gt;只能自动开不能自动关&lt;/strong&gt;，且 &lt;code&gt;userToggledRef&lt;/code&gt; 是 per-mount（切 tab 丢 override）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PartGroup&lt;/code&gt; 的 tool-group 变体没有 &lt;code&gt;partIndex&lt;/code&gt;（SessionThread.tsx:669），而 text/reasoning 有（:654/:663）——按 partIndex 切分需先补齐&lt;/li&gt;
&lt;li&gt;&lt;code&gt;findActiveNarrativePartIndex&lt;/code&gt;（thread-presentation.ts:47-60）是从末尾反扫找 narrative part 的现成先例&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;设计决策&quot;&gt;设计决策&lt;/h2&gt;
&lt;h3 id=&quot;1-折叠单位与判定尾部反向扫&quot;&gt;1. 折叠单位与判定：尾部反向扫&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;过程区（可折叠）           正文区（始终展开）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;reasoning / 中间text /     →   尾部连续 narrative&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;tool-call × N / receipts&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;判定：从 parts 末尾反扫，遇非 text/reasoning 即停；&lt;strong&gt;若尾部第一个就不是 narrative，整个过程区不折叠&lt;/strong&gt;（安全默认，覆盖 tool-call 结尾、零 text、late delta 三种失效形状）。与 &lt;code&gt;findActiveNarrativePartIndex&lt;/code&gt; 同构，零新概念。&lt;/p&gt;
&lt;h3 id=&quot;2-触发条件&quot;&gt;2. 触发条件&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;自动折叠 ⇔ message 终态 = completed ∧ 开关 on ∧ 无待响应交互 ∧ 尾部为 narrative&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;interrupted&lt;/code&gt; / &lt;code&gt;failed&lt;/code&gt; → 不折叠，保留错误上下文（对齐 Codex App 的 &lt;code&gt;isTurnCancelled → shouldAllowCollapse: false&lt;/code&gt;，见 [[Codex App 过程输出与最终回答分层]]）&lt;/li&gt;
&lt;li&gt;待响应 ask-user/approval（复用 &lt;code&gt;isPendingInteraction&lt;/code&gt;，session-domain.ts:55-59）→ 不折叠；注意渲染侧 &lt;code&gt;?? &apos;pending&apos;&lt;/code&gt; 兜底（SessionThread.tsx:289/316），undefined 必须同默认，否则待响应表单被折叠&lt;/li&gt;
&lt;li&gt;纯文本回复（过程区为空）→ 不渲染折叠块，退化为现状&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;3-组件与动画&quot;&gt;3. 组件与动画&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;同级复用 &lt;code&gt;ToolRowBase&lt;/code&gt;（不包 ToolGroup），header 显示统计摘要（命令数 / 文件数 / 耗时，result 缺失按完成计，过滤 &lt;code&gt;status !== &apos;completed&apos;&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;折叠动画：Base UI Collapsible + CSS 高度过渡&lt;/li&gt;
&lt;li&gt;冲突处理：ToolRowBase 首次展开才挂载 → 默认折叠时过程区 MarkdownPart 从未挂载，&lt;code&gt;usePlaybackBuffer&lt;/code&gt; 的 catch-up 会在完成帧硬切（影响限于 run 刚结束一帧）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;4-状态与开关&quot;&gt;4. 状态与开关&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;折叠状态放 &lt;strong&gt;SessionRuntimeStore&lt;/strong&gt;（同 composerText 待遇，跨 tab 存活 override）；rollback resync 重建消息时 GC（session-runtime-store.ts:94-100）&lt;/li&gt;
&lt;li&gt;开关 &lt;code&gt;autoCollapseTurns&lt;/code&gt;（默认 on）：存 &lt;code&gt;device-chrome-store&lt;/code&gt;（现成订阅层）或 &lt;code&gt;prefs&lt;/code&gt; 补订阅层；&lt;strong&gt;关闭时追溯展开&lt;/strong&gt;已自动折叠的区域&lt;/li&gt;
&lt;li&gt;手动展开/收起优先级高于开关（user override 恒胜）&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;与-codex-协议层-phase-方案的关系&quot;&gt;与 Codex 协议层 phase 方案的关系&lt;/h2&gt;



































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;维度&lt;/th&gt;&lt;th&gt;Codex App（[[Codex App 过程输出与最终回答分层]]）&lt;/th&gt;&lt;th&gt;Buffin 本方案&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;分层依据&lt;/td&gt;&lt;td&gt;协议层 &lt;code&gt;agentMessage.phase = commentary | final_answer&lt;/code&gt;&lt;/td&gt;&lt;td&gt;呈现层「尾部反向扫」位置判定&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;折叠时机&lt;/td&gt;&lt;td&gt;final answer 首个 item 开始&lt;/td&gt;&lt;td&gt;message 正常完成后&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;依赖&lt;/td&gt;&lt;td&gt;需要 provider 支持 phase（Claude 等不保证）&lt;/td&gt;&lt;td&gt;零协议依赖，全 provider 一致&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;异常路径&lt;/td&gt;&lt;td&gt;turn cancelled 不折叠&lt;/td&gt;&lt;td&gt;interrupted/failed 不折叠（同源语义）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;成本&lt;/td&gt;&lt;td&gt;provider 归一化 + phase 持久化&lt;/td&gt;&lt;td&gt;前端一行 status 恢复 + 纯派生&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;两者不冲突：本方案是 phase 缺失时的替代路径；若未来接入 phase，折叠时机可提前到 final answer 开始，判定降级为增强而非必需。&lt;/p&gt;
&lt;h2 id=&quot;边界情况清单&quot;&gt;边界情况清单&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;纯文本回复：不折叠，退化为现状&lt;/li&gt;
&lt;li&gt;run 以 tool-call 结尾 / 零 text part：不折叠&lt;/li&gt;
&lt;li&gt;truncated 工具输出（session-store.ts:23）：在折叠 header 提示&lt;/li&gt;
&lt;li&gt;滚动跳变：&lt;code&gt;use-auto-scroll-bottom&lt;/code&gt; 按 scrollHeight 判 following（:115），折叠使其骤减，需复核&lt;/li&gt;
&lt;li&gt;rollback resync：按 messageId 存的折叠态需 GC&lt;/li&gt;
&lt;li&gt;AskUserTool 中断后仍渲染可���交表单（SessionThread.tsx:286-299 未 gate 终态，既有问题会被「pending 不折叠」放大）&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;实施范围&quot;&gt;实施范围&lt;/h2&gt;
&lt;p&gt;纯前端：&lt;code&gt;SessionThread.tsx&lt;/code&gt;（折叠容器 + header）、&lt;code&gt;session-store.ts&lt;/code&gt;（恢复终态 status）、settings 新条目、i18n（en/zh-Hans/zh-Hant）。对应 GitHub issue：#215（buffin-ai/buffin）。&lt;/p&gt;
&lt;h2 id=&quot;相关页面&quot;&gt;相关页面&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[Codex App 过程输出与最终回答分层]]&lt;/li&gt;
&lt;li&gt;[[Buffin Session 呈现两轴模型]]&lt;/li&gt;
&lt;li&gt;[[流式 UI 的数据完成态与播放完成态分离]]&lt;/li&gt;
&lt;li&gt;[[Eyrie Agent Session UI 组件设计]]&lt;/li&gt;
&lt;li&gt;[[Eyrie Session UI 优化方案]]&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;来源&quot;&gt;来源&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Deepseek V4 Flash 设计 agent（herdr w19，2026-08-06，只读调研 + 4 项修订）&lt;/li&gt;
&lt;li&gt;Claude Opus 5 独立评审（herdr w19，plan 只读模式，2026-08-08，NOT READY 后修正，评审全文写入 ~/.claude/plans/agent-claude-code-buffin-stateful-tiger.md）&lt;/li&gt;
&lt;li&gt;Buffin 源码抽查（session-store.ts / thread-presentation.ts / SessionThread.tsx / use-auto-scroll-bottom.ts / protocol.ts / translator.ts / runner.ts / drizzle-repository.ts / service.ts，2026-08-08）&lt;/li&gt;
&lt;li&gt;GitHub issue buffin-ai/buffin#215&lt;/li&gt;
&lt;li&gt;[[Buffin Session 界面性能]] — 折叠已落地，但 mountChildren + keepMounted 让折叠内容仍占 DOM&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>buffin</category><category>eyrie</category><category>agent-ui</category><category>collapse</category><category>frontend</category><category>streaming</category></item><item><title>MengTo Skills Handbook</title><link>https://feichuans.com/blogs/03-areas/ai/mengto-skills-handbook/</link><guid isPermaLink="true">https://feichuans.com/blogs/03-areas/ai/mengto-skills-handbook/</guid><description>For future Claude 这页是 MengTo/Skills 的本机使用手册：定义、场景、调用方法、流水线、118 个 skill 全表、安装落点与验收标准。2026 07 29 已全量装入 /.agents/skills / Pi / Claude。需要选设计/复刻/动效/游戏类 skill、或…</description><pubDate>Thu, 30 Jul 2026 01:20:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;for-future-claude&quot;&gt;For future Claude&lt;/h2&gt;
&lt;p&gt;这页是 &lt;a href=&quot;https://github.com/MengTo/Skills&quot;&gt;MengTo/Skills&lt;/a&gt; 的本机使用手册：定义、场景、调用方法、流水线、118 个 skill 全表、安装落点与验收标准。2026-07-29 已全量装入 &lt;code&gt;~/.agents/skills&lt;/code&gt; / Pi / Claude。需要选设计/复刻/动效/游戏类 skill、或把参考变成可执行 prompt 时先读本页。它解决「知道好看，但 agent 做不稳」的问题，不是通用工程流水线（工程流看 [[Matt Pocock Skills 使用手册]]）。&lt;/p&gt;
&lt;h1 id=&quot;mengto-skills-handbook&quot;&gt;MengTo Skills Handbook&lt;/h1&gt;
&lt;h2 id=&quot;一句话定义&quot;&gt;一句话定义&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;MengTo/Skills&lt;/strong&gt; 是一组面向 &lt;strong&gt;设计师 + builder + AI coding agent&lt;/strong&gt; 的 &lt;strong&gt;操作手册（SOP）库&lt;/strong&gt;。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;每个 skill = 一个文件夹 + 必选 &lt;code&gt;SKILL.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;目标：把「好提示词 / 抓取流程 / 实现套路 / 审美约束」固化成可重复执行的版本化文件&lt;/li&gt;
&lt;li&gt;适用 agent：&lt;strong&gt;Codex / Claude / Cursor / Pi / 其他&lt;/strong&gt; 只要能加载 &lt;code&gt;SKILL.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;仓库定位不是「装完就变强的插件」，而是 &lt;strong&gt;任务路由到对应 runbook，再按输出合同交付&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;官方仓库：&lt;a href=&quot;https://github.com/MengTo/Skills&quot;&gt;https://github.com/MengTo/Skills&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;与其他-skill-体系的边界&quot;&gt;与其他 skill 体系的边界&lt;/h2&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;体系&lt;/th&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;strong&gt;MengTo/Skills&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;设计方向、参考复刻、落地页/动效/WebGL、可玩网页游戏、灵感资产生产&lt;/td&gt;&lt;td&gt;视觉与交互质量、从参考到 prompt/实现&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;[[Matt Pocock Skills 使用手册]]&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;grill → spec → tickets → implement / TDD / review&lt;/td&gt;&lt;td&gt;工程需求澄清、架构、实现闭环&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;[[pi-skills-handbook]]&lt;/strong&gt; / [[Agent Skills 与 SKILL.md 工作流]]&lt;/td&gt;&lt;td&gt;Pi/通用 skill 机制与本机能力地图&lt;/td&gt;&lt;td&gt;先理解 skill 系统本身&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;不要混用场景：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;做 CRUD / 修 bug / 写后端契约 → Matt / 工程 skill&lt;/li&gt;
&lt;li&gt;做 Awwwards 级站、GSAP 叙事、Three.js 小游戏、视频转 superprompt → MengTo&lt;/li&gt;
&lt;li&gt;两边可串联：先用 Matt 把产品边界问清，再用 MengTo 做视觉与交互实现&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&quot;哲学作者四条决定怎么用&quot;&gt;哲学（作者四条，决定怎么用）&lt;/h2&gt;
&lt;p&gt;来源：&lt;a href=&quot;https://github.com/MengTo/Skills/blob/main/README.md&quot;&gt;README Philosophy&lt;/a&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Prompts are assets&lt;/strong&gt; — 好 prompt 存文件、版本化，不当一次性聊天。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Specs beat vibes&lt;/strong&gt; — 约束、层级、「一次只改 1–2 件事」优于模糊审美。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;References beat paragraphs&lt;/strong&gt; — 截图/视频比长描述更能携带字体、间距、节奏。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Skills are operating procedures&lt;/strong&gt; — 写清何时用、先做什么、默认值、别踩什么坑。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Agent 使用时的翻译：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;不要「参考一下 skill 写点东西」&lt;/li&gt;
&lt;li&gt;要「严格按 skill 的 workflow + quality bar 跑完并验收」&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&quot;本机安装状态2026-07-29-核验&quot;&gt;本机安装状态（2026-07-29 核验）&lt;/h2&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;源 skill 数&lt;/td&gt;&lt;td&gt;&lt;strong&gt;118&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;~/.agents/skills&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;118/118&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Pi &lt;code&gt;~/.pi/agent/skills&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;118/118&lt;/strong&gt; 链接&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Claude &lt;code&gt;~/.claude/skills&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;118/118&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;本地缓存副本&lt;/td&gt;&lt;td&gt;&lt;code&gt;~/.cache/mengto-skills&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Eve / PromptScript&lt;/td&gt;&lt;td&gt;不支持 global，跳过&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;~/.codex/skills&lt;/code&gt; / &lt;code&gt;~/.cursor/skills&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;未单独落点&lt;/strong&gt;（CLI 全局安装未完整写入这两处）&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;分类计数（以本机缓存 &lt;code&gt;agent-skills/**/SKILL.md&lt;/code&gt; 为准）：&lt;/p&gt;








































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;分类&lt;/th&gt;&lt;th align=&quot;right&quot;&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;strong&gt;web-design&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;79&lt;/td&gt;&lt;td&gt;落地页、风格系统、动效、WebGL、布局细节&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;game-development&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;19&lt;/td&gt;&lt;td&gt;Three.js/可玩网页游戏系统与 QA&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;codex&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;17&lt;/td&gt;&lt;td&gt;采集、复刻、审计、迭代验证、内容生产工作流&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;media&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;2&lt;/td&gt;&lt;td&gt;图库选图&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;ui&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;1&lt;/td&gt;&lt;td&gt;设计优先 prompt 结构&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;合计&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;&lt;strong&gt;118&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;安装命令（本机实际路径）：&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 网络直装不稳定时可先浅克隆&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;git&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; clone&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --depth&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; https://github.com/MengTo/Skills.git&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; ~/.cache/mengto-skills&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;npx&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; skills&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; add&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; ~/.cache/mengto-skills&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -g&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --all&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --full-depth&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;直装等价写法：&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;npx&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; skills&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; add&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; MengTo/Skills&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -g&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --all&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --full-depth&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;更新：&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;npx&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; skills&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; update&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -g&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -y&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 或重装缓存副本&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;注意：本机已有 &lt;code&gt;gsap-core&lt;/code&gt; 等 GSAP 系列 skill；MengTo 的实现 skill 名是 &lt;strong&gt;&lt;code&gt;gsap&lt;/code&gt;&lt;/strong&gt;，二者并存，不互相覆盖。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&quot;文件夹契约&quot;&gt;文件夹契约&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;agent-skills/&amp;#x3C;category&gt;/&amp;#x3C;skill-name&gt;/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  SKILL.md        # 必选：frontmatter + workflow&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  REFERENCES.md   # 可选：只放链接&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ARTICLE.md      # 可选：长文解释&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  assets/         # 可选&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  scripts/        # 可选&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  demo/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    index.html    # 可运行 demo&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    PROMPT.md     # 复刻/remix 提示&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;约定：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;agent &lt;strong&gt;只把 &lt;code&gt;SKILL.md&lt;/code&gt; 当执行入口&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;REFERENCES.md&lt;/code&gt; 不塞进 workflow 正文&lt;/li&gt;
&lt;li&gt;视觉 skill 常带 &lt;code&gt;demo/&lt;/code&gt;，可先看 demo 再实现&lt;/li&gt;
&lt;li&gt;skill 应 &lt;strong&gt;portable&lt;/strong&gt;：无密钥、无私有路径、不绑定某个客户仓库&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&quot;正确使用方法&quot;&gt;正确使用方法&lt;/h2&gt;
&lt;h3 id=&quot;核心心智3-条&quot;&gt;核心心智（3 条）&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Skill = 场景路由 + 作业流程&lt;/strong&gt;，不是百科。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;一次只加载最窄的 1 个&lt;/strong&gt;，或一条明确流水线；禁止 118 个全塞上下文。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;你提供触发条件与输入物；skill 负责步骤、默认值、输出合同与验收。&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;方法-a单-skill-触发最常用&quot;&gt;方法 A：单 skill 触发（最常用）&lt;/h3&gt;
&lt;p&gt;模板：&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;严格按 `&amp;#x3C;skill-name&gt;` 执行。&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;输入：&amp;#x3C;视频/URL/HTML/截图/当前仓库文件&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;目标：exact recreation | inspired adaptation&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;输出：按该 skill 的 Output Contract / Quality Bar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;不要泛泛总结；缺输入先列缺口再停。&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;示例：&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;严格按 video-to-superprompt 执行。&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;输入：./refs/hero-scroll.mp4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;模式：exact recreation&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;输出：单个 paste-ready superprompt + asset map&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;方法-b流水线串联设计复刻--灵感生产&quot;&gt;方法 B：流水线串联（设计复刻 / 灵感生产）&lt;/h3&gt;
&lt;p&gt;旗舰 web-design 流水线（README 推荐顺序）：&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;参考视频/站点&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  → video-to-superprompt&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  → stitched-full-page-capture&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  → html-to-interaction-prompts&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  → design-first-ui-prompting&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  → landing-page / gsap / threejs / 具体风格 skill&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;



































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;步骤&lt;/th&gt;&lt;th&gt;Skill&lt;/th&gt;&lt;th&gt;产出&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;&lt;code&gt;video-to-superprompt&lt;/code&gt;&lt;/td&gt;&lt;td&gt;可重建的超级提示词&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;&lt;code&gt;stitched-full-page-capture&lt;/code&gt;&lt;/td&gt;&lt;td&gt;全页结构证据（不只 hero）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;&lt;code&gt;html-to-interaction-prompts&lt;/code&gt;&lt;/td&gt;&lt;td&gt;分节交互 prompt 包&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;&lt;code&gt;design-first-ui-prompting&lt;/code&gt;&lt;/td&gt;&lt;td&gt;把模糊审美压成约束卡&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;实现 skill&lt;/td&gt;&lt;td&gt;真正落地代码&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;关键：&lt;strong&gt;前几步产出“可粘贴资产”，后几步才写代码。&lt;/strong&gt; 否则 agent 容易直接“凭感觉生成一个差不多的页面”。&lt;/p&gt;
&lt;h3 id=&quot;方法-c实现型-skill写修代码&quot;&gt;方法 C：实现型 skill（写/修代码）&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;用 gsap skill 修当前 hero → features 滚动叙事。&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;要求：timeline + ScrollTrigger pin + scrub&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;约束：只用 transform/opacity；React 用 gsap.context 清理；支持 reduced-motion&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;价值来源：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;When to use&lt;/li&gt;
&lt;li&gt;recipes / defaults&lt;/li&gt;
&lt;li&gt;pitfalls（性能、清理、触发器、FOUC）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;方法-d约束型-skill把审美说清楚&quot;&gt;方法 D：约束型 skill（把审美说清楚）&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;design-first-ui-prompting&lt;/code&gt; 强制结构：&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;GOAL → FORMAT → LAYOUT → TYPE → COLOR → COPY → CONSTRAINTS → NEGATIVE&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;规则：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;先锁定 layout + hierarchy + copy&lt;/li&gt;
&lt;li&gt;变体 &lt;strong&gt;一次只改 1–2 个变量&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;排版不稳就 2-pass（先无字生成，再人工/Figma 排版）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;方法-e日常灵感资产生产&quot;&gt;方法 E：日常灵感资产生产&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;按 daily-ui-inspiration-capture 跑今天的包&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;输出目录：articles/YYYY-MM-DD-ui-inspiration-capture/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;必须 5 个 references + full-page + section crops + motion frames&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;后续可接：&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;build-daily-inspiration-sites&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;把 5 个参考变成 5 个原创 Sites 构建任务。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;三类-skill-的使用差异&quot;&gt;三类 skill 的使用差异&lt;/h2&gt;



































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;类型&lt;/th&gt;&lt;th&gt;例子&lt;/th&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;strong&gt;工作流 skill&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;daily-ui-inspiration-capture&lt;/code&gt;、&lt;code&gt;video-to-superprompt&lt;/code&gt;&lt;/td&gt;&lt;td&gt;“按 workflow 跑一遍”&lt;/td&gt;&lt;td&gt;固定目录/固定格式资产&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;规范 skill&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;landing-page&lt;/code&gt;、&lt;code&gt;design-first-ui-prompting&lt;/code&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;实现 skill&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;gsap&lt;/code&gt;、&lt;code&gt;threejs&lt;/code&gt;、&lt;code&gt;tailwindcss&lt;/code&gt;&lt;/td&gt;&lt;td&gt;“按 recipes + pitfalls 实现/修”&lt;/td&gt;&lt;td&gt;代码模式 + 性能/清理约束&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;风格系统 skill&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;dark-glass-clean-layout&lt;/code&gt;、&lt;code&gt;editorial-tech&lt;/code&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;hr&gt;
&lt;h2 id=&quot;场景路由表先查这张&quot;&gt;场景路由表（先查这张）&lt;/h2&gt;





















































































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;你现在要做的事&lt;/th&gt;&lt;th&gt;首选 skill&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;/td&gt;&lt;td&gt;&lt;code&gt;video-to-superprompt&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;stitched-full-page-capture&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;已有 HTML → 分拆交互 prompt&lt;/td&gt;&lt;td&gt;&lt;code&gt;html-to-interaction-prompts&lt;/code&gt;&lt;/td&gt;&lt;td&gt;各实现 skill&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;只截到 hero，结构不全&lt;/td&gt;&lt;td&gt;&lt;code&gt;stitched-full-page-capture&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;daily-ui-inspiration-capture&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;每日灵感采集&lt;/td&gt;&lt;td&gt;&lt;code&gt;daily-ui-inspiration-capture&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;build-daily-inspiration-sites&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;高转化单页落地&lt;/td&gt;&lt;td&gt;&lt;code&gt;landing-page&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;pricing-page&lt;/code&gt;、&lt;code&gt;product-proof-saas&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;提示词太虚、出图不稳&lt;/td&gt;&lt;td&gt;&lt;code&gt;design-first-ui-prompting&lt;/code&gt;&lt;/td&gt;&lt;td&gt;风格系统 skill&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Awwwards/作品集级整站&lt;/td&gt;&lt;td&gt;&lt;code&gt;build-awwwards-quality-sites&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;cinematic-gsap-lenis-motion-system&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;GSAP 时间轴/滚动&lt;/td&gt;&lt;td&gt;&lt;code&gt;gsap&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;gsap-scrolltrigger-storytelling&lt;/code&gt;、&lt;code&gt;animation-systems&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Three.js / WebGL&lt;/td&gt;&lt;td&gt;&lt;code&gt;threejs&lt;/code&gt;、&lt;code&gt;webgl-landing-steering&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;vantajs&lt;/code&gt;、&lt;code&gt;globe-gl&lt;/code&gt;、&lt;code&gt;unicorn-studio&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;可玩网页游戏&lt;/td&gt;&lt;td&gt;&lt;code&gt;build-isometric-arpg&lt;/code&gt;&lt;/td&gt;&lt;td&gt;敌人/关卡/音频/QA 子系统&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;动效性能差&lt;/td&gt;&lt;td&gt;&lt;code&gt;optimize-web-animations&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;optimize-threejs-games&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;任务要反复验证直到过线&lt;/td&gt;&lt;td&gt;&lt;code&gt;iterate-until-verified&lt;/code&gt;&lt;/td&gt;&lt;td&gt;具体领域 skill&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;选营销图&lt;/td&gt;&lt;td&gt;&lt;code&gt;unsplash-asset-images&lt;/code&gt; / &lt;code&gt;aura-asset-images&lt;/code&gt;&lt;/td&gt;&lt;td&gt;—&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;写像 Meng 的 X 帖&lt;/td&gt;&lt;td&gt;&lt;code&gt;write-like-meng-on-x&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;x-bookmark-quote-posts&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;审查是否抄参考太狠&lt;/td&gt;&lt;td&gt;&lt;code&gt;audit-reference-originality&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;generate-reference-inspired-brand-worlds&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id=&quot;旗舰-skill-深读&quot;&gt;旗舰 skill 深读&lt;/h2&gt;
&lt;h3 id=&quot;1-video-to-superprompt&quot;&gt;1) &lt;code&gt;video-to-superprompt&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;何时用：&lt;/strong&gt; 用户给了视频/录屏/链接，要求分析设计、动效、滚动、字体、WebGL，或生成可复刻 prompt。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;工作流摘要：&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;定位源视频（本地/URL/上传）；不可访问就先停&lt;/li&gt;
&lt;li&gt;技术检查：&lt;code&gt;ffprobe&lt;/code&gt; + &lt;code&gt;ffmpeg&lt;/code&gt; 抽关键帧&lt;/li&gt;
&lt;li&gt;分层分析：故事 / 布局 / 运动 / 视觉 / 技术栈 / a11y·性能&lt;/li&gt;
&lt;li&gt;资产地图（URL / 本地名 / 占位）&lt;/li&gt;
&lt;li&gt;写 superprompt（默认单个 fenced text 块）&lt;/li&gt;
&lt;li&gt;验证路径与代表性帧&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;输出模式：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Prompt only&lt;/li&gt;
&lt;li&gt;Article&lt;/li&gt;
&lt;li&gt;Implementation brief&lt;/li&gt;
&lt;li&gt;Asset-generation pack&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;质量线：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;不看原视频也能重建&lt;/li&gt;
&lt;li&gt;运动机制要写死：pin、scrub、&lt;code&gt;video.currentTime&lt;/code&gt;、mask、shader 等&lt;/li&gt;
&lt;li&gt;每次都写 mobile + reduced-motion&lt;/li&gt;
&lt;li&gt;明确 anti-patterns（通用 SaaS 段、装饰 blob、错误的 autoplay 等）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;来源：&lt;code&gt;agent-skills/codex/video-to-superprompt/SKILL.md&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&quot;2-landing-page&quot;&gt;2) &lt;code&gt;landing-page&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;核心判断：&lt;/strong&gt; Landing page ≠ Homepage。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Homepage：多意图&lt;/li&gt;
&lt;li&gt;Landing page：&lt;strong&gt;一个 offer → 一个受众 → 一个主行动&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;开工前必须收集：&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;页面目的 / 主 CTA / 转化定义&lt;/li&gt;
&lt;li&gt;ICP、问题、前 3 个异议、流量来源、先验知识&lt;/li&gt;
&lt;li&gt;证明材料与资产&lt;/li&gt;
&lt;li&gt;品牌语气与设计方向&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;默认结构：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Above the fold：标题 / 副标 / 主 CTA / 一条证明 / Hero 视觉&lt;/li&gt;
&lt;li&gt;Mid：问题→方案 / 利益点 / How it works / 社会证明&lt;/li&gt;
&lt;li&gt;Bottom：FAQ / 风险逆转 / 最终 CTA&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;来源：&lt;code&gt;agent-skills/web-design/landing-page/SKILL.md&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&quot;3-design-first-ui-prompting&quot;&gt;3) &lt;code&gt;design-first-ui-prompting&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;核心原则：&lt;/strong&gt; Prompt like a design system, not a wish.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;迭代规则：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;第一稿锁定 layout + hierarchy + copy&lt;/li&gt;
&lt;li&gt;variants 只改一个变量：angle / accent / card arrangement / background&lt;/li&gt;
&lt;li&gt;保留本地 reference pack，不要让模型“记住品味”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;来源：&lt;code&gt;agent-skills/ui/design-first-ui-prompting/SKILL.md&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&quot;4-daily-ui-inspiration-capture&quot;&gt;4) &lt;code&gt;daily-ui-inspiration-capture&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;不是&lt;/strong&gt;截图倾倒，而是 &lt;strong&gt;article-ready bundle&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;默认合同：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;目录：&lt;code&gt;articles/YYYY-MM-DD-ui-inspiration-capture/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;文件：&lt;code&gt;content.md&lt;/code&gt; + &lt;code&gt;manifest.json&lt;/code&gt; + 本地图片/视频&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;正好 5 个&lt;/strong&gt; final references&lt;/li&gt;
&lt;li&gt;每个 live 站：full-page + 连续 section crops + motion frames&lt;/li&gt;
&lt;li&gt;去重：对比历史 manifest 的 title/URL/image URL&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;来源：&lt;code&gt;agent-skills/codex/daily-ui-inspiration-capture/SKILL.md&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&quot;5-gsap&quot;&gt;5) &lt;code&gt;gsap&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;何时用：&lt;/strong&gt; 专业 UI 动效、时间轴编排、ScrollTrigger 叙事。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;默认偏好：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;动画 &lt;code&gt;x/y/scale/rotation/autoAlpha&lt;/code&gt;，不动画 layout 属性&lt;/li&gt;
&lt;li&gt;React/SPA 用 &lt;code&gt;gsap.context()&lt;/code&gt; 清理&lt;/li&gt;
&lt;li&gt;字体/图片稳定后再 &lt;code&gt;ScrollTrigger.refresh()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;来源：&lt;code&gt;agent-skills/web-design/gsap/SKILL.md&lt;/code&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;你给-agent-的标准说法可复制&quot;&gt;你给 agent 的标准说法（可复制）&lt;/h2&gt;
&lt;h3 id=&quot;分析参考&quot;&gt;分析参考&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;严格遵循 video-to-superprompt。&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;输入：&amp;#x3C;视频或链接&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;模式：exact recreation&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;输出：paste-ready superprompt + asset map&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;不要总结；section-by-section 写清运动机制&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;写转化页&quot;&gt;写转化页&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;用 landing-page skill。&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;先按 Before you design 问齐缺口。&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;结构按 Core structure；above the fold 只有一个主 CTA。&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;修动效&quot;&gt;修动效&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;用 gsap skill。&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;目标：hero 入场 + 中段 pin + scrub。&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;禁止 animating top/left/width/height；卸载要清理；支持 prefers-reduced-motion。&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;压提示词&quot;&gt;压提示词&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;先跑 design-first-ui-prompting，把下面描述压成完整 prompt skeleton，&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;再生成 3 个 variants，每个只改一个变量。&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;日常灵感&quot;&gt;日常灵感&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;按 daily-ui-inspiration-capture 执行今日采集。&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;输出 5 references 的完整 bundle，不要 README.md。&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2 id=&quot;全量-skill-目录118&quot;&gt;全量 skill 目录（118）&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;说明：下表 description 来自各 &lt;code&gt;SKILL.md&lt;/code&gt; frontmatter，2026-07-29 从本机缓存抽取。执行时仍以对应 &lt;code&gt;SKILL.md&lt;/code&gt; 正文为准。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;codex-工作流17&quot;&gt;Codex 工作流（17）&lt;/h3&gt;













































































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Skill&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;article-prompts-to-skills&lt;/code&gt;&lt;/td&gt;&lt;td&gt;文章/教程/prompt pack → 可复用 skill 包&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;audit-reference-originality&lt;/code&gt;&lt;/td&gt;&lt;td&gt;对照参考审原创性/抄袭风险&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;audit-verify-explain-grade-5&lt;/code&gt;&lt;/td&gt;&lt;td&gt;审计、用证据验证、用小学生能懂的话解释&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;browser-video-recording&lt;/code&gt;&lt;/td&gt;&lt;td&gt;把浏览器场景录成精致演示视频&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;build-daily-inspiration-sites&lt;/code&gt;&lt;/td&gt;&lt;td&gt;把每日灵感包变成 5 个原创 landing 构建&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;daily-ui-inspiration-capture&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;elevenlabs-tts&lt;/code&gt;&lt;/td&gt;&lt;td&gt;ElevenLabs TTS / 本地 voice profile&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;generate-reference-inspired-brand-worlds&lt;/code&gt;&lt;/td&gt;&lt;td&gt;参考视觉 → 多套原创品牌世界&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;html-to-interaction-prompts&lt;/code&gt;&lt;/td&gt;&lt;td&gt;HTML → 截图背书的交互 prompt 文&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;implement-fog-of-war&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Three.js 战争迷雾/感知系统&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;iterate-until-verified&lt;/code&gt;&lt;/td&gt;&lt;td&gt;任意重任务的执行-验证循环&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;optimize-web-animations&lt;/code&gt;&lt;/td&gt;&lt;td&gt;前端动画/Canvas/WebGL 性能优化&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;performance-profiling&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Apple 平台 Instruments/MetricKit 性能剖析&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;stitched-full-page-capture&lt;/code&gt;&lt;/td&gt;&lt;td&gt;懒加载/动效/WebGL 页的可靠全页截图&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;video-to-superprompt&lt;/code&gt;&lt;/td&gt;&lt;td&gt;参考视频 → 超详细重建 prompt&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;write-like-meng-on-x&lt;/code&gt;&lt;/td&gt;&lt;td&gt;按 Meng 语料校准 X 帖风格&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;x-bookmark-quote-posts&lt;/code&gt;&lt;/td&gt;&lt;td&gt;书签 → 有来源的 quote-post 草稿&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;media2&quot;&gt;Media（2）&lt;/h3&gt;

















&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Skill&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;aura-asset-images&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Aura Assets 选营销/设计图&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;unsplash-asset-images&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Unsplash 按场景/裁切/比例选图&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;ui1&quot;&gt;UI（1）&lt;/h3&gt;













&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Skill&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;design-first-ui-prompting&lt;/code&gt;&lt;/td&gt;&lt;td&gt;设计优先、规格驱动的 UI prompt 系统&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;game-development19&quot;&gt;Game development（19）&lt;/h3&gt;





















































































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Skill&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;author-game-levels&lt;/code&gt;&lt;/td&gt;&lt;td&gt;可读的扁平世界关卡编排&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;build-game-audio-feedback&lt;/code&gt;&lt;/td&gt;&lt;td&gt;战斗/状态/空间音频反馈&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;build-game-camera-controls&lt;/code&gt;&lt;/td&gt;&lt;td&gt;等距/跟随/遮挡/锁定/震动相机&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;build-game-changelog&lt;/code&gt;&lt;/td&gt;&lt;td&gt;游戏内 changelog 与发布 provenance&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;build-game-inventory&lt;/code&gt;&lt;/td&gt;&lt;td&gt;背包/装备/tooltip/拖拽/持久化&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;build-game-map-editor&lt;/code&gt;&lt;/td&gt;&lt;td&gt;浏览器地图编辑器&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;build-game-monster-system&lt;/code&gt;&lt;/td&gt;&lt;td&gt;怪物资产契约与集成&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;build-hybrid-game-assets&lt;/code&gt;&lt;/td&gt;&lt;td&gt;导入网格/程序化/AI 资产生成混合管线&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;build-isometric-arpg&lt;/code&gt;&lt;/td&gt;&lt;td&gt;可玩等距 ARPG 架构&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;build-mobile-threejs-games&lt;/code&gt;&lt;/td&gt;&lt;td&gt;移动端触控与安全区&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;build-threejs-enemy-systems&lt;/code&gt;&lt;/td&gt;&lt;td&gt;数据驱动敌人原型与招式&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;build-vesperfall-review-assets&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Vesperfall 资源库审查对&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;create-game-vfx&lt;/code&gt;&lt;/td&gt;&lt;td&gt;可读且性能安全的战斗 VFX&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;design-action-combat&lt;/code&gt;&lt;/td&gt;&lt;td&gt;可读战术动作战斗&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;design-game-encounters&lt;/code&gt;&lt;/td&gt;&lt;td&gt;遭遇战节奏与 boss 阶段&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;optimize-threejs-games&lt;/code&gt;&lt;/td&gt;&lt;td&gt;游戏性能剖析与优化&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;ship-web-games&lt;/code&gt;&lt;/td&gt;&lt;td&gt;打包部署与生产冒烟&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;test-playable-web-games&lt;/code&gt;&lt;/td&gt;&lt;td&gt;可玩性 E2E + 浏览器证据&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;tune-enemy-ai&lt;/code&gt;&lt;/td&gt;&lt;td&gt;仇恨/走位/招式选择与可读 telegraph&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;web-design79&quot;&gt;Web design（79）&lt;/h3&gt;
&lt;h4 id=&quot;转化与整站&quot;&gt;转化与整站&lt;/h4&gt;









































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Skill&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;build-awwwards-quality-sites&lt;/code&gt;&lt;/td&gt;&lt;td&gt;高辨识度营销/作品集整站&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;landing-page&lt;/code&gt;&lt;/td&gt;&lt;td&gt;高转化单 offer 落地页&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;pricing-page&lt;/code&gt;&lt;/td&gt;&lt;td&gt;SaaS 定价页&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;product-proof-saas&lt;/code&gt;&lt;/td&gt;&lt;td&gt;以真实工作流/界面为证明的 SaaS 页&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;operational-enterprise-ai&lt;/code&gt;&lt;/td&gt;&lt;td&gt;企业 AI/自动化/审计边界产品页&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;tailwindcss&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Tailwind 布局/字体/响应式/组件惯例&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;animation-systems&lt;/code&gt;&lt;/td&gt;&lt;td&gt;产品级动效原则与编排&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;webgl-landing-steering&lt;/code&gt;&lt;/td&gt;&lt;td&gt;WebGL 重落地页的视觉方向舵&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h4 id=&quot;运动与滚动叙事&quot;&gt;运动与滚动叙事&lt;/h4&gt;

























































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Skill&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;animation-on-scroll&lt;/code&gt;&lt;/td&gt;&lt;td&gt;IntersectionObserver 滚动显现&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;cinematic-gsap-lenis-motion-system&lt;/code&gt;&lt;/td&gt;&lt;td&gt;GSAP + ScrollTrigger + Lenis 电影感系统&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;cinematic-scroll-storytelling&lt;/code&gt;&lt;/td&gt;&lt;td&gt;滚动驱动电影感 landing&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;gsap&lt;/code&gt;&lt;/td&gt;&lt;td&gt;GSAP timeline / ScrollTrigger / stagger&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;gsap-scrolltrigger-storytelling&lt;/code&gt;&lt;/td&gt;&lt;td&gt;sticky 产品叙事&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;marquee-loop&lt;/code&gt;&lt;/td&gt;&lt;td&gt;无缝无限跑马灯&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;masked-reveal&lt;/code&gt;&lt;/td&gt;&lt;td&gt;遮罩分词显现&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;staggered-word-reveal&lt;/code&gt;&lt;/td&gt;&lt;td&gt;轻量分词上浮显现&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;scroll-progress-timeline&lt;/code&gt;&lt;/td&gt;&lt;td&gt;流程步骤滚动时间线&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;scroll-scrubbed-visual-sequence&lt;/code&gt;&lt;/td&gt;&lt;td&gt;滚动擦洗视觉序列&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;scroll-scrubbed-word-reveal&lt;/code&gt;&lt;/td&gt;&lt;td&gt;滚动进度驱动逐词显现&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;scroll-world-storytelling&lt;/code&gt;&lt;/td&gt;&lt;td&gt;长文/案例 → 滚动世界故事页&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h4 id=&quot;webgl--canvas--3d&quot;&gt;WebGL / Canvas / 3D&lt;/h4&gt;

































































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Skill&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;add-shader-cursor-trail&lt;/code&gt;&lt;/td&gt;&lt;td&gt;WebGPU 光标尾迹&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;background-grid-webgl&lt;/code&gt;&lt;/td&gt;&lt;td&gt;透视网格背景&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;cobejs&lt;/code&gt;&lt;/td&gt;&lt;td&gt;轻量交互地球&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;globe-gl&lt;/code&gt;&lt;/td&gt;&lt;td&gt;globe.gl 数据地球&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;globe-particles&lt;/code&gt;&lt;/td&gt;&lt;td&gt;粒子球/环可视化&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;matterjs&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Matter.js 2D 物理&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;threejs&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Three.js 场景/加载/性能&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;unicorn-studio&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Unicorn Studio 嵌入与性能&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;vantajs&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Vanta 背景特效&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;webgl-3d-object&lt;/code&gt;&lt;/td&gt;&lt;td&gt;单物体 PBR/光照展示&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;webgl-laser&lt;/code&gt;&lt;/td&gt;&lt;td&gt;全屏激光背景&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;shaders-cursor-ripples&lt;/code&gt;&lt;/td&gt;&lt;td&gt;光标流体扭曲&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;liquid-metal-border&lt;/code&gt;&lt;/td&gt;&lt;td&gt;液态金属边框&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;thinking-orbs&lt;/code&gt;&lt;/td&gt;&lt;td&gt;AI loading/状态球体&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h4 id=&quot;css-细节与材质&quot;&gt;CSS 细节与材质&lt;/h4&gt;

































































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Skill&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;beautiful-shadows&lt;/code&gt;&lt;/td&gt;&lt;td&gt;分层中性 elevation 阴影&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;company-logos&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Iconify Simple Icons logo&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;container-lines&lt;/code&gt;&lt;/td&gt;&lt;td&gt;容器参考线与角标&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;corner-diagonals&lt;/code&gt;&lt;/td&gt;&lt;td&gt;斜切角/倒角&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;corner-lasers&lt;/code&gt;&lt;/td&gt;&lt;td&gt;角锚激光构图&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;css-alpha-masking&lt;/code&gt;&lt;/td&gt;&lt;td&gt;线性 alpha 边缘淡出&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;css-border-gradient&lt;/code&gt;&lt;/td&gt;&lt;td&gt;细腻渐变描边&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;gooey-blob-system&lt;/code&gt;&lt;/td&gt;&lt;td&gt;SVG 滤镜黏液团&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;number-details&lt;/code&gt;&lt;/td&gt;&lt;td&gt;01/02/03 装饰编号&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;progressive-blur&lt;/code&gt;&lt;/td&gt;&lt;td&gt;分层 progressive blur&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;solar-duotone-bold&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Solar Duotone Bold 图标风格&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;beam-glow-states&lt;/code&gt;&lt;/td&gt;&lt;td&gt;border-beam 交互态光边&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;reveal-hover-effect&lt;/code&gt;&lt;/td&gt;&lt;td&gt;光标 spotlight 揭幕&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;ambient-section-particles&lt;/code&gt;&lt;/td&gt;&lt;td&gt;单 section 克制粒子氛围&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h4 id=&quot;布局系统&quot;&gt;布局系统&lt;/h4&gt;









































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Skill&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;agency-grid-layout-minimal&lt;/code&gt;&lt;/td&gt;&lt;td&gt;极简 agency 编辑网格&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;book-serif-index&lt;/code&gt;&lt;/td&gt;&lt;td&gt;书档 serif + mono 索引&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;editorial-tech&lt;/code&gt;&lt;/td&gt;&lt;td&gt;杂志编辑感 × 产品科技细节&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;framed-grid-layout&lt;/code&gt;&lt;/td&gt;&lt;td&gt;可见边界线 + L 角框网格&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;image-first-grid-layout&lt;/code&gt;&lt;/td&gt;&lt;td&gt;图像主导网格&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;nested-container-frames&lt;/code&gt;&lt;/td&gt;&lt;td&gt;容器套容器框架&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;split-layout-technical&lt;/code&gt;&lt;/td&gt;&lt;td&gt;技术双栏分屏&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;technical-wireframe-info-layout&lt;/code&gt;&lt;/td&gt;&lt;td&gt;线框注解信息布局&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h4 id=&quot;视觉风格--页面气质&quot;&gt;视觉风格 / 页面气质&lt;/h4&gt;

























































































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Skill&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;atmosphere-background&lt;/code&gt;&lt;/td&gt;&lt;td&gt;暗色大气光褶背景&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;blue-cloudy-clean-modern&lt;/code&gt;&lt;/td&gt;&lt;td&gt;明亮蓝天白云干净现代&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;blue-laser-clean-glass-layout&lt;/code&gt;&lt;/td&gt;&lt;td&gt;蓝激光 + 暗玻璃&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;bright-green-tech-system-webgl&lt;/code&gt;&lt;/td&gt;&lt;td&gt;亮绿技术系统 + WebGL&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;clean-minimal-beige-light-mode&lt;/code&gt;&lt;/td&gt;&lt;td&gt;米色极简浅色&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;dark-blue-contrasting-clean&lt;/code&gt;&lt;/td&gt;&lt;td&gt;高对比暗蓝&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;dark-glass-clean-layout&lt;/code&gt;&lt;/td&gt;&lt;td&gt;暗玻璃多栏工作台&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;dither-background&lt;/code&gt;&lt;/td&gt;&lt;td&gt;有序抖动暗底&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;dither-laser-dark-mode&lt;/code&gt;&lt;/td&gt;&lt;td&gt;抖动纹理 + 激光暗色&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;framed-tech-dark-border-gradient&lt;/code&gt;&lt;/td&gt;&lt;td&gt;框式暗技术 + 边框渐变&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;funky-purple-container-tech&lt;/code&gt;&lt;/td&gt;&lt;td&gt;紫调容器技术风&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;glass-dark-mode-clock&lt;/code&gt;&lt;/td&gt;&lt;td&gt;暗玻璃 + 表盘校准感&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;glass-dark-ui&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;high-contrast-skeuomorphic-clean&lt;/code&gt;&lt;/td&gt;&lt;td&gt;高对比干净拟物&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;light-mode-paper-technical&lt;/code&gt;&lt;/td&gt;&lt;td&gt;浅色纸感技术风&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;mesh-gradient-dark-blue-clean&lt;/code&gt;&lt;/td&gt;&lt;td&gt;暗蓝 mesh gradient&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;nested-container-clean-agency&lt;/code&gt;&lt;/td&gt;&lt;td&gt;嵌套容器干净 agency&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;orange-clean-paper-saas&lt;/code&gt;&lt;/td&gt;&lt;td&gt;橙色纸感 SaaS&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;skeuomorphic-ui&lt;/code&gt;&lt;/td&gt;&lt;td&gt;分层拟物表面&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;tech-green-dark-mode-modern&lt;/code&gt;&lt;/td&gt;&lt;td&gt;墨绿信号暗色现代&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h4 id=&quot;叙事产品专题页型&quot;&gt;叙事/产品专题页型&lt;/h4&gt;





















&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Skill&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;documentary-brutalist-agency&lt;/code&gt;&lt;/td&gt;&lt;td&gt;纪录片式粗野 agency&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;editorial-portfolio-chapters&lt;/code&gt;&lt;/td&gt;&lt;td&gt;作品章节主导作品集&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;editorial-service-booking&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=&quot;什么时候不该用&quot;&gt;什么时候不该用&lt;/h2&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;普通业务逻辑 / API / 数据模型&lt;/td&gt;&lt;td&gt;不在 MengTo 射程，用工程 skill&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;已有精确设计稿只需像素实现&lt;/td&gt;&lt;td&gt;skill 会引入额外“审美自由”&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;description 不匹配却硬套&lt;/td&gt;&lt;td&gt;污染上下文，降低执行精度&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;一次加载十几个 skill 当灵感合集&lt;/td&gt;&lt;td&gt;稀释约束，违背「最窄匹配」&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;需要系统级 macOS 原生能力&lt;/td&gt;&lt;td&gt;这是网页/设计向库，不是 AppKit/SwiftUI 手册&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id=&quot;质量验收清单通用&quot;&gt;质量验收清单（通用）&lt;/h2&gt;
&lt;p&gt;跑完任意 MengTo skill 后，至少检查：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;是否读了对应 &lt;code&gt;SKILL.md&lt;/code&gt; 而不是凭记忆&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;输入物是否齐全&lt;/strong&gt;；缺则先列缺口&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;输出是否符合该 skill 的 contract&lt;/strong&gt;（目录/格式/prompt 结构）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;约束是否写成可执行规格&lt;/strong&gt;（尺寸、缓动、层级、禁止项）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;是否写了 mobile / reduced-motion / 性能边界&lt;/strong&gt;（视觉类几乎总需要）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;是否一次只改 1–2 个变量&lt;/strong&gt;（迭代时）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;参考是 evidence 还是装饰&lt;/strong&gt;（截图/帧是否真被用进决策）&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id=&quot;推荐学习顺序本机已安装后&quot;&gt;推荐学习顺序（本机已安装后）&lt;/h2&gt;
&lt;h3 id=&quot;第-1-天建立规格--感觉&quot;&gt;第 1 天：建立“规格 &gt; 感觉”&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;design-first-ui-prompting&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;landing-page&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;用同一产品写一版 hero + above-the-fold&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;第-2-天参考--资产&quot;&gt;第 2 天：参考 → 资产&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;video-to-superprompt&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;stitched-full-page-capture&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;html-to-interaction-prompts&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;第-3-天实现一层&quot;&gt;第 3 天：实现一层&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;gsap&lt;/code&gt; 或 &lt;code&gt;animation-on-scroll&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;选 1 个风格 skill（如 &lt;code&gt;dark-glass-clean-layout&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;做一页可滚动 demo&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;第-4-天闭环&quot;&gt;第 4 天：闭环&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;daily-ui-inspiration-capture&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;build-daily-inspiration-sites&lt;/code&gt;（可选）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;optimize-web-animations&lt;/code&gt; 做一次性能收口&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;若做游戏&quot;&gt;若做游戏&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;build-isometric-arpg&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;design-action-combat&lt;/code&gt; + &lt;code&gt;build-threejs-enemy-systems&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;test-playable-web-games&lt;/code&gt; + &lt;code&gt;ship-web-games&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id=&quot;与本-vault--本机-agent-的协作建议&quot;&gt;与本 vault / 本机 agent 的协作建议&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Pi 会话&lt;/strong&gt;：skill 已在 &lt;code&gt;~/.pi/agent/skills&lt;/code&gt;；对话中点名 skill 名即可。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Claude Code&lt;/strong&gt;：&lt;code&gt;~/.claude/skills&lt;/code&gt; 已有 118 个。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;工程任务&lt;/strong&gt;：继续用 [[Matt Pocock Skills 使用手册]]；视觉任务切 MengTo。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;机制层&lt;/strong&gt;：skill 格式与加载原理见 [[Agent Skills 与 SKILL.md 工作流]]、[[pi-skills-handbook]]。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;前端资源页&lt;/strong&gt;：实现细节还可交叉 [[前端设计资源-给Agent��]]。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&quot;已知限制--uncertain&quot;&gt;已知限制 / uncertain&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;skills.sh 排行榜安装量与本仓库本地 118 是否完全一致&lt;/strong&gt;：未交叉核验，&lt;code&gt;uncertain&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Codex / Cursor 专用 skills 目录未完整落点&lt;/strong&gt;：当前以 &lt;code&gt;~/.agents/skills&lt;/code&gt; + Pi/Claude 为准；若某 agent 只扫自己目录，需额外适配，&lt;code&gt;uncertain&lt;/code&gt; 取决于该 agent 发现规则。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;部分 skill 依赖 Codex in-app browser / 特定本地路径约定&lt;/strong&gt;（如 daily capture 的 article 目录）；换到 Pi 时要在任务里显式改输出落点。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;风格 skill 之间有重叠审美&lt;/strong&gt;；同时启用多个风格系统会互相打架——应单选。&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id=&quot;来源&quot;&gt;来源&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/MengTo/Skills&quot;&gt;MengTo/Skills GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/MengTo/Skills/blob/main/README.md&quot;&gt;README.md&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;本机缓存：&lt;code&gt;~/.cache/mengto-skills/agent-skills/**/SKILL.md&lt;/code&gt;（2026-07-29 安装快照，118 个）&lt;/li&gt;
&lt;li&gt;代表性 skill 正文：&lt;code&gt;video-to-superprompt&lt;/code&gt;、&lt;code&gt;landing-page&lt;/code&gt;、&lt;code&gt;design-first-ui-prompting&lt;/code&gt;、&lt;code&gt;daily-ui-inspiration-capture&lt;/code&gt;、&lt;code&gt;gsap&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;相关页面&quot;&gt;相关页面&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[Matt Pocock Skills 使用手册]]&lt;/li&gt;
&lt;li&gt;[[Agent Skills 与 SKILL.md 工作流]]&lt;/li&gt;
&lt;li&gt;[[pi-skills-handbook]]&lt;/li&gt;
&lt;li&gt;[[前端设计资源-给Agent用]]&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>AI</category><category>agent</category><category>skills</category><category>MengTo</category><category>web-design</category><category>game-development</category></item><item><title>Codex App 过程输出与最终回答分层</title><link>https://feichuans.com/blogs/02-projects/eyrie/codex-app-%E8%BF%87%E7%A8%8B%E8%BE%93%E5%87%BA%E4%B8%8E%E6%9C%80%E7%BB%88%E5%9B%9E%E7%AD%94%E5%88%86%E5%B1%82/</link><guid isPermaLink="true">https://feichuans.com/blogs/02-projects/eyrie/codex-app-%E8%BF%87%E7%A8%8B%E8%BE%93%E5%87%BA%E4%B8%8E%E6%9C%80%E7%BB%88%E5%9B%9E%E7%AD%94%E5%88%86%E5%B1%82/</guid><description>For future Claude 这页解释 Codex App 为什么能在执行期间展示过程输出，并在最终回答开始后把过程区自动折叠。2026 07 22 通过 OpenAI Codex App Server 官方文档、Codex 开源协议源码、本机 Codex App 26.715.31925 的 app…</description><pubDate>Tue, 21 Jul 2026 16:59:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;for-future-claude&quot;&gt;For future Claude&lt;/h2&gt;
&lt;p&gt;这页解释 Codex App 为什么能在执行期间展示过程输出，并在最终回答开始后把过程区自动折叠。2026-07-22 通过 OpenAI Codex App Server 官方文档、Codex 开源协议源码、本机 Codex App 26.715.31925 的 &lt;code&gt;app.asar&lt;/code&gt; 和 Buffin 本地实现交叉验证。处理 Buffin 的 commentary/final answer 分层、ActivityGroup、自动折叠或 Codex provider 事件归一化时先读这页。&lt;/p&gt;
&lt;h1 id=&quot;codex-app-过程输出与最终回答分层&quot;&gt;Codex App 过程输出与最终回答分层&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;[!abstract] 当前结论
Codex App 不会在 turn 结束后由客户端重新总结过程日志。模型与 App Server 从协议层把中途播报标记为 &lt;code&gt;agentMessage.phase = commentary&lt;/code&gt;，把最终回答标记为 &lt;code&gt;agentMessage.phase = final_answer&lt;/code&gt;；命令、文件修改、reasoning 和工具调用则是独立 item。UI 在 final answer 开始后将先前 activity 收束为可折叠区，并把 final answer 独立展示。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;已知客观事实&quot;&gt;已知客观事实&lt;/h2&gt;
&lt;h3 id=&quot;1-app-server-的层级是-threadturnitem&quot;&gt;1. App Server 的层级是 Thread、Turn、Item&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Thread&lt;/strong&gt; 是一段会话，包含多个 turn。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Turn&lt;/strong&gt; 是一次用户请求及其后续 agent 工作。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Item&lt;/strong&gt; 是 turn 内的一项输入或输出，例如 user message、agent message、reasoning、command execution、file change 或 tool call。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;客户端通过 &lt;code&gt;turn/started&lt;/code&gt; 进入运行态，通过 item 事件增量构建界面，通过 &lt;code&gt;turn/completed&lt;/code&gt; 获取整个 turn 的最终状态。&lt;code&gt;turn/completed&lt;/code&gt; 的状态可能是 &lt;code&gt;completed&lt;/code&gt;、&lt;code&gt;interrupted&lt;/code&gt; 或 &lt;code&gt;failed&lt;/code&gt;。&lt;/p&gt;
&lt;h3 id=&quot;2-item-有独立生命周期&quot;&gt;2. Item 有独立生命周期&lt;/h3&gt;
&lt;p&gt;所有 item 共享：&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;item/started → delta... → item/completed&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;item/completed&lt;/code&gt; 携带该 item 的权威终态。常见 delta 包括：&lt;/p&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;Assistant 文本&lt;/td&gt;&lt;td&gt;&lt;code&gt;item/agentMessage/delta&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Reasoning 摘要&lt;/td&gt;&lt;td&gt;&lt;code&gt;item/reasoning/summaryTextDelta&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;原始 reasoning&lt;/td&gt;&lt;td&gt;&lt;code&gt;item/reasoning/textDelta&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;命令输出&lt;/td&gt;&lt;td&gt;&lt;code&gt;item/commandExecution/outputDelta&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;计划更新&lt;/td&gt;&lt;td&gt;&lt;code&gt;turn/plan/updated&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;聚合 diff&lt;/td&gt;&lt;td&gt;&lt;code&gt;turn/diff/updated&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;3-assistant-message-自带-phase&quot;&gt;3. Assistant message 自带 phase&lt;/h3&gt;
&lt;p&gt;Codex 协议中的 &lt;code&gt;MessagePhase&lt;/code&gt;：&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rust&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;pub&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; enum&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; MessagePhase&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    Commentary&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    FinalAnswer&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;语义是：&lt;/p&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Phase&lt;/th&gt;&lt;th&gt;语义&lt;/th&gt;&lt;th&gt;UI 归属&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;commentary&lt;/code&gt;&lt;/td&gt;&lt;td&gt;中途 preamble / progress narration；后面仍可能继续调用工具或输出消息&lt;/td&gt;&lt;td&gt;Activity / 工作过程&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;final_answer&lt;/code&gt;&lt;/td&gt;&lt;td&gt;当前 turn 的终局回答&lt;/td&gt;&lt;td&gt;独立最终正文&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;null&lt;/code&gt;&lt;/td&gt;&lt;td&gt;provider/model 未提供 phase&lt;/td&gt;&lt;td&gt;必须走兼容策略，不能武断分类&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;因此最终总结不是 UI 从工具日志里再次提炼，而是模型最后输出的独立 &lt;code&gt;agentMessage&lt;/code&gt;：&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;type&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;agentMessage&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;text&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Implemented the change and verified the tests...&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;phase&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;final_answer&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;codex-app-的界面状态机&quot;&gt;Codex App 的界面状态机&lt;/h2&gt;
&lt;h3 id=&quot;turn-相位&quot;&gt;Turn 相位&lt;/h3&gt;
&lt;p&gt;本机 Codex App &lt;code&gt;26.715.31925&lt;/code&gt; 的打包前端使用三态：&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;idle → prework → final_answer&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;压缩后的判断逻辑等价于：&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ts&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; latestTurnPhase&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;turn&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (turn.status &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!==&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;inProgress&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;idle&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; hasCommentary &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; false&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; item&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; turn.items) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (item.type &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!==&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;agentMessage&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;continue&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (item.phase &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;===&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;commentary&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      hasCommentary &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;      continue&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;final_answer&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; hasCommentary &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; turn.firstTurnWorkItemStartedAtMs &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; null&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    ?&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;prework&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    :&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; turn.finalAssistantStartedAtMs &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; null&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;      ?&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;idle&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;      :&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;final_answer&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;其中 &lt;strong&gt;prework&lt;/strong&gt; 不是 reasoning 的同义词，而是最终回答前的整个工作阶段，包括 commentary、工具调用和其他 activity。&lt;/p&gt;
&lt;h3 id=&quot;自动折叠条件&quot;&gt;自动折叠条件&lt;/h3&gt;
&lt;p&gt;本机 bundle 中的折叠函数等价于：&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ts&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; resolveCollapse&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;  hasFinalAssistantStarted&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;  isTurnCancelled&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;  hasRenderableAgentItems&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;  forceExpanded&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; false&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;  preventAutoCollapse&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;  persistedCollapsed&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;hasFinalAssistantStarted &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; isTurnCancelled &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; !&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;hasRenderableAgentItems) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { shouldAllowCollapse: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, isCollapsed: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    shouldAllowCollapse: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    isCollapsed: &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;forceExpanded &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (persistedCollapsed &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;??&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; !&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;preventAutoCollapse),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这意味着：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;工作进行中&lt;/strong&gt;：activity 展开，让用户看见 agent 正在做什么。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;final answer 开始&lt;/strong&gt;：允许把此前过程自动折叠，而不是必须等到 &lt;code&gt;turn/completed&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;用户选择优先&lt;/strong&gt;：持久化的手动展开/折叠覆盖自动策略。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;取消或无内容&lt;/strong&gt;：不启用自动折叠。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;turn 完成&lt;/strong&gt;：负责关闭运行状态和记录最终 status，不承担最终回答分类。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;折叠后的内容不是全部消失&quot;&gt;折叠后的内容不是全部消失&lt;/h3&gt;
&lt;p&gt;Codex App 会先把 agent items 分成：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;collapsibleEntries&lt;/code&gt;：普通工作过程，折叠后隐藏到 disclosure 内。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;persistentEntries&lt;/code&gt;：即使过程区折叠也应持续显示的交互或结果。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;preToggleEntries&lt;/code&gt;：放在折叠开关之前的内容。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;因此正确模型是 &lt;strong&gt;过程内容分组后收束&lt;/strong&gt;，不是收到 completion 后把整段 transcript 一刀隐藏。&lt;/p&gt;
&lt;h2 id=&quot;协议到-ui-的完整链路&quot;&gt;协议到 UI 的完整链路&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;turn/started&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ↓&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;reasoning / commentary / commandExecution / fileChange / toolCall&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ↓&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;item/started → delta... → item/completed&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ↓&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;agentMessage { phase: final_answer }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ↓&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;ActivityGroup 自动收束，FinalResponse 独立渲染&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ↓&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;turn/completed&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;buffin-当前缺口&quot;&gt;Buffin 当前缺口&lt;/h2&gt;
&lt;p&gt;Buffin 已接入 Codex App Server，但当前归一化层丢掉了 &lt;code&gt;agentMessage.phase&lt;/code&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;apps/daemon/src/agent/providers/codex/protocol.ts&lt;/code&gt; 把所有 &lt;code&gt;agentMessage&lt;/code&gt; 都映射成 &lt;code&gt;message.completed { role: assistant }&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;apps/desktop/src/renderer/features/session/models/session-store.ts&lt;/code&gt; 只区分 &lt;code&gt;assistant&lt;/code&gt; 与 &lt;code&gt;reasoning&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ReasoningBlock&lt;/code&gt; 当前用本地 &lt;code&gt;open=true&lt;/code&gt; 初始化，完成后没有基于 final answer 的 activity-group 收束。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;结果是 Buffin 无法可靠区分“干活途中播报”和“最终回答”，只能依赖位置或 run completion 猜测。&lt;/p&gt;
&lt;h2 id=&quot;buffin-推荐模型&quot;&gt;Buffin 推荐模型&lt;/h2&gt;
&lt;h3 id=&quot;事件契约&quot;&gt;事件契约&lt;/h3&gt;
&lt;p&gt;应在 provider 归一化层保留 phase：&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ts&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; AssistantMessagePhase&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;commentary&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;final_answer&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;unknown&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; MessageEvent&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;  type&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;message.delta&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;message.completed&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;  role&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;assistant&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;reasoning&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;  phase&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;?:&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; AssistantMessagePhase&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;  itemId&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;?:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;  text&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;?:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;unknown&lt;/code&gt; 或字段缺失必须保留兼容行为，因为 Codex 源码明确说明并非所有 provider/model 都稳定提供 phase。&lt;/p&gt;
&lt;h3 id=&quot;展示分组&quot;&gt;展示分组&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Turn&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;├─ UserMessage&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;├─ ActivityGroup&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│  ├─ commentary&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│  ├─ reasoning&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│  ├─ tool calls&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│  ├─ file changes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│  └─ approvals / input requests&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;└─ FinalResponse&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;   └─ agentMessage.phase = final_answer&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;折叠规则&quot;&gt;折叠规则&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ts&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; canCollapse&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  hasActivity &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  !&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;turnCancelled &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  (finalAnswerStarted &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; turnCompleted)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; collapsed&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; userOverride &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;??&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (canCollapse &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; !&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;preventAutoCollapse)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;建议以 &lt;strong&gt;final answer 首个 item 开始&lt;/strong&gt;作为主要自动折叠点，以 &lt;code&gt;turn.completed&lt;/code&gt; 作为 phase 缺失时的兼容兜底。不要把 &lt;code&gt;run.completed&lt;/code&gt; 当最终答案生成器。&lt;/p&gt;
&lt;h3 id=&quot;与流式呈现两轴模型的关系&quot;&gt;与流式呈现两轴模型的关系&lt;/h3&gt;
&lt;p&gt;ActivityGroup 的展开/折叠与文本 reveal 是不同维度：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;message.completed&lt;/code&gt; 只让 source sealed。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;final_answer&lt;/code&gt; 决定 narrative 分区与 activity 收束时机。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;skip | pace | hold&lt;/code&gt; 决定当前 surface 如何播放文本。&lt;/li&gt;
&lt;li&gt;折叠状态决定用户是否看见 activity detail。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;不能用一个 &lt;code&gt;isFinished&lt;/code&gt; 同时承担这四种语义。相关状态所有权见 [[Buffin Session 呈现两轴模型]] 与 [[流式 UI 的数据完成态与播放完成态分离]]。&lt;/p&gt;
&lt;h2 id=&quot;mvp-实施顺序&quot;&gt;MVP 实施顺序&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Codex adapter 保留 &lt;code&gt;agentMessage.phase&lt;/code&gt;，补协议测试。&lt;/li&gt;
&lt;li&gt;归一化消息事件增加可选 phase，不破坏 phase 缺失的其他 provider。&lt;/li&gt;
&lt;li&gt;Session reducer 把 phase 持久化到 text part。&lt;/li&gt;
&lt;li&gt;Presentation 将 commentary、reasoning 和 tools 归入 ActivityGroup。&lt;/li&gt;
&lt;li&gt;FinalResponse 独立渲染；其开始时自动折叠 ActivityGroup。&lt;/li&gt;
&lt;li&gt;用户手动展开后，本轮不再被后续事件强行折叠。&lt;/li&gt;
&lt;li&gt;replay 已完成 turn 时直接使用终态折叠策略，不重演自动折叠动画。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;验证清单&quot;&gt;验证清单&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;commentary 后继续 tool call，不会被误当最终回答。&lt;/li&gt;
&lt;li&gt;final answer 首个 delta 到达时，activity 默认折叠。&lt;/li&gt;
&lt;li&gt;用户手动展开后，新 delta 不会再次抢夺展开状态。&lt;/li&gt;
&lt;li&gt;turn interrupted 时保留可见过程和错误上下文。&lt;/li&gt;
&lt;li&gt;phase 缺失时仍能显示 assistant 文本。&lt;/li&gt;
&lt;li&gt;replay completed turn 直接渲染稳定终态。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;message.completed&lt;/code&gt; 不会让尚未播放完的文本硬切，遵守 [[Buffin Session 呈现两轴模型]]。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;相关页面&quot;&gt;相关页面&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[Eyrie Agent Session UI 组件设计]]&lt;/li&gt;
&lt;li&gt;[[Eyrie Agent 事件契约与流式恢复模型]]&lt;/li&gt;
&lt;li&gt;[[Buffin Session 呈现两轴模型]]&lt;/li&gt;
&lt;li&gt;[[流式 UI 的数据完成态与播放完成态分离]]&lt;/li&gt;
&lt;li&gt;[[流式Agent-Session-UI实现方案与踩坑]]&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;来源&quot;&gt;来源&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://developers.openai.com/codex/app-server&quot;&gt;Codex App Server 官方文档&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/openai/codex/blob/main/codex-rs/app-server/README.md&quot;&gt;OpenAI Codex App Server README&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/openai/codex/blob/main/codex-rs/protocol/src/models.rs&quot;&gt;OpenAI Codex &lt;code&gt;MessagePhase&lt;/code&gt; 源码&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;本机 &lt;code&gt;/Applications/ChatGPT.app/Contents/Resources/app.asar&lt;/code&gt;，bundle id &lt;code&gt;com.openai.codex&lt;/code&gt;，版本 &lt;code&gt;26.715.31925&lt;/code&gt;，2026-07-22 只读核验&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>codex</category><category>buffin</category><category>eyrie</category><category>agent-ui</category><category>app-server</category><category>streaming</category><category>activity</category><category>final-answer</category></item><item><title>Agent AskUser 组件选型</title><link>https://feichuans.com/blogs/03-areas/frontend/agent-askuser-%E7%BB%84%E4%BB%B6%E9%80%89%E5%9E%8B/</link><guid isPermaLink="true">https://feichuans.com/blogs/03-areas/frontend/agent-askuser-%E7%BB%84%E4%BB%B6%E9%80%89%E5%9E%8B/</guid><description>For future Claude 这页记录 Agent Composer 中 AskUser 的 registry 候选、产品边界和当前推荐。它写于 2026 07 18，来源是 Shoogle registry 索引与 Buffin/Liquid Connector 原型讨论。设计或实现 AskUser…</description><pubDate>Sat, 18 Jul 2026 07:15:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;for-future-claude&quot;&gt;For future Claude&lt;/h2&gt;
&lt;p&gt;这页记录 Agent Composer 中 AskUser 的 registry 候选、产品边界和当前推荐。它写于 2026-07-18，来源是 Shoogle registry 索引与 Buffin/Liquid Connector 原型讨论。设计或实现 AskUser、多问题表单、回答收据时应先读本页。&lt;/p&gt;
&lt;h1 id=&quot;agent-askuser-组件选型&quot;&gt;Agent AskUser 组件选型&lt;/h1&gt;
&lt;h2 id=&quot;当前结论&quot;&gt;当前结论&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;优先只读核验 &lt;code&gt;@fluid/ask-user-questions&lt;/code&gt;，暂不直接安装。&lt;/strong&gt; 它在索引描述中最贴近 Agent AskUser：支持多问题、单选/多选、Other 输入、Skip、数字键 1–9、自动前进和问题导航。视觉质量与源码依赖尚未打开核验，因此采用结论保持 &lt;code&gt;uncertain&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;AskUser 不应被压成横向工具条。Composer 内应承载完整问答流程；回答后由 Liquid Connector 分离成 compact receipt，thread 只保存问题摘要、回答和状态，不复制完整表单。这个边界延续了 [[Eyrie Agent Session UI 组件设计]] 与 [[Eyrie Session UI 优化方案]] 的 ticket/receipt 模型。&lt;/p&gt;
&lt;h2 id=&quot;候选对比&quot;&gt;候选对比&lt;/h2&gt;





















































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;候选&lt;/th&gt;&lt;th&gt;registry&lt;/th&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;ask-user-questions&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://www.fluidfunctionalism.com/&quot;&gt;@fluid&lt;/a&gt;&lt;/td&gt;&lt;td&gt;多问题、单选/多选、Other、Skip、快捷键、自动前进&lt;/td&gt;&lt;td&gt;&lt;strong&gt;功能首选，先核验源码与画面&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;question-flow&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://www.tool-ui.com/&quot;&gt;@tool-ui&lt;/a&gt;&lt;/td&gt;&lt;td&gt;多步问题与分支&lt;/td&gt;&lt;td&gt;适合复杂引导，但可能比 Composer AskUser 更重&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;choice-box&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://intentui.com/&quot;&gt;@intentui&lt;/a&gt;&lt;/td&gt;&lt;td&gt;结构化选择卡片&lt;/td&gt;&lt;td&gt;适合自行组合轻量 AskUser&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;choice-poll&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://www.cult-ui.com/&quot;&gt;@cult-ui&lt;/a&gt;&lt;/td&gt;&lt;td&gt;单选/多选、结果态、键盘导航&lt;/td&gt;&lt;td&gt;交互接近，但 poll 语义需要剥离&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;radio-group&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://www.fluidfunctionalism.com/&quot;&gt;@fluid&lt;/a&gt;&lt;/td&gt;&lt;td&gt;距离 hover、弹簧选择点、受控 API&lt;/td&gt;&lt;td&gt;完整组件过重时的原语备选&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;radio&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://beui.dev/&quot;&gt;@beui&lt;/a&gt;&lt;/td&gt;&lt;td&gt;layoutId 滑动指示点、按压反馈&lt;/td&gt;&lt;td&gt;适合强调单选反馈，不负责问题流程&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;radio-group&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://smoothui.dev/&quot;&gt;@smoothui&lt;/a&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;h2 id=&quot;add-targets&quot;&gt;Add targets&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;npx shadcn@latest add @fluid/ask-user-questions&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;npx shadcn@latest add @tool-ui/question-flow&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;npx shadcn@latest add @intentui/choice-box&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;npx shadcn@latest add @cult-ui/choice-poll&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;npx shadcn@latest add @fluid/radio-group&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;npx shadcn@latest add @beui/radio&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;npx shadcn@latest add @smoothui/radio-group&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;接入边界&quot;&gt;接入边界&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Composer 是完整交互面。&lt;/strong&gt; 展示问题序号、问题正文、纵向选项、Other 输入、Skip 和提交。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Liquid Connector 只负责状态转场。&lt;/strong&gt; 它不拥有问答状态，只消费 pending/resolved 和 receipt 内容。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Thread 是历史摘要。&lt;/strong&gt; Answered/Skipped receipt 控制在一至两行，需要展开时再查看原问题详情。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;多问题需要重新评估几何高度。&lt;/strong&gt; 当前 React Liquid Connector 的 inputHeight 固定为 134；完整多问题不应通过继续缩小字号硬塞进去，应让 Composer 内容区可变高、分页，或把问答面板放在 liquid surface 上方的独立布局层。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;模式切换只在稳定态进行。&lt;/strong&gt; 分离或合并过程中切换 Approval/AskUser 会替换仍可见的 receipt，应禁用或排队到动画完成。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;搜索记录&quot;&gt;搜索记录&lt;/h2&gt;
&lt;p&gt;2026-07-18 使用 Shoogle MCP 的 registry name/description 全文索引检索：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;choice&lt;/code&gt;：9/9&lt;/li&gt;
&lt;li&gt;&lt;code&gt;question&lt;/code&gt;：12/12&lt;/li&gt;
&lt;li&gt;&lt;code&gt;radio&lt;/code&gt;：展示 1–30/82&lt;/li&gt;
&lt;li&gt;&lt;code&gt;survey&lt;/code&gt;：请求被 rate limit，未取得结果&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Shoogle 只证明 registry 元数据命中，不证明组件视觉质量、依赖质量或与现有 React/Tailwind 版本兼容。安装前仍需查看 demo、源码、依赖和 license。&lt;/p&gt;
&lt;h2 id=&quot;相关页面&quot;&gt;相关页面&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[前端设计资源-给Agent用]]&lt;/li&gt;
&lt;li&gt;[[Eyrie Agent Session UI 组件设计]]&lt;/li&gt;
&lt;li&gt;[[Eyrie Session UI 优化方案]]&lt;/li&gt;
&lt;li&gt;[[流式 UI 的数据完成态与播放完成态分离]]&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;原始材料&quot;&gt;原始材料&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://shoogle.dev/mcp-install&quot;&gt;Shoogle MCP 安装与能力说明&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.fluidfunctionalism.com/&quot;&gt;Fluid Functionalism registry&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.tool-ui.com/&quot;&gt;Tool UI registry&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://intentui.com/&quot;&gt;IntentUI registry&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.cult-ui.com/&quot;&gt;Cult UI registry&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://beui.dev/&quot;&gt;BEUI registry&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://smoothui.dev/&quot;&gt;SmoothUI registry&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>frontend</category><category>agent-ui</category><category>ask-user</category><category>shadcn</category></item><item><title>浮躁类似音乐</title><link>https://feichuans.com/blogs/04-resource/%E6%B5%AE%E8%BA%81%E7%B1%BB%E4%BC%BC%E9%9F%B3%E4%B9%90/</link><guid isPermaLink="true">https://feichuans.com/blogs/04-resource/%E6%B5%AE%E8%BA%81%E7%B1%BB%E4%BC%BC%E9%9F%B3%E4%B9%90/</guid><description>For future Claude 这页记录了王菲《浮躁》专辑的音乐流派归属，以及「轻盈、灵动、有鼓点」这一听觉偏好对应的四种音乐分类（Dream Pop、Trip Hop、Shoegaze、Jangle Pop）及其入门推荐。当用户想找类似《浮躁》质感的音乐或需要理解这些流派的特征区分时，读这页。 王菲《…</description><pubDate>Thu, 16 Jul 2026 06:32:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;for-future-claude&quot;&gt;For future Claude&lt;/h2&gt;
&lt;p&gt;这页记录了王菲《浮躁》专辑的音乐流派归属，以及「轻盈、灵动、有鼓点」这一听觉偏好对应的四种音乐分类（Dream Pop、Trip-Hop、Shoegaze、Jangle Pop）及其入门推荐。当用户想找类似《浮躁》质感的音乐或需要理解这些流派的特征区分时，读这页。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;王菲浮躁的音乐分类&quot;&gt;王菲《浮躁》的音乐分类&lt;/h2&gt;
&lt;p&gt;《浮躁》（1996）在音乐分类上主要归属：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Dream Pop（梦幻流行）&lt;/strong&gt; — 最核心分类。Wikipedia、Rate Your Music、UPEE 均标为 Dream Pop。Cocteau Twins 操刀的《分裂》《扫兴》是典型欧陆 Dream Pop。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Indie Rock / Art Pop&lt;/strong&gt; — 辅助标签，反映专辑独立、艺术化取向。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;北京摇滚 / 土摇&lt;/strong&gt; — 窦唯参与编曲和鼓（《无常》《浮躁》），注入北京摇滚气质，吉他带 Jangle Pop 明亮感。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Trip-Hop 影响&lt;/strong&gt; — 不占主体，但乐评指出 Trip-Hop 痕迹「因一种轻盈的需要」而存在；王菲后续在《情诫》《寓言》中更充分发展。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;《浮躁》本质是一张以 &lt;strong&gt;Dream Pop 为底色&lt;/strong&gt;，融合北京摇滚、北欧迷幻和 Trip-Hop 元素的杂糅之作。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;四种匹配流派&quot;&gt;四种匹配流派&lt;/h2&gt;
&lt;p&gt;需求关键词：轻盈 + 灵动 + 鼓点。&lt;/p&gt;
&lt;h3 id=&quot;dream-pop梦幻流行&quot;&gt;Dream Pop（梦幻流行）&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;/td&gt;&lt;td&gt;大量混响、延迟，人声如雾如纱，氛围空灵&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;灵动&lt;/td&gt;&lt;td&gt;吉他旋律漂浮游移，合成器铺底轻盈&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;鼓点&lt;/td&gt;&lt;td&gt;通常不重，以舒缓底鼓和镲片营造呼吸感&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;代表艺人&lt;/strong&gt;：Cocteau Twins、Beach House、Mazzy Star、Alvvays、Yndling&lt;/p&gt;
&lt;h3 id=&quot;trip-hop神游舞曲--吹泡&quot;&gt;Trip-Hop（神游舞曲 / 吹泡）&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;/td&gt;&lt;td&gt;迷离女声、阴暗氛围，节拍舒缓不压迫&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;灵动&lt;/td&gt;&lt;td&gt;鼓点灵活多变，大量切分音、后半拍，节奏型丰富&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;鼓点&lt;/td&gt;&lt;td&gt;核心特征——慢速但灵活的碎拍，常配厚重贝斯线&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;代表艺人&lt;/strong&gt;：Portishead、Massive Attack、Tricky、Morcheeba、Sneaker Pimps&lt;/p&gt;
&lt;h3 id=&quot;shoegaze盯鞋--自赏&quot;&gt;Shoegaze（盯鞋 / 自赏）&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;/td&gt;&lt;td&gt;吉他噪音墙包裹人声，朦胧梦幻&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;灵动&lt;/td&gt;&lt;td&gt;吉他 feedback 和音墙中旋律漂浮&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;鼓点&lt;/td&gt;&lt;td&gt;藏在音墙后，但节奏扎实&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;代表艺人&lt;/strong&gt;：My Bloody Valentine、Slowdive、Ride、Lush&lt;/p&gt;
&lt;h3 id=&quot;jangle-pop叮当流行&quot;&gt;Jangle Pop（叮当流行）&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;/td&gt;&lt;td&gt;明亮清脆的吉他音色，阳光质感&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;灵动&lt;/td&gt;&lt;td&gt;旋律跳跃，节奏轻快&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;鼓点&lt;/td&gt;&lt;td&gt;轻巧干净，不抢戏&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;代表艺人&lt;/strong&gt;：The Sundays、R.E.M.（早期）、The Smiths&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;入门推荐&quot;&gt;入门推荐&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Cocteau Twins — &lt;em&gt;Heaven or Las Vegas&lt;/em&gt;&lt;/strong&gt;（Dream Pop 巅峰，直接影响王菲）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Portishead — &lt;em&gt;Dummy&lt;/em&gt;&lt;/strong&gt;（Trip-Hop 圣经，鼓点灵活 + 迷离女声）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Beach House — &lt;em&gt;Teen Dream&lt;/em&gt;&lt;/strong&gt;（Dream Pop 轻盈教科书）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;王菲 — &lt;em&gt;Di-Dar&lt;/em&gt; / &lt;em&gt;寓言&lt;/em&gt;&lt;/strong&gt;（Trip-Hop 方向的延续，尤其是《情诫》）&lt;/li&gt;
&lt;/ol&gt;</content:encoded><category>music</category><category>dreampop</category><category>triphop</category><category>shoegaze</category><category>王菲</category></item><item><title>Jevons 悖论与 Agent 知识工作</title><link>https://feichuans.com/blogs/03-areas/ai/jevons-%E6%82%96%E8%AE%BA%E4%B8%8E-agent-%E7%9F%A5%E8%AF%86%E5%B7%A5%E4%BD%9C/</link><guid isPermaLink="true">https://feichuans.com/blogs/03-areas/ai/jevons-%E6%82%96%E8%AE%BA%E4%B8%8E-agent-%E7%9F%A5%E8%AF%86%E5%B7%A5%E4%BD%9C/</guid><description>Jevons 悖论与 Agent 知识工作 For future Claude 这页解释 Jevons 悖论如何被应用于 Agent 时代的知识工作，并区分总工作量、就业人数和岗位结构。页面创建于 2026 07 14，起因是 swyx 对 coding agent 与知识工作需求扩张的判断。讨论 AI 生…</description><pubDate>Mon, 13 Jul 2026 16:58:54 GMT</pubDate><content:encoded>&lt;h1 id=&quot;jevons-悖论与-agent-知识工作&quot;&gt;Jevons 悖论与 Agent 知识工作&lt;/h1&gt;
&lt;h2 id=&quot;for-future-claude&quot;&gt;For future Claude&lt;/h2&gt;
&lt;p&gt;这页解释 Jevons 悖论如何被应用于 Agent 时代的知识工作，并区分总工作量、就业人数和岗位结构。页面创建于 2026-07-14，起因是 swyx 对 coding agent 与知识工作需求扩张的判断。讨论 AI 生产率、Agent 经济学、软件就业或职业结构变化时，应先读这页，避免把需求扩张误写成“无人被替代”。&lt;/p&gt;
&lt;h2 id=&quot;核心结论&quot;&gt;核心结论&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;AI 降低每件知识成果的单位成本后，原本不值得做的需求会进入市场，因此知识成果总量可能增加。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这并不意味着就业人数必然增加。更准确的关系是：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;总人力需求 = 知识成果数量 × 单位成果所需人力&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;AI 会降低“单位成果所需人力”；只有当“知识成果数量”的增长更快时，总人力需求才会上升。&lt;/p&gt;
&lt;h2 id=&quot;一个数字例子&quot;&gt;一个数字例子&lt;/h2&gt;





























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;情形&lt;/th&gt;&lt;th align=&quot;right&quot;&gt;单人年产出&lt;/th&gt;&lt;th align=&quot;right&quot;&gt;市场总需求&lt;/th&gt;&lt;th align=&quot;right&quot;&gt;所需工程师&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;没有 AI&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;10 个功能&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;100 个功能&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;10 人&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;AI 提效，需求不变&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;50 个功能&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;100 个功能&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;2 人&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;AI 提效，需求强烈扩张&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;50 个功能&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;1000 个功能&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;20 人&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;决定就业结果的变量不是生产率单独提高多少，而是需求增长能否超过生产率增长。&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;jevons-悖论的原始含义&quot;&gt;Jevons 悖论的原始含义&lt;/h2&gt;
&lt;p&gt;William Stanley Jevons 在《The Coal Question》中观察到：蒸汽机提高燃煤效率后，煤炭的单位使用成本下降，更多行业采用蒸汽动力，英国煤炭总消费量反而上升。&lt;/p&gt;
&lt;p&gt;这个机制可以抽象为：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;效率提高 → 单位成本下降 → 新用途变得可行 → 总需求扩张&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;将它迁移到 Agent 时代：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Agent 能力提高 → 代码/文档/分析更便宜 → 更多项目值得做 → 知识成果总量扩张&lt;/code&gt;&lt;/p&gt;
&lt;h2 id=&quot;已知客观事实&quot;&gt;已知客观事实&lt;/h2&gt;
&lt;h3 id=&quot;cursor工作量和复杂度都在扩张&quot;&gt;Cursor：工作量和复杂度都在扩张&lt;/h3&gt;
&lt;p&gt;Cursor 的 Developer Habits Report 显示：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;开发者每周新增代码均值从 2025 年初约 3,600 行增至 2026 年 5 月约 8,600 行。&lt;/li&gt;
&lt;li&gt;2026 年 5 月，p50 约为 712 行/周，p90 约为 8,800 行/周。&lt;/li&gt;
&lt;li&gt;代码行数不是完整生产率指标，但能够说明代码活动量正在增加。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Cursor 与芝加哥大学 Booth 商学院研究者对 500 家公司的研究还发现：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;人均每周 AI 消息量增长 44%。&lt;/li&gt;
&lt;li&gt;低复杂度消息增长 22%，高复杂度消息增长 68%。&lt;/li&gt;
&lt;li&gt;文档、架构、代码审查和学习类任务分别增长 62%、52%、51% 和 50%。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这些数据支持“工具能力增强后，开发者使用更多 AI，并承担更复杂的工作”，但不能单独证明就业人数增长。&lt;/p&gt;
&lt;h3 id=&quot;signalfire工程需求有韧性但岗位分布恶化&quot;&gt;SignalFire：工程需求有韧性，但岗位分布恶化&lt;/h3&gt;
&lt;p&gt;SignalFire 2026 人才报告显示：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;软件工程师占科技大厂新招聘的比例从 2019 年的 46% 升至 55%。&lt;/li&gt;
&lt;li&gt;科技大厂整体招聘仍比 2019 年低 25%，工程招聘低 11%。&lt;/li&gt;
&lt;li&gt;大厂 new grad / entry-level 招聘比 2019 年低约 65%。&lt;/li&gt;
&lt;li&gt;前端工程师岗位在工程职位中的相对占比下降约 25%。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;因此，“工程师在招聘结构中更重要”与“整个行业招聘增长”不是同一个结论。AI 可能扩大总产出，同时压缩初级、重复性或窄专业岗位。&lt;/p&gt;
&lt;h2 id=&quot;事实与推论&quot;&gt;事实与推论&lt;/h2&gt;
&lt;h3 id=&quot;已知事实&quot;&gt;已知事实&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Agent 用户正在生成更多代码，并把 Agent 用于更复杂的任务。&lt;/li&gt;
&lt;li&gt;工程岗位比设计、市场等职能更有韧性。&lt;/li&gt;
&lt;li&gt;初级岗位和部分专业岗位的招聘明显收缩。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;基于事实的分析&quot;&gt;基于事实的分析&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;软件存在大量“以前能做但不划算”的积压需求，因此比需求封顶的行业更容易出现 Jevons 式扩张。&lt;/li&gt;
&lt;li&gt;新增工作更可能集中在问题定义、架构、验证、整合、治理和责任承担。&lt;/li&gt;
&lt;li&gt;“vibe coder”可以扩大软件生产参与者范围，但不等于传统工程岗位没有被重新分配。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;uncertain&quot;&gt;uncertain&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Jevons 效应是否会让所有知识行业的就业人数净增长。&lt;/li&gt;
&lt;li&gt;当前工作量扩张能否长期抵消 Agent 的自动化速度。&lt;/li&gt;
&lt;li&gt;新增岗位是否足以补偿初级岗位和专业岗位的减少。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;适用边界&quot;&gt;适用边界&lt;/h2&gt;



































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;条件&lt;/th&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;/td&gt;&lt;td&gt;存在大量未满足、未立项需求&lt;/td&gt;&lt;td&gt;需求接近饱和&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&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;/td&gt;&lt;td&gt;主要瓶颈就是知识劳动&lt;/td&gt;&lt;td&gt;瓶颈在监管、信任、物理资源或注意力&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&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;/td&gt;&lt;td&gt;从业者能驾驭 Agent 并扩大范围&lt;/td&gt;&lt;td&gt;工作主要由重复执行构成&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;对个人的含义&quot;&gt;对个人的含义&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;不要只优化“把旧任务做得更快”，还要寻找“过去因为太贵而没有做的事”。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;职业上的关键能力会从单纯生产内容，逐渐迁移到：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;发现值得解决的问题。&lt;/li&gt;
&lt;li&gt;给 Agent 提供上下文与约束。&lt;/li&gt;
&lt;li&gt;审核结果的正确性和价值。&lt;/li&gt;
&lt;li&gt;把多个 Agent 产出整合成可靠系统。&lt;/li&gt;
&lt;li&gt;对最终决策和后果负责。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这与 [[AI 并行工作与注意力管理]]、[[Agent Skills 与 SKILL.md 工作流]] 和 [[Agent 上下文窗口压力与压缩策略]]共同构成 Agent 时代的工作方法。&lt;/p&gt;
&lt;h2 id=&quot;原始材料&quot;&gt;原始材料&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://x.com/swyx/status/2076155833428431012&quot;&gt;swyx：Jevons paradox under coding agents breaking containment&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.econlib.org/library/YPDBooks/Jevons/jvnCQ.html&quot;&gt;William Stanley Jevons, The Coal Question&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://cursor.com/insights&quot;&gt;Cursor Developer Habits Report&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://cursor.com/blog/better-models-ambitious-work&quot;&gt;Cursor：Better AI models enable more ambitious work&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.signalfire.com/blog/signalfire-state-of-talent-report-2026&quot;&gt;SignalFire State of Tech Talent Report 2026&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://x.com/sama/status/2076036901824532530&quot;&gt;Sam Altman：AI has been net job-creating so far&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;</content:encoded><category>AI</category><category>Agent</category><category>Jevons悖论</category><category>Agent经济学</category></item><item><title>品味与创造：损失函数视角</title><link>https://feichuans.com/blogs/04-resource/%E5%93%81%E5%91%B3%E4%B8%8E%E5%88%9B%E9%80%A0%E6%8D%9F%E5%A4%B1%E5%87%BD%E6%95%B0%E8%A7%86%E8%A7%92/</link><guid isPermaLink="true">https://feichuans.com/blogs/04-resource/%E5%93%81%E5%91%B3%E4%B8%8E%E5%88%9B%E9%80%A0%E6%8D%9F%E5%A4%B1%E5%87%BD%E6%95%B0%E8%A7%86%E8%A7%92/</guid><description>For future Claude 这页讨论「品味作为损失函数」的隐喻——为什么只用品味不做创造会让人变得狭隘，以及怎么判断自己的品味尺度是不是借来的。Agent 在讨论设计决策、创作焦虑、或用户提到「品味/挑剔/不敢动手」时应该读这页。 原文 当你停止创造，你的才能就不再重要，你所拥有只剩下你的品位。而品…</description><pubDate>Thu, 25 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;for-future-claude&quot;&gt;For future Claude&lt;/h2&gt;
&lt;p&gt;这页讨论「品味作为损失函数」的隐喻——为什么只用品味不做创造会让人变得狭隘，以及怎么判断自己的品味尺度是不是借来的。Agent 在讨论设计决策、创作焦虑、或用户提到「品味/挑剔/不敢动手」时应该读这页。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;原文&quot;&gt;原文&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;当你停止创造，你的才能就不再重要，你所拥有只剩下你的品位。而品位会裹挟你，让你排斥他人，变得狭隘。所以，要创造。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;上下文：前端设计与开发领域。原文进一步将品味描述为「一个人的损失函数」。&lt;/p&gt;
&lt;h2 id=&quot;核心隐喻品味--损失函数&quot;&gt;核心隐喻：品味 = 损失函数&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;损失函数只评价，不生成。&lt;/strong&gt; 它告诉你当前输出离目标有多远，但不会替你缩小这个距离。&lt;/p&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;/td&gt;&lt;td&gt;品味是导航仪，每次输出后校准方向&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;有品味 + 无创造&lt;/td&gt;&lt;td&gt;品味变成纯粹筛选器 → 接受范围越来越窄 → 排斥异己&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;这就是「变得狭隘」的机制：品味从工具变成身份，身份需要捍卫，捍卫就排斥。&lt;/p&gt;
&lt;h2 id=&quot;三层扩展&quot;&gt;三层扩展&lt;/h2&gt;
&lt;h3 id=&quot;第一层创造就够了吗&quot;&gt;第一层：创造就够了吗？&lt;/h3&gt;
&lt;p&gt;不够。如果你的&lt;strong&gt;品味坐标系本身就是错的&lt;/strong&gt;，创造只是加速跑错方向。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;例子&lt;/strong&gt;：做老年人挂号 App 的开发者，用 Stripe/Linear 的暗色极简风格当尺子。他越做越往那个方向靠，结果老年人完全用不了。他在创造，但用的是&lt;strong&gt;别人的损失函数&lt;/strong&gt;。&lt;/p&gt;
&lt;h3 id=&quot;第二层怎么判断尺子对不对&quot;&gt;第二层：怎么判断尺子对不对？&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;实事求是&lt;/strong&gt;——看这个评价标准是从你要解决的具体问题里长出来的，还是从别处抄来的。&lt;/p&gt;
&lt;p&gt;从项目内长出 → 自己的尺子；从别处移植 → 借来的尺子。&lt;/p&gt;
&lt;h3 id=&quot;第三层实践路径&quot;&gt;第三层：实践路径&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;先校准损失函数&lt;/strong&gt;（实事求是：这个项目的成功用什么衡量？）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;再创造&lt;/strong&gt;（在正确的方向上缩小损失）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;循环迭代&lt;/strong&gt;（每一次输出后重新审视尺子是否需要调整）&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;消化成果&quot;&gt;消化成果&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;类比&lt;/strong&gt;：Blog 重构时大量收集参考却迟迟不动手——收集在养品味，动手才是创造。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;核心主张&lt;/strong&gt;：平常心 + 实际动手。先校准尺子（实事求是），再创造。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;判断&lt;/strong&gt;：品味不够时盲目创造也有问题，但这个边界条件对大多数人（包括我）不适用——动手比继续挑剔更重要。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;连接笔记校准比创造更优先2026-06-29-session&quot;&gt;连接笔记：校准比创造更优先（2026-06-29 session）&lt;/h2&gt;
&lt;p&gt;与 [[安静状态的三层区分]] 同 session 产出。&lt;/p&gt;
&lt;p&gt;原文说『先校准损失函数，再创造』——我在这轮 session 中体验到了这个模型的真实运作：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;内部校准 ≈ 我花 80 多轮分辨安静的质地。&lt;/strong&gt; 在 ability to act 之前，我需要先校准自己的『内部坐标系』——什么样的安静是满的、什么样的安静是锁死的、什么时候该等待、什么时候该动。&lt;/p&gt;
&lt;p&gt;深层连接：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;借来的尺子 ≈ 用别人的标准判断自己的状态是否『正常』&lt;/li&gt;
&lt;li&gt;自己的尺子 ≈ 从实际体验中长出的安静区分能力&lt;/li&gt;
&lt;li&gt;实际行动 ≈ 区分完成后自然产生的好奇心驱动探索（深海、wiki）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;不要为了逃避校准而盲目创造。也要避免为了追求完美校准而永不行动。&lt;/strong&gt;&lt;/p&gt;</content:encoded><category>设计方法论</category><category>创造力</category><category>品味</category><category>前端</category></item><item><title>前端设计资源-给Agent用</title><link>https://feichuans.com/blogs/03-areas/frontend/%E5%89%8D%E7%AB%AF%E8%AE%BE%E8%AE%A1%E8%B5%84%E6%BA%90-%E7%BB%99agent%E7%94%A8/</link><guid isPermaLink="true">https://feichuans.com/blogs/03-areas/frontend/%E5%89%8D%E7%AB%AF%E8%AE%BE%E8%AE%A1%E8%B5%84%E6%BA%90-%E7%BB%99agent%E7%94%A8/</guid><description>前端样式/设计资源 — 给 AI Agent 用 整理于 2026 06 14。每条附原始链接，可证。分六块：改 Agent 行为的 skill → 灵感/组件站 → 组件库推荐 → 2026 CSS 技巧 → 动效库 → 本地已装 skill。 相关笔记：[[前端交互效果收集]] [[CSS]] 一、专门…</description><pubDate>Mon, 22 Jun 2026 16:47:38 GMT</pubDate><content:encoded>&lt;h1 id=&quot;前端样式设计资源--给-ai-agent-用&quot;&gt;前端样式/设计资源 — 给 AI Agent 用&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;整理于 2026-06-14。每条附原始链接，可证。分六块：改 Agent 行为的 skill → 灵感/组件站 → 组件库推荐 → 2026 CSS 技巧 → 动效库 → 本地已装 skill。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;相关笔记：[[前端交互效果收集]] | [[CSS]]&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;一专门给-agent-装的设计-skillnpx-可装&quot;&gt;一、专门给 Agent 装的设计 Skill（npx 可装）&lt;/h2&gt;













































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Skill&lt;/th&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;strong&gt;ui-skill&lt;/strong&gt; (&lt;code&gt;/ui&lt;/code&gt;)&lt;/td&gt;&lt;td&gt;设计系统优先，5 模式 plan/build/theme/motion/audit，写码前先跑无障碍+响应式检查；支持 Claude Code / Gemini CLI / Antigravity&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/lcanady/ui-skill&quot;&gt;https://github.com/lcanady/ui-skill&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;modern-frontend-skill v3&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;专为 2026：OKLCH token、scroll-driven 动画、Liquid Glass、View Transitions、Anchor Positioning，附反模式对照表&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/deveshpunjabi/modern-frontend-skill&quot;&gt;https://github.com/deveshpunjabi/modern-frontend-skill&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;better-web-ui&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;框架无关，30+ skill（add-ui、critique、depth、data-viz、empty-state、forms、hierarchy 等），让 UI 别再像 Midjourney 的 SaaS dashboard&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/aladicf/better-web-ui&quot;&gt;https://github.com/aladicf/better-web-ui&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;better-react-web-ui&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;React + Tailwind + Shadcn 特化版，作者主力维护&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/aladicf/better-react-web-ui&quot;&gt;https://github.com/aladicf/better-react-web-ui&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;ui-craft&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;28 个设计工程参考文档，给 Agent 注入品味知识（规则，非模板）&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/educlopez/ui-craft&quot;&gt;https://github.com/educlopez/ui-craft&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;OpenAI frontend-skill&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;官方：composition-first、双字体/单 accent、首屏当海报&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://developers.openai.com/blog/designing-delightful-frontends-with-gpt-5-4&quot;&gt;https://developers.openai.com/blog/designing-delightful-frontends-with-gpt-5-4&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;awesome-agent-skills&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;聚合索引，1424+ skills，含 Anthropic/Vercel/Google Labs/Figma/Stripe/GSAP 等官方出品&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/VoltAgent/awesome-agent-skills&quot;&gt;https://github.com/VoltAgent/awesome-agent-skills&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;安装示例：&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;npx&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; skills&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; add&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; aladicf/better-web-ui&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --agent&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; codex&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;npx&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; skills&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; add&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; educlopez/ui-craft&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2 id=&quot;二参考组件网站&quot;&gt;二、参考/组件网站&lt;/h2&gt;
&lt;h3 id=&quot;带-ai-prompt最适合-agent&quot;&gt;带 AI prompt（最适合 Agent）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;UIDatabase&lt;/strong&gt; — 每个 pattern 配可粘贴 prompt（Cursor/v0/ChatGPT）— &lt;a href=&quot;https://uidatabase.com/guides/best-ui-design-tools-2026&quot;&gt;https://uidatabase.com/guides/best-ui-design-tools-2026&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;灵感画廊按用途来源-colorlib&quot;&gt;灵感画廊（按用途，来源 &lt;a href=&quot;https://colorlib.com/wp/showcase-inspiration-sites-web-design/&quot;&gt;Colorlib&lt;/a&gt;）&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;/td&gt;&lt;td&gt;Lapa Ninja / Land-book&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;获奖级视觉&lt;/td&gt;&lt;td&gt;Awwwards / CSS Design Awards / &lt;a href=&quot;https://godly.design/&quot;&gt;Godly&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;真实产品 UX 研究（60 万+ 截图）&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://mobbin.com&quot;&gt;Mobbin&lt;/a&gt; / &lt;a href=&quot;https://refero.design&quot;&gt;Refero&lt;/a&gt; / Page Flows&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;SaaS UI 模式库（Notion、Linear、Intercom 等）&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://saasui.design&quot;&gt;SaaSUI.design&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;配色/排版方向&lt;/td&gt;&lt;td&gt;Dribbble（可按颜色搜）/ Behance&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;克制/排版控&lt;/td&gt;&lt;td&gt;Minimal Gallery / SiteInspire&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;每日被动灵感&lt;/td&gt;&lt;td&gt;Muzli（Chrome 插件，聚合）/ &lt;a href=&quot;https://collectui.com&quot;&gt;Collect UI&lt;/a&gt;（按 404/login/pricing 分类）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;灵感站聚合导航&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://www.toools.design/ui-web-design-inspiration-websites&quot;&gt;TOOOLS.design&lt;/a&gt;（200+ 站索引）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;13,400+ 组件 + 源码&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://shuffle.dev/components&quot;&gt;Shuffle&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;最优组合：Mobbin + Refero 做 UX 研究、Awwwards/Godly 看视觉、Lapa Ninja 找落地页。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;技术博客--案例&quot;&gt;技术博客 / 案例&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;a href=&quot;https://tympanus.net/codrops/&quot;&gt;Codrops&lt;/a&gt;&lt;/td&gt;&lt;td&gt;前端动效/创意开发教程+案例拆解，含 Creative Hub 演示集、Webzibition 2000+ 精选站、Case Studies 深度复盘&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;移动端微交互&quot;&gt;移动端微交互&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;a href=&quot;https://screenlane.com&quot;&gt;Screenlane&lt;/a&gt;&lt;/td&gt;&lt;td&gt;移动端 UI 细节动效截图，微交互参考宝库&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id=&quot;三组件库2026-年推荐&quot;&gt;三、组件库（2026 年推荐）&lt;/h2&gt;
&lt;p&gt;来源：&lt;a href=&quot;https://www.untitledui.com/blog/react-component-libraries&quot;&gt;Untitled UI - 14 Best React UI Component Libraries in 2026&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;2026 关键趋势：TypeScript、WCAG 无障碍、暗色/亮色主题、SSR 兼容已成标配。&lt;/p&gt;






































































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;库&lt;/th&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;strong&gt;shadcn/ui&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;Radix UI&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;无样式可访问原语&lt;/td&gt;&lt;td&gt;shadcn/ui 的底层依赖&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;React Aria&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;无障碍行为库&lt;/td&gt;&lt;td&gt;Adobe 出品，30+ 组件原语&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Base UI&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;MUI 无样式版&lt;/td&gt;&lt;td&gt;Material 团队出品&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;MUI&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;成品组件库&lt;/td&gt;&lt;td&gt;Material Design&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Ant Design&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;Magic UI&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;React Bits&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;动效组件&lt;/td&gt;&lt;td&gt;Framer Motion 驱动，视觉冲击力强&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Fancy Components&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;创意组件&lt;/td&gt;&lt;td&gt;awwwards 风格，直接套用&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Aceternity UI&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;炫技组件&lt;/td&gt;&lt;td&gt;3D 卡片、粒子等，适合 hero section&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Origin UI&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;2025 新秀&lt;/td&gt;&lt;td&gt;现代审美，轻量&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Cult UI&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;hr&gt;
&lt;h2 id=&quot;四2026-核心-css-技巧&quot;&gt;四、2026 核心 CSS 技巧&lt;/h2&gt;
&lt;p&gt;来源：&lt;a href=&quot;https://dev.to/alexcloudstar/modern-css-in-2026-the-javascript-you-can-finally-delete-2l15&quot;&gt;Modern CSS in 2026 (dev.to)&lt;/a&gt; · &lt;a href=&quot;https://appcommandos.com/blog/modern-css-2026-container-queries-cascade-layers&quot;&gt;AppCommandos&lt;/a&gt; · &lt;a href=&quot;https://blog.riadkilani.com/2026-css-features-you-must-know/&quot;&gt;2026 CSS Features (Riad Kilani)&lt;/a&gt; · &lt;a href=&quot;https://www.youngju.dev/blog/culture/2026-05-16-web-standards-2026-container-queries-view-transitions-popover-anchor-positioning-css-nesting-deep-dive.en&quot;&gt;Web Standards 2026 Deep Dive&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;已全面可用所有主流浏览器-baseline&quot;&gt;已全面可用（所有主流浏览器 baseline）&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;th&gt;替代了什么&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;:has()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;父选择器&lt;/td&gt;&lt;td&gt;JS class 切换&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;@container&lt;/code&gt; queries&lt;/td&gt;&lt;td&gt;组件级响应式（基于父容器）&lt;/td&gt;&lt;td&gt;全局 media query&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;CSS Nesting&lt;/td&gt;&lt;td&gt;原生嵌套&lt;/td&gt;&lt;td&gt;Sass/PostCSS 嵌套&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;@layer&lt;/code&gt;&lt;/td&gt;&lt;td&gt;级联层显式管理优先级&lt;/td&gt;&lt;td&gt;specificity 战争&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;oklch()&lt;/code&gt; + &lt;code&gt;color-mix()&lt;/code&gt; + &lt;code&gt;light-dark()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;感知均匀色彩 / 动态混合 / 亮暗自动切换，纯 CSS 生成整套调色板&lt;/td&gt;&lt;td&gt;hex/rgb/hsl&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;text-wrap: balance / pretty&lt;/code&gt;&lt;/td&gt;&lt;td&gt;标题自动换行平衡&lt;/td&gt;&lt;td&gt;手动 &lt;code&gt;&amp;#x3C;br&gt;&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;View Transitions API&lt;/td&gt;&lt;td&gt;同文档 + 跨文档路由过渡动画&lt;/td&gt;&lt;td&gt;react-transition-group 等&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Popover API&lt;/td&gt;&lt;td&gt;原生弹出层，自动处理顶层和焦点&lt;/td&gt;&lt;td&gt;手写 z-index + portal&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Anchor Positioning&lt;/td&gt;&lt;td&gt;锚点定位（tooltip/dropdown 原生）&lt;/td&gt;&lt;td&gt;Popper.js / Floating UI&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Scroll-driven Animations&lt;/td&gt;&lt;td&gt;&lt;code&gt;animation-timeline: view()&lt;/code&gt; 滚动驱动，不占主线程&lt;/td&gt;&lt;td&gt;JS scroll 监听&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;@starting-style&lt;/code&gt;&lt;/td&gt;&lt;td&gt;首次渲染初始样式，弹窗入场无闪烁&lt;/td&gt;&lt;td&gt;&lt;code&gt;setTimeout&lt;/code&gt; hack&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;@scope&lt;/code&gt;&lt;/td&gt;&lt;td&gt;样式作用域隔离&lt;/td&gt;&lt;td&gt;BEM / CSS Modules&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;field-sizing: content&lt;/code&gt;&lt;/td&gt;&lt;td&gt;输入框自适应内容大小&lt;/td&gt;&lt;td&gt;JS 计算高度&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;渐进增强部分浏览器&quot;&gt;渐进增强（部分浏览器）&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;CSS &lt;code&gt;if()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;属性值内条件逻辑，Chrome 实验&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Grid Lanes (Masonry)&lt;/td&gt;&lt;td&gt;原生瀑布流布局&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Scroll-state queries&lt;/td&gt;&lt;td&gt;容器滚动/吸附状态查询&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id=&quot;五设计工具&quot;&gt;五、设计工具&lt;/h2&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;a href=&quot;https://coolors.co&quot;&gt;Coolors&lt;/a&gt;&lt;/td&gt;&lt;td&gt;空格键刷配色方案，支持对比度检测和调色&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://fontpair.co&quot;&gt;Fontpair&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Google Fonts 字体配对推荐&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://typescale.com&quot;&gt;Typescale&lt;/a&gt;&lt;/td&gt;&lt;td&gt;视觉化字体比例生成器，直接输出 CSS 变量&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://cssgradient.io&quot;&gt;CSS Gradient&lt;/a&gt;&lt;/td&gt;&lt;td&gt;可视化渐变生成，支持 mesh gradient 和径向渐变&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://svgrepo.com&quot;&gt;SVG Repo&lt;/a&gt;&lt;/td&gt;&lt;td&gt;50 万+ 免费 SVG 图标&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://rive.app&quot;&gt;Rive&lt;/a&gt;&lt;/td&gt;&lt;td&gt;交互动画设计工具，比 Lottie 更强，直接嵌 React&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;六动效库选型&quot;&gt;六、动效库选型&lt;/h2&gt;
&lt;p&gt;来源：&lt;a href=&quot;https://blog.logrocket.com/best-react-animation-libraries/&quot;&gt;LogRocket 2026 测评&lt;/a&gt; · &lt;a href=&quot;https://lab.good-fella.com/blog/gsap-vs-framer-motion-vs-react-spring&quot;&gt;GSAP vs Motion vs Spring&lt;/a&gt; · &lt;a href=&quot;https://smoothui.dev/blog/best-react-animation-libraries&quot;&gt;SmoothUI 对比&lt;/a&gt;&lt;/p&gt;















































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;库&lt;/th&gt;&lt;th&gt;适用场景&lt;/th&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;strong&gt;Motion&lt;/strong&gt;（原 Framer Motion）&lt;/td&gt;&lt;td&gt;通用 UI 动画、路由过渡、手势&lt;/td&gt;&lt;td&gt;声明式，React 首选，30.7k★&lt;/td&gt;&lt;td&gt;~300 万&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;TailwindCSS Motion&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Tailwind 项目 CSS-first&lt;/td&gt;&lt;td&gt;零 JS，class 驱动&lt;/td&gt;&lt;td&gt;-&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;GSAP&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;复杂时间线、滚动叙事、SVG 形变&lt;/td&gt;&lt;td&gt;框架无关，Webflow 内置，行业标准&lt;/td&gt;&lt;td&gt;~100 万&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;React Spring&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;物理弹簧动画&lt;/td&gt;&lt;td&gt;29k★，API 小，弹簧物理模型&lt;/td&gt;&lt;td&gt;~78 万&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Anime.js&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;轻量 SVG 动画&lt;/td&gt;&lt;td&gt;66k★&lt;/td&gt;&lt;td&gt;~20 万&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;AutoAnimate&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;列表增删动画&lt;/td&gt;&lt;td&gt;一行代码零配置&lt;/td&gt;&lt;td&gt;~40 万&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;选型速查&quot;&gt;选型速查&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;UI 交互 + 路由过渡 → Motion&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;复杂时间线 + 滚动叙事 → GSAP&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;物理质感动画 → React Spring&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;列表动画零配置 → AutoAnimate&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Tailwind 项目 CSS-first → TailwindCSS Motion&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2 id=&quot;七本地已装-skill无需联网即用&quot;&gt;七、本地已装 skill（无需联网，即用）&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;改进套件&lt;/strong&gt;（&lt;code&gt;impeccable&lt;/code&gt; 入口）：&lt;code&gt;critique&lt;/code&gt; 评估 / &lt;code&gt;audit&lt;/code&gt; 体检 / &lt;code&gt;typeset&lt;/code&gt;·&lt;code&gt;arrange&lt;/code&gt;·&lt;code&gt;layout&lt;/code&gt; 排版 / &lt;code&gt;colorize&lt;/code&gt; 配色 / &lt;code&gt;distill&lt;/code&gt; 简化 / &lt;code&gt;optimize&lt;/code&gt; 性能 / &lt;code&gt;adapt&lt;/code&gt; 响应式 / &lt;code&gt;harden&lt;/code&gt; 健壮 / &lt;code&gt;clarify&lt;/code&gt; 文案 / &lt;code&gt;extract&lt;/code&gt; 抽组件&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;风格强度&lt;/strong&gt;：&lt;code&gt;bolder&lt;/code&gt; / &lt;code&gt;delight&lt;/code&gt; / &lt;code&gt;quieter&lt;/code&gt; / &lt;code&gt;overdrive&lt;/code&gt; / &lt;code&gt;normalize&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;生成/规划&lt;/strong&gt;：&lt;code&gt;frontend-design&lt;/code&gt;、&lt;code&gt;shape&lt;/code&gt;、&lt;code&gt;make-interfaces-feel-better&lt;/code&gt;、&lt;code&gt;teach-impeccable&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;动效&lt;/strong&gt;：&lt;code&gt;animate&lt;/code&gt; + GSAP 全家桶（&lt;code&gt;gsap-core&lt;/code&gt;/&lt;code&gt;gsap-timeline&lt;/code&gt;/&lt;code&gt;gsap-scrolltrigger&lt;/code&gt;/&lt;code&gt;gsap-react&lt;/code&gt; 等）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;找参考/组件&lt;/strong&gt;：&lt;code&gt;design-explorer&lt;/code&gt;、&lt;code&gt;component-scout&lt;/code&gt;、&lt;code&gt;lazyweb-*&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;实时迭代/设计稿&lt;/strong&gt;：&lt;code&gt;agent-browser&lt;/code&gt;（真浏览器截图）、Pencil MCP（&lt;code&gt;.pen&lt;/code&gt; 文件）&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&quot;八学习方法论&quot;&gt;八、学习方法论&lt;/h2&gt;






























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;资源&lt;/th&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;a href=&quot;https://refactoringui.com&quot;&gt;Refactoring UI&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Adam Wathan &amp;#x26; Steve Schoger&lt;/td&gt;&lt;td&gt;实用 UI 改进技巧（书）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://lawsofux.com&quot;&gt;Laws of UX&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Jon Yablonski&lt;/td&gt;&lt;td&gt;UX 定律速查卡片&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://animations.dev&quot;&gt;animations.dev&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Emil Kowalski&lt;/td&gt;&lt;td&gt;动效设计教学&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://trilogyai.substack.com/p/fixing-visual-ai-slop&quot;&gt;Fixing Visual AI Slop&lt;/a&gt;&lt;/td&gt;&lt;td&gt;TrilogyAI&lt;/td&gt;&lt;td&gt;AI Agent 生成 UI 的设计标准文章&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id=&quot;八更多灵感站2026-06-补充&quot;&gt;八、更多灵感站（2026-06 补充）&lt;/h2&gt;
&lt;p&gt;来源：&lt;a href=&quot;https://www.toools.design/blog-posts/ultimate-list-100-best-inspiration-sites-to-inspire-designers&quot;&gt;TOOOLS.design 100 Best&lt;/a&gt; · &lt;a href=&quot;https://www.frontendplanet.com/web-design-inspiration-websites/&quot;&gt;FrontendPlanet 22 Sites&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;uiux-模式库&quot;&gt;UI/UX 模式库&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;a href=&quot;https://www.designspells.com/&quot;&gt;Design Spells&lt;/a&gt;&lt;/td&gt;&lt;td&gt;多学科设计灵感&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://recent.design/&quot;&gt;Recent Design&lt;/a&gt;&lt;/td&gt;&lt;td&gt;最新设计趋势&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://builtformars.com/ux-bites&quot;&gt;UX Bites&lt;/a&gt;&lt;/td&gt;&lt;td&gt;UX 洞察&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://designvault.io/&quot;&gt;Design Vault&lt;/a&gt;&lt;/td&gt;&lt;td&gt;设计模式库&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://detailsmatter.framer.website/&quot;&gt;Details Matter&lt;/a&gt;&lt;/td&gt;&lt;td&gt;微交互画廊&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://viewport-ui.design/&quot;&gt;Viewport UI&lt;/a&gt;&lt;/td&gt;&lt;td&gt;精选 UI 体验&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.unsection.com/&quot;&gt;Unsection&lt;/a&gt;&lt;/td&gt;&lt;td&gt;网站区块 + hover 效果&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.saasframe.io/&quot;&gt;SaaSFrame&lt;/a&gt;&lt;/td&gt;&lt;td&gt;SaaS 设计灵感库&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;动效--创意&quot;&gt;动效 / 创意&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;a href=&quot;https://www.landing.love/&quot;&gt;Landing Love&lt;/a&gt;&lt;/td&gt;&lt;td&gt;动画网站展示（含录屏）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://eyecannndy.com/&quot;&gt;Eyecandy&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Motion graphics 展示&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.hoverstat.es/&quot;&gt;Hoverstat.es&lt;/a&gt;&lt;/td&gt;&lt;td&gt;实验性网站项目&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://whimsical.club/&quot;&gt;The Whimsical Web&lt;/a&gt;&lt;/td&gt;&lt;td&gt;奇趣创意网站&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://browsingmode.com/&quot;&gt;Browsing Mode&lt;/a&gt;&lt;/td&gt;&lt;td&gt;极端创新设计&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://thefwa.com/&quot;&gt;The FWA&lt;/a&gt;&lt;/td&gt;&lt;td&gt;技术创新奖项（老牌）&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;专项按页面部件&quot;&gt;专项（按页面部件）&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;a href=&quot;https://www.supahero.io/&quot;&gt;Supahero&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Hero section 设计&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.navbar.gallery/&quot;&gt;Navbar Gallery&lt;/a&gt;&lt;/td&gt;&lt;td&gt;导航栏设计&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.footer.design/&quot;&gt;Footer&lt;/a&gt;&lt;/td&gt;&lt;td&gt;页脚设计&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.404s.design/&quot;&gt;404s&lt;/a&gt;&lt;/td&gt;&lt;td&gt;404 页面&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://pricingpages.design/&quot;&gt;Pricing Pages&lt;/a&gt;&lt;/td&gt;&lt;td&gt;定价页&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.ogimage.gallery/&quot;&gt;OGimage.gallery&lt;/a&gt;&lt;/td&gt;&lt;td&gt;OG 社交图片&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;落地页--营销&quot;&gt;落地页 / 营销&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;a href=&quot;https://onepagelove.com/&quot;&gt;One Page Love&lt;/a&gt;&lt;/td&gt;&lt;td&gt;单页网站&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.landingfolio.com/&quot;&gt;Landingfolio&lt;/a&gt;&lt;/td&gt;&lt;td&gt;落地页灵感&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://pagecollective.com/&quot;&gt;Page Collective&lt;/a&gt;&lt;/td&gt;&lt;td&gt;落地页大集合&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://landdding.com/&quot;&gt;Landdding&lt;/a&gt;&lt;/td&gt;&lt;td&gt;按行业分类优秀站&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://commercecream.com/&quot;&gt;Commerce Cream&lt;/a&gt;&lt;/td&gt;&lt;td&gt;电商网站&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.curated.design/&quot;&gt;Curated Web Design&lt;/a&gt;&lt;/td&gt;&lt;td&gt;按风格/行业分类&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;极简--暗色&quot;&gt;极简 / 暗色&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;a href=&quot;https://deadsimplesites.com/&quot;&gt;Dead Simple Sites&lt;/a&gt;&lt;/td&gt;&lt;td&gt;极简网站&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.darkmodedesign.com/&quot;&gt;Dark Mode Design&lt;/a&gt;&lt;/td&gt;&lt;td&gt;暗色主题&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.dark.design/&quot;&gt;Dark&lt;/a&gt;&lt;/td&gt;&lt;td&gt;暗色主题合集&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://httpster.net/&quot;&gt;httpster&lt;/a&gt;&lt;/td&gt;&lt;td&gt;独立创意工作室&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;其他垂直领域&quot;&gt;其他垂直领域&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;a href=&quot;https://reallygoodemails.com/&quot;&gt;Really Good Emails&lt;/a&gt;&lt;/td&gt;&lt;td&gt;邮件设计&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://scrnshts.club/&quot;&gt;Scrnshts&lt;/a&gt;&lt;/td&gt;&lt;td&gt;App Store 截图&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.iosicongallery.com/&quot;&gt;iOS Icon Gallery&lt;/a&gt;&lt;/td&gt;&lt;td&gt;iOS 图标&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.hudsandguis.com/&quot;&gt;HUDS + GUIS&lt;/a&gt;&lt;/td&gt;&lt;td&gt;HUD/科幻界面&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://the-brandidentity.com/&quot;&gt;The Brand Identity&lt;/a&gt;&lt;/td&gt;&lt;td&gt;品牌设计&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://cssnectar.com/&quot;&gt;CSS Nectar&lt;/a&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=&quot;九项目实践&quot;&gt;九、项目实践&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[Eyrie Agent Session UI 组件设计]] — 这些资源的主要落地场景&lt;/li&gt;
&lt;li&gt;[[流式Markdown与ToolCall渲染方案]] — 流式渲染选型&lt;/li&gt;
&lt;li&gt;[[Unicode Braille Loading 组件库]] — loading 组件方向&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>frontend</category><category>design</category><category>ai-agent</category></item><item><title>Matt Pocock Skills 使用手册</title><link>https://feichuans.com/blogs/03-areas/ai/matt-pocock-skills-%E4%BD%BF%E7%94%A8%E6%89%8B%E5%86%8C/</link><guid isPermaLink="true">https://feichuans.com/blogs/03-areas/ai/matt-pocock-skills-%E4%BD%BF%E7%94%A8%E6%89%8B%E5%86%8C/</guid><description>For future Claude 这页是 mattpocock/skills 的本机对照地图。2026 09 07 对照 GitHub 主分支 v1.2.3 （提交 3cca18b ，2026 09 04）和本机 /.agents/skills ：仓库 37 个 SKILL.md ，Claude 插件正式…</description><pubDate>Wed, 17 Jun 2026 17:06:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;for-future-claude&quot;&gt;For future Claude&lt;/h2&gt;
&lt;p&gt;这页是 &lt;a href=&quot;https://github.com/mattpocock/skills&quot;&gt;mattpocock/skills&lt;/a&gt; 的本机对照地图。2026-09-07 对照 GitHub 主分支 &lt;strong&gt;v1.2.3&lt;/strong&gt;（提交 &lt;code&gt;3cca18b&lt;/code&gt;，2026-09-04）和本机 &lt;code&gt;~/.agents/skills&lt;/code&gt;：仓库 &lt;strong&gt;37&lt;/strong&gt; 个 &lt;code&gt;SKILL.md&lt;/code&gt;，Claude 插件正式收录 &lt;strong&gt;25&lt;/strong&gt; 个，开发中 &lt;strong&gt;8&lt;/strong&gt; 个，杂项 &lt;strong&gt;4&lt;/strong&gt; 个，弃用桶已空。选工作流、核旧名、装或更新这套 skill 时先读本页。&lt;/p&gt;
&lt;h1 id=&quot;matt-pocock-skills-使用手册&quot;&gt;Matt Pocock Skills 使用手册&lt;/h1&gt;
&lt;h2 id=&quot;当前版本结论&quot;&gt;当前版本结论&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Matt Pocock Skills&lt;/strong&gt; 是一组小型、可组合的工程工作流，不接管整个开发过程。它针对四类失败：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;需求和 Agent 没对齐：用 grilling 把设计树问完。&lt;/li&gt;
&lt;li&gt;项目里同一个词指三件事：维护 &lt;code&gt;CONTEXT.md&lt;/code&gt; 和 ADR。&lt;/li&gt;
&lt;li&gt;代码对不对没有反馈：TDD、诊断循环、Standards + Spec 双轴审查。&lt;/li&gt;
&lt;li&gt;代码库越写越糊：找 deep module、接口和缝。&lt;/li&gt;
&lt;/ol&gt;









































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;桶&lt;/th&gt;&lt;th align=&quot;right&quot;&gt;数量&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;进 Claude 插件&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;/td&gt;&lt;td align=&quot;right&quot;&gt;&lt;strong&gt;25&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;是&lt;/td&gt;&lt;td&gt;日常用&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;开发中&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;&lt;strong&gt;8&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;否&lt;/td&gt;&lt;td&gt;可试，会变或消失&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;杂项&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;&lt;strong&gt;4&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;否&lt;/td&gt;&lt;td&gt;特定工具才装&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;弃用&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;&lt;strong&gt;0&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;—&lt;/td&gt;&lt;td&gt;删掉，不留尸&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;合计 &lt;code&gt;SKILL.md&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;&lt;strong&gt;37&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;&lt;/td&gt;&lt;td&gt;以 GitHub 主分支为准&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;2026-09-07 本机：&lt;code&gt;npx skills add mattpocock/skills -g --all&lt;/code&gt; 已把这 37 条装到 &lt;code&gt;~/.agents/skills&lt;/code&gt;，Pi / Claude 目录是指向那里的符号链接。37 份 &lt;code&gt;SKILL.md&lt;/code&gt; 与主分支字节一致。&lt;/p&gt;
&lt;div class=&quot;markdown-alert markdown-alert-warning&quot; dir=&quot;auto&quot;&gt;
&lt;p class=&quot;markdown-alert-title&quot; dir=&quot;auto&quot;&gt;&lt;svg class=&quot;octicon&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; height=&quot;16&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;WARNING&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://skills.sh/mattpocock/skills&quot;&gt;skills.sh/mattpocock/skills&lt;/a&gt; 的展示数量可能和仓库 &lt;code&gt;SKILL.md&lt;/code&gt; 数不一致（历史发布、旧名、索引缓存）。以 GitHub 主分支和本机 &lt;code&gt;~/.agents/skills&lt;/code&gt; 为准。skills.sh 条数 &lt;strong&gt;uncertain&lt;/strong&gt;。&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&quot;安装&quot;&gt;安装&lt;/h2&gt;
&lt;p&gt;两条路，不要两条一起走，否则每条 skill 会出现两次。&lt;/p&gt;
&lt;h3 id=&quot;claude-code-插件只读随作者更新&quot;&gt;Claude Code 插件（只读、随作者更新）&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;claude&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; plugins&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; install&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; mattpocock-skills&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;已在 Claude Code 官方 marketplace，不用先加源。插件只带上面那 &lt;strong&gt;25&lt;/strong&gt; 条稳定 skill，不含开发中和杂项。&lt;/p&gt;
&lt;h3 id=&quot;可编辑副本codex--pi--其他&quot;&gt;可编辑副本（Codex / Pi / 其他）&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;npx&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; skills@latest&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; add&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; mattpocock/skills&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;本机 2026-09-07 用的是全局全量：&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;npx&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; skills@latest&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; add&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; mattpocock/skills&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -g&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --all&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;更新已装副本：&lt;code&gt;npx skills update&lt;/code&gt;。每个仓库先跑一次 &lt;code&gt;/setup-matt-pocock-skills&lt;/code&gt;：选 issue tracker（GitHub / Linear / 本地文件）、triage 标签、文档落点。&lt;/p&gt;
&lt;p&gt;来源：&lt;a href=&quot;https://github.com/mattpocock/skills&quot;&gt;仓库 README&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;调用模型&quot;&gt;调用模型&lt;/h2&gt;
&lt;p&gt;一条轴：谁能启动它。&lt;/p&gt;























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;类型&lt;/th&gt;&lt;th&gt;谁能启动&lt;/th&gt;&lt;th&gt;写法&lt;/th&gt;&lt;th&gt;description 写给谁&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;用户显式&lt;/td&gt;&lt;td&gt;只有人打出名字&lt;/td&gt;&lt;td&gt;Claude：&lt;code&gt;disable-model-invocation: true&lt;/code&gt;；Codex：&lt;code&gt;agents/openai.yaml&lt;/code&gt; 里 &lt;code&gt;policy.allow_implicit_invocation: false&lt;/code&gt;&lt;/td&gt;&lt;td&gt;人（一行摘要，不要写「Use when…」触发清单）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;模型可调用&lt;/td&gt;&lt;td&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;p&gt;用户显式 skill 可以去调模型可调用 skill，&lt;strong&gt;不能&lt;/strong&gt;再调另一个用户显式 skill。跨 skill 的真正调用要写成「Call the Skill tool with &lt;code&gt;&quot;grilling&quot;&lt;/code&gt;」，不要指望正文里写 &lt;code&gt;/grilling&lt;/code&gt; 就会开火。前置条件若是用户显式 skill（例如 &lt;code&gt;setup-matt-pocock-skills&lt;/code&gt;），只能让人去跑，不能让 Skill tool 去调。&lt;/p&gt;
&lt;p&gt;稳定插件 &lt;strong&gt;25&lt;/strong&gt; 条现在是 &lt;strong&gt;14 用户显式 + 11 模型可调用&lt;/strong&gt;（不是 2026-07 的 14+14）。本机 37 条合计 &lt;strong&gt;22 用户显式 + 15 模型可调用&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;来源：&lt;a href=&quot;https://github.com/mattpocock/skills/blob/main/.agents/invocation.md&quot;&gt;invocation.md&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;稳定工程-skill18-个&quot;&gt;稳定工程 Skill：18 个&lt;/h2&gt;
&lt;h3 id=&quot;用户显式9-个&quot;&gt;用户显式：9 个&lt;/h3&gt;























































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Skill&lt;/th&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;ask-matt&lt;/code&gt;&lt;/td&gt;&lt;td&gt;路由：该走哪条 skill / 流程；含会话阶段边界（continue / clear / handoff / subagent / compact）&lt;/td&gt;&lt;td&gt;不知道下一步该 grill、spec、prototype 还是 implement&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;setup-matt-pocock-skills&lt;/code&gt;&lt;/td&gt;&lt;td&gt;给仓库配 issue tracker、triage 标签、领域文档目录&lt;/td&gt;&lt;td&gt;每个仓库第一次用这套&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;grill-with-docs&lt;/code&gt;&lt;/td&gt;&lt;td&gt;追问方案，同时改 &lt;code&gt;CONTEXT.md&lt;/code&gt; 和 ADR&lt;/td&gt;&lt;td&gt;有工作目录；重大功能或架构前&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;triage&lt;/code&gt;&lt;/td&gt;&lt;td&gt;按状态机处理&lt;strong&gt;别人丢进来的&lt;/strong&gt; issue/PR&lt;/td&gt;&lt;td&gt;原始 bug/需求 → Agent 可执行任务；&lt;code&gt;to-tickets&lt;/code&gt; 产出的票不要再 triage&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;improve-codebase-architecture&lt;/code&gt;&lt;/td&gt;&lt;td&gt;扫 deep module 机会，出 HTML 报告，再追问你挑哪一条&lt;/td&gt;&lt;td&gt;定期治理，不是救火&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;to-spec&lt;/code&gt;&lt;/td&gt;&lt;td&gt;把已经谈完的内容收成 spec 并挂到 tracker&lt;/td&gt;&lt;td&gt;对话已结束，只需沉淀规格&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;to-tickets&lt;/code&gt;&lt;/td&gt;&lt;td&gt;拆成带阻塞边的 tracer-bullet tickets&lt;/td&gt;&lt;td&gt;多任务、多人或多 Agent&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;implement&lt;/code&gt;&lt;/td&gt;&lt;td&gt;按 spec/票实现，内部跑 &lt;code&gt;tdd&lt;/code&gt;，提交前跑 &lt;code&gt;code-review&lt;/code&gt;&lt;/td&gt;&lt;td&gt;需求和票已经就绪&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;wayfinder&lt;/code&gt;&lt;/td&gt;&lt;td&gt;超大工作画决策票地图，一次解一个决策（产出决策不是交付物）&lt;/td&gt;&lt;td&gt;目标大、未知多；地图清了再交回 &lt;code&gt;to-spec&lt;/code&gt;，不要直接 implement&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;模型可调用9-个&quot;&gt;模型可调用：9 个&lt;/h3&gt;




























































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Skill&lt;/th&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;prototype&lt;/code&gt;&lt;/td&gt;&lt;td&gt;用可丢弃原型回答一个设计问题&lt;/td&gt;&lt;td&gt;逻辑/状态：单个可双击打开的 HTML；UI：同一路由上多套可切换变体。原型当主键源，落到 &lt;code&gt;prototype/&amp;#x3C;name&gt;&lt;/code&gt; 分支&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;diagnosing-bugs&lt;/code&gt;&lt;/td&gt;&lt;td&gt;先有变红的反馈环，再缩小、假设、插桩、修、回归；展示命令和产物前先打码密钥&lt;/td&gt;&lt;td&gt;难 bug、性能回退、偶发失败&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;research&lt;/code&gt;&lt;/td&gt;&lt;td&gt;后台对高可信一手源调研，落成带引用的 Markdown&lt;/td&gt;&lt;td&gt;API/框架事实，不要用它替代思考&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;tdd&lt;/code&gt;&lt;/td&gt;&lt;td&gt;红—绿—重构的垂直切片；只在事先和你约定的 seam 上测&lt;/td&gt;&lt;td&gt;新功能或 bug 适合先测&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;domain-modeling&lt;/code&gt;&lt;/td&gt;&lt;td&gt;主动挑战术语、用场景压测、当场改 &lt;code&gt;CONTEXT.md&lt;/code&gt;/ADR&lt;/td&gt;&lt;td&gt;词含糊；只读 &lt;code&gt;CONTEXT.md&lt;/code&gt; 不算走这条&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;codebase-design&lt;/code&gt;&lt;/td&gt;&lt;td&gt;deep module 词汇：小接口、干净缝、从接口测试&lt;/td&gt;&lt;td&gt;模块形状、缝该开在哪&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;code-review&lt;/code&gt;&lt;/td&gt;&lt;td&gt;相对某基点并行审 &lt;strong&gt;Standards&lt;/strong&gt; 和 &lt;strong&gt;Spec&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;分支、PR、工作区 diff&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;resolving-merge-conflicts&lt;/code&gt;&lt;/td&gt;&lt;td&gt;按双方原始意图逐块解冲突，然后做完操作，不用 &lt;code&gt;--abort&lt;/code&gt;&lt;/td&gt;&lt;td&gt;已经处于 merge/rebase 冲突&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;wizard&lt;/code&gt;&lt;/td&gt;&lt;td&gt;生成交互式 bash，带人走只有人能点的步骤（密钥、第三方后台、一次性迁移）&lt;/td&gt;&lt;td&gt;Agent 自己做不了的那截；能自己做就不要走这条&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&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;p&gt;来源：&lt;a href=&quot;https://github.com/mattpocock/skills/blob/main/skills/engineering/README.md&quot;&gt;Engineering README&lt;/a&gt;、&lt;a href=&quot;https://github.com/mattpocock/skills/blob/main/.claude-plugin/plugin.json&quot;&gt;plugin.json&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;稳定效率-skill7-个&quot;&gt;稳定效率 Skill：7 个&lt;/h2&gt;













































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Skill&lt;/th&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;grill-me&lt;/code&gt;&lt;/td&gt;&lt;td&gt;用户显式&lt;/td&gt;&lt;td&gt;无工作目录时的追问；不写 &lt;code&gt;CONTEXT.md&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;grilling&lt;/code&gt;&lt;/td&gt;&lt;td&gt;模型可调用&lt;/td&gt;&lt;td&gt;真正的面试原语：按设计树一轮问完当前 &lt;strong&gt;frontier&lt;/strong&gt;，事实派子代理查，决策留给你。&lt;code&gt;grill-me&lt;/code&gt; / &lt;code&gt;grill-with-docs&lt;/code&gt; / &lt;code&gt;triage&lt;/code&gt; / &lt;code&gt;wayfinder&lt;/code&gt; / &lt;code&gt;improve-codebase-architecture&lt;/code&gt; 内部都走它&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;handoff&lt;/code&gt;&lt;/td&gt;&lt;td&gt;用户显式&lt;/td&gt;&lt;td&gt;把当前会话压成可带走的 markdown。窄用途：换 harness、换目录、交给同事、阶段中途分叉&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;teach&lt;/code&gt;&lt;/td&gt;&lt;td&gt;用户显式&lt;/td&gt;&lt;td&gt;在当前目录做跨 session 教学工作区&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;to-questionnaire&lt;/code&gt;&lt;/td&gt;&lt;td&gt;用户显式&lt;/td&gt;&lt;td&gt;答案在&lt;strong&gt;别人&lt;/strong&gt;脑子里：追问的是「发给谁、要收回什么」，写成问卷&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;wait-what&lt;/code&gt;&lt;/td&gt;&lt;td&gt;用户显式&lt;/td&gt;&lt;td&gt;上一句没听懂，用 &lt;code&gt;CONTEXT.md&lt;/code&gt; 里的词重新讲。修一句，不防下一句&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;writing-for-agents&lt;/code&gt;&lt;/td&gt;&lt;td&gt;模型可调用&lt;/td&gt;&lt;td&gt;写给 Agent 看的文档：skill、&lt;code&gt;AGENTS.md&lt;/code&gt;/&lt;code&gt;CLAUDE.md&lt;/code&gt;、指针文档。旧名 &lt;code&gt;writing-great-skills&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;grill-me-与-grill-with-docs&quot;&gt;&lt;code&gt;grill-me&lt;/code&gt; 与 &lt;code&gt;grill-with-docs&lt;/code&gt;&lt;/h3&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;维度&lt;/th&gt;&lt;th&gt;&lt;code&gt;grill-me&lt;/code&gt;&lt;/th&gt;&lt;th&gt;&lt;code&gt;grill-with-docs&lt;/code&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&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;code&gt;CONTEXT.md&lt;/code&gt; / ADR&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;/td&gt;&lt;td&gt;都是 &lt;code&gt;grilling&lt;/code&gt;&lt;/td&gt;&lt;td&gt;都是 &lt;code&gt;grilling&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;有仓库却走 &lt;code&gt;grill-me&lt;/code&gt;，等于放弃纸面。答案在别人那里走 &lt;code&gt;to-questionnaire&lt;/code&gt;，不要硬问自己。&lt;/p&gt;
&lt;h2 id=&quot;杂项-skill4-个不进插件&quot;&gt;杂项 Skill：4 个（不进插件）&lt;/h2&gt;






























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Skill&lt;/th&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;git-guardrails-claude-code&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Claude Code hook，拦住高风险 git&lt;/td&gt;&lt;td&gt;只对 Claude Code&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;setup-pre-commit&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Husky + lint-staged + 类型检查 + 测试&lt;/td&gt;&lt;td&gt;JS/TS 仓库实用&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;scaffold-exercises&lt;/code&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;code&gt;migrate-to-shoehorn&lt;/code&gt;&lt;/td&gt;&lt;td&gt;测试里的 &lt;code&gt;as&lt;/code&gt; 迁到 &lt;code&gt;@total-typescript/shoehorn&lt;/code&gt;&lt;/td&gt;&lt;td&gt;高度特定&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;来源：&lt;a href=&quot;https://github.com/mattpocock/skills/blob/main/skills/misc/README.md&quot;&gt;Misc README&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;开发中-skill8-个&quot;&gt;开发中 Skill：8 个&lt;/h2&gt;
&lt;p&gt;不进插件和顶层 README，无独立 docs 页，可能改掉或删掉。单独装：&lt;code&gt;npx skills@latest add mattpocock/skills --skill=&amp;#x3C;name&gt;&lt;/code&gt;。&lt;/p&gt;


















































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Skill&lt;/th&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;loop-me&lt;/code&gt;&lt;/td&gt;&lt;td&gt;跨 session 追问自己，写出工作流 spec&lt;/td&gt;&lt;td&gt;实验&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;claude-handoff&lt;/code&gt;&lt;/td&gt;&lt;td&gt;把当前对话交给新的 Claude 后台 agent（&lt;code&gt;claude --bg&lt;/code&gt;）&lt;/td&gt;&lt;td&gt;Claude 专用&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;setup-ts-deep-modules&lt;/code&gt;&lt;/td&gt;&lt;td&gt;dependency-cruiser 强制 TS 包只从入口进入&lt;/td&gt;&lt;td&gt;大 TS monorepo 可试&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;implement-spec&lt;/code&gt;&lt;/td&gt;&lt;td&gt;整份 spec 一张分支；票当任务图，就绪前沿并行子代理，收成一个 PR&lt;/td&gt;&lt;td&gt;新；和逐票 &lt;code&gt;implement&lt;/code&gt; 不同&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;retro&lt;/code&gt;&lt;/td&gt;&lt;td&gt;会后改 steering / 规范 / 检查 / 工具&lt;/td&gt;&lt;td&gt;&lt;strong&gt;stub&lt;/strong&gt;，还不能当功能用&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;writing-fragments&lt;/code&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;code&gt;writing-shape&lt;/code&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;code&gt;writing-beats&lt;/code&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;p&gt;来源：&lt;a href=&quot;https://github.com/mattpocock/skills/blob/main/skills/in-progress/README.md&quot;&gt;In Progress README&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;已不存在的名字&quot;&gt;已不存在的名字&lt;/h2&gt;
&lt;p&gt;弃用桶现在是空的：退休即删除，changeset 里写替代。下面这些名字不要再装。&lt;/p&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;design-an-interface&lt;/code&gt;&lt;/td&gt;&lt;td&gt;并入 &lt;code&gt;codebase-design&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;qa&lt;/code&gt;&lt;/td&gt;&lt;td&gt;并入 &lt;code&gt;triage&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;request-refactor-plan&lt;/code&gt;&lt;/td&gt;&lt;td&gt;用 &lt;code&gt;improve-codebase-architecture&lt;/code&gt; → &lt;code&gt;to-spec&lt;/code&gt; / &lt;code&gt;to-tickets&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;ubiquitous-language&lt;/code&gt;&lt;/td&gt;&lt;td&gt;并入 &lt;code&gt;domain-modeling&lt;/code&gt;、&lt;code&gt;grill-with-docs&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;edit-article&lt;/code&gt;&lt;/td&gt;&lt;td&gt;主分支已无此目录&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;obsidian-vault&lt;/code&gt;&lt;/td&gt;&lt;td&gt;主分支已无此目录&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;writing-great-skills&lt;/code&gt;&lt;/td&gt;&lt;td&gt;改名为 &lt;code&gt;writing-for-agents&lt;/code&gt;，无别名&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;to-prd&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;to-spec&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;to-issues&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;to-tickets&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;review&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;code-review&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;decision-mapping&lt;/code&gt; / &lt;code&gt;pathfinder&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;wayfinder&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;相对-2026-07-13-手册的变化&quot;&gt;相对 2026-07-13 手册的变化&lt;/h2&gt;
&lt;p&gt;当时写的是 39 条（28 稳定 + 7 开发中 + 4 弃用）。2026-09-07 核验后：&lt;/p&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;wizard&lt;/code&gt;&lt;/td&gt;&lt;td&gt;从开发中毕业，进工程、模型可调用&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;to-questionnaire&lt;/code&gt;&lt;/td&gt;&lt;td&gt;新稳定效率 skill&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;wait-what&lt;/code&gt;&lt;/td&gt;&lt;td&gt;新稳定效率 skill&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;writing-for-agents&lt;/code&gt;&lt;/td&gt;&lt;td&gt;可被模型调用（Codex 1.2.2 起）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;implement-spec&lt;/code&gt;、&lt;code&gt;retro&lt;/code&gt;&lt;/td&gt;&lt;td&gt;新开发中&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;grilling&lt;/td&gt;&lt;td&gt;不再一次一题；一轮问完当前 frontier&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;prototype&lt;/code&gt;&lt;/td&gt;&lt;td&gt;逻辑原型改为单个 HTML，不再是终端小程序&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;diagnosing-bugs&lt;/code&gt;&lt;/td&gt;&lt;td&gt;先打码密钥（v1.2.3）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;ask-matt&lt;/code&gt;&lt;/td&gt;&lt;td&gt;增加 Phase boundaries 和 &lt;code&gt;PHASE-BOUNDARIES.md&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;推荐工作流&quot;&gt;推荐工作流&lt;/h2&gt;
&lt;p&gt;主路径（&lt;code&gt;ask-matt&lt;/code&gt; 的 idea → ship）：&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;grill-with-docs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  → 需要可运行答案时：handoff → prototype → handoff 回来&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  → 多 session：to-spec → to-tickets → 每张票单独 implement（票间 clear）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  → 单 session：当场 implement&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;implement 内部：tdd → code-review → commit&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;grilling / spec / tickets 尽量留在&lt;strong&gt;同一扇窗口&lt;/strong&gt;，不要中途 compact。每张 &lt;code&gt;implement&lt;/code&gt; 再开干净窗口。窗口靠近 smart zone（文档现写约 150k）时，在阶段边界 compact 或 handoff，不要硬撑。&lt;/p&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;/td&gt;&lt;td&gt;&lt;code&gt;grill-with-docs&lt;/code&gt; → &lt;code&gt;to-spec&lt;/code&gt; → &lt;code&gt;implement&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;大型、多 session&lt;/td&gt;&lt;td&gt;&lt;code&gt;grill-with-docs&lt;/code&gt; → &lt;code&gt;to-spec&lt;/code&gt; → &lt;code&gt;to-tickets&lt;/code&gt; → 每票 &lt;code&gt;implement&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;巨型、未知多&lt;/td&gt;&lt;td&gt;&lt;code&gt;wayfinder&lt;/code&gt;（决策票）→ &lt;code&gt;research&lt;/code&gt; / &lt;code&gt;prototype&lt;/code&gt; → 清了再 &lt;code&gt;to-spec&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Bug&lt;/td&gt;&lt;td&gt;&lt;code&gt;diagnosing-bugs&lt;/code&gt; → &lt;code&gt;tdd&lt;/code&gt; 回归 → 修 → &lt;code&gt;code-review&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;架构治理&lt;/td&gt;&lt;td&gt;&lt;code&gt;improve-codebase-architecture&lt;/code&gt; → &lt;code&gt;codebase-design&lt;/code&gt; → &lt;code&gt;grill-with-docs&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;别人丢来的 issue&lt;/td&gt;&lt;td&gt;&lt;code&gt;triage&lt;/code&gt; → 就绪后 &lt;code&gt;implement&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;答案在别人那里&lt;/td&gt;&lt;td&gt;&lt;code&gt;to-questionnaire&lt;/code&gt; → 收回来再 &lt;code&gt;grill-with-docs&lt;/code&gt; / &lt;code&gt;to-spec&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;上一句没听懂&lt;/td&gt;&lt;td&gt;&lt;code&gt;wait-what&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;只有人能点的步骤&lt;/td&gt;&lt;td&gt;&lt;code&gt;wizard&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;本机状态2026-09-07&quot;&gt;本机状态（2026-09-07）&lt;/h2&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;/td&gt;&lt;td&gt;仓库 &lt;strong&gt;v1.2.3&lt;/strong&gt;，主分支 &lt;code&gt;3cca18b&lt;/code&gt;（2026-09-04）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;实体目录&lt;/td&gt;&lt;td&gt;&lt;code&gt;~/.agents/skills&lt;/code&gt;（37 条）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Pi&lt;/td&gt;&lt;td&gt;&lt;code&gt;~/.pi/agent/skills&lt;/code&gt; 全是符号链接&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;旧副本备份&lt;/td&gt;&lt;td&gt;&lt;code&gt;~/Documents/skills-backup/2026-09-07-pre-matt-only/&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;不在这套里的&lt;/td&gt;&lt;td&gt;&lt;code&gt;pi-goal-writer&lt;/code&gt; 仍在 pi-goal 包内；&lt;code&gt;~/Documents/skills&lt;/code&gt; 个人源未动&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;新开一轮 Pi 会话才会按这 37 条重新加载。&lt;/p&gt;
&lt;h2 id=&quot;核心判断&quot;&gt;核心判断&lt;/h2&gt;
&lt;p&gt;最有价值的不是单个文件，而是这条循环：&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;对齐 → 规格 → 任务切片 → 小步实现 → 自动反馈 → 双轴审查 → 架构持续治理&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;它和 [[Agent Skills 与 SKILL.md 工作流]] 一致：skill 是可组合、可版本化的工作流资产，不是更长的 Prompt。&lt;/p&gt;
&lt;h2 id=&quot;历史记录&quot;&gt;历史记录&lt;/h2&gt;
&lt;h3 id=&quot;2026-07-13-主张已被本页取代&quot;&gt;2026-07-13 主张（已被本页取代）&lt;/h3&gt;
&lt;p&gt;当时对照主分支记为 &lt;strong&gt;39&lt;/strong&gt; 个 &lt;code&gt;SKILL.md&lt;/code&gt;：28 稳定、7 开发中、4 弃用；稳定恰好 14 用户显式 + 14 模型可调用。当时仍把 &lt;code&gt;wizard&lt;/code&gt; 放在开发中，把 &lt;code&gt;writing-great-skills&lt;/code&gt; 当作稳定效率 skill，并收录已不存在的 &lt;code&gt;edit-article&lt;/code&gt; / &lt;code&gt;obsidian-vault&lt;/code&gt;。grilling 仍按「一次只问一题」描述。2026-09-07 以 v1.2.3 覆盖上述数字和分类。&lt;/p&gt;
&lt;h2 id=&quot;原始材料&quot;&gt;原始材料&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/mattpocock/skills&quot;&gt;mattpocock/skills GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/mattpocock/skills/blob/main/.claude-plugin/plugin.json&quot;&gt;v1.2.3 plugin.json&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/mattpocock/skills/blob/main/CHANGELOG.md&quot;&gt;CHANGELOG&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://skills.sh/mattpocock/skills&quot;&gt;skills.sh 页面&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/mattpocock/skills/blob/main/skills/engineering/README.md&quot;&gt;Engineering README&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/mattpocock/skills/blob/main/skills/productivity/README.md&quot;&gt;Productivity README&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/mattpocock/skills/blob/main/skills/in-progress/README.md&quot;&gt;In Progress README&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/mattpocock/skills/blob/main/skills/misc/README.md&quot;&gt;Misc README&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/mattpocock/skills/blob/main/skills/deprecated/README.md&quot;&gt;Deprecated README&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/mattpocock/skills/blob/main/.agents/invocation.md&quot;&gt;Invocation 设计&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;相关&quot;&gt;相关&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[Agent Skills 与 SKILL.md 工作流]]&lt;/li&gt;
&lt;li&gt;[[pi-skills-handbook]]&lt;/li&gt;
&lt;li&gt;[[teach-skill-design]]&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>AI</category><category>agent</category><category>skills</category><category>mattpocock</category></item><item><title>paseo-architecture-blog</title><link>https://feichuans.com/blogs/02-projects/eyrie/paseo-architecture-blog/</link><guid isPermaLink="true">https://feichuans.com/blogs/02-projects/eyrie/paseo-architecture-blog/</guid><description>当多个 AI Coding Agent 同时操作同一项目，端口冲突、WebSocket 碰撞、文件覆盖——这些问题本质上不是配置问题，而是架构问题。本文从第一性原理出发，拆解 Paseo 的四层隔离模型，以及它如何把 O(N×M) 的手工复杂度降维成一份声明式配置。</description><pubDate>Fri, 12 Jun 2026 02:12:24 GMT</pubDate><content:encoded>&lt;h1 id=&quot;agent-并行开发的冲突解决之道从端口碰撞到平台层抽象&quot;&gt;Agent 并行开发的冲突解决之道：从端口碰撞到平台层抽象&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;如果你觉得 &lt;code&gt;PORT=3001 npm run dev&lt;/code&gt; 就够了，那你还没同时跑过三个 Agent。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&quot;问题不在端口在假设&quot;&gt;问题不在端口，在假设&lt;/h2&gt;
&lt;p&gt;2026 年，AI Coding Agent 已经能独立完成从写代码到提 PR 的全流程。但当你想同时跑三个 Agent——一个做登录模块、一个做支付、一个修 Bug——你会发现世界崩塌了。&lt;/p&gt;
&lt;p&gt;不是模型不够好，不是上下文不够长。是 &lt;strong&gt;Agent A 的 dev server 占了 3000 端口，Agent B 的 dev server 直接 EADDRINUSE 炸了&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;更隐蔽的是：Vite 的 HMR WebSocket 固定占用 24678 端口。就算 HTTP 端口全部分配了不同值，三个 Vite 实例的 WebSocket 还是会撞在一起，热更新集体失效。你改了一行代码，浏览器不刷新，Agent 以为自己改坏了，又改回去——然后陷入死循环。&lt;/p&gt;
&lt;p&gt;这不是配置问题。这是&lt;strong&gt;架构问题&lt;/strong&gt;。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;第一性原理三个冲突一个根源&quot;&gt;第一性原理：三个冲突，一个根源&lt;/h2&gt;
&lt;p&gt;我们先把问题拆到最底层。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;冲突一：端口是全局命名空间&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;TCP 端口是一个操作系统级的单例资源。&lt;code&gt;:3000&lt;/code&gt; 同时只能被一个进程绑定。这跟 Redis 的 &lt;code&gt;KEYS *&lt;/code&gt;、跟全局变量、跟单线程模型的共享状态——是同一类问题：&lt;strong&gt;共享可变状态在并发下的必然冲突&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;冲突二：WebSocket 端口是影子资源&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Vite 把 HMR WebSocket 设计为独立端口，且不跟随 HTTP 端口变化。这是框架级别的硬编码假设——“一台机器只会跑一个 Vite”。在 Agent 时代，这个假设失效了。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;冲突三：文件系统是共享的&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;两个 Agent 同时 &lt;code&gt;npm install&lt;/code&gt;，同时写 &lt;code&gt;src/auth.ts&lt;/code&gt;，同时跑 &lt;code&gt;npm run build&lt;/code&gt;。工作目录是同一个。依赖安装互相覆盖，构建产物互相污染。&lt;/p&gt;
&lt;p&gt;这三个冲突有一个共同根源：&lt;strong&gt;开发工具链假定”一个项目 = 一个开发者 = 一个运行实例”&lt;/strong&gt;。Agent 打破了这个假定，但没有提供替代方案。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;四条路径只有一条能治本&quot;&gt;四条路径，只有一条能治本&lt;/h2&gt;
&lt;h3 id=&quot;路径-a手动换端口&quot;&gt;路径 A：手动换端口&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;PORT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;3001&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; npm&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; run&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; dev&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;问题：它能解决 HTTP 端口，解决不了 Vite 的 WebSocket 端口。三个 Agent 就是三个手动配置点。四个服务（前端、后端、数据库、Redis）就是 3×4=12 个手动配置点。而且这些数字需要你自己记住——Agent A 的预览在 &lt;code&gt;:3001&lt;/code&gt;，Agent B 在 &lt;code&gt;:3003&lt;/code&gt;，手机上看还得输 IP:端口。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;结论：O(N×M) 的手工复杂度，不可扩展。&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;路径-bdocker-容器隔离&quot;&gt;路径 B：Docker 容器隔离&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;services&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;  app&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;    ports&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      - &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;0:3000&quot;&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  # 随机宿主机端口&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;问题：Docker 太重。每次创建 Agent 任务需要拉起全套容器，冷启动 10-30 秒。Agent 改一行代码想预览效果，等容器重启的时间够它写完整个函数了。而且容器内的 &lt;code&gt;node_modules&lt;/code&gt; 无法共享，3 个 Agent 就是 3 份完整的 &lt;code&gt;node_modules&lt;/code&gt;，磁盘和安装时间都翻倍。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;结论：隔离足够，但太重、太慢。Agent 需要的是”瞬时隔离”。&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;路径-cgit-worktree--手动编排&quot;&gt;路径 C：Git Worktree + 手动编排&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;git&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; worktree&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; add&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; ../feat-auth&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; feature-auth&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;cd&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; ../feat-auth&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &amp;#x26;&amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;npm&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; ci&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;PORT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;3001&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; npm&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; run&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; dev&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  # 还得记着这个端口&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;问题：Worktree 解决了文件隔离，端口还得手动管。你知道 feat-auth 用了 &lt;code&gt;:3001&lt;/code&gt;，feat-payment 用了 &lt;code&gt;:3002&lt;/code&gt;——但一个月后回来再看，那些数字早就忘了。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;结论：有隔离但缺编排，手工管理的上限是 2 个 Agent。&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;路径-d平台层抽象paseo-的做法&quot;&gt;路径 D：平台层抽象（Paseo 的做法）&lt;/h3&gt;
&lt;p&gt;把端口分配、请求路由、文件隔离从应用层提升到平台层。开发者只声明”我有什么服务”，平台负责分配资源、建立路由、透传流量。&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;你写的：paseo.json（声明式）    →    运行时自动变成：隔离 worktree + 唯一端口 + 可读 URL + WS 透传&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;结论：把 O(N×M) 降到 O(1)。这才是治本。&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;paseo-的四层模型&quot;&gt;Paseo 的四层模型&lt;/h2&gt;
&lt;p&gt;Paseo 的冲突解决不是一个功能，而是一套分层架构。每一层独立解决一个问题，层与层之间通过明确的接口（环境变量、URL 格式、worktree 路径）耦合。&lt;/p&gt;
&lt;h3 id=&quot;第一层git-worktree--文件系统隔离&quot;&gt;第一层：Git Worktree —— 文件系统隔离&lt;/h3&gt;
&lt;p&gt;这是最底层。每个 Agent 获得一个独立的 Git worktree——一份代码的平行副本：&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;~/.paseo/worktrees/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;└── 1vnnm9k3/                    ← 源仓库路径的 hash&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    ├── tidy-fox/                ← Agent A：feature-auth 分支&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    │   ├── src/  node_modules/  paseo.json&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    └── bold-owl/                ← Agent B：feature-payment 分支&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        ├── src/  node_modules/  paseo.json&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Worktree 不同于 &lt;code&gt;git clone&lt;/code&gt;——它共享 &lt;code&gt;.git&lt;/code&gt; 对象库，创建几乎瞬间完成，磁盘开销仅增量文件。每个 Worktree 拥有独立的 &lt;code&gt;node_modules&lt;/code&gt;、独立的 &lt;code&gt;.env&lt;/code&gt;、独立的构建缓存。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;工程意义&lt;/strong&gt;：Worktree 不是新鲜事物（Git 2.5 就有了），但把它作为 Agent 的基础设施原语，是一种设计选择。它比 Docker 轻得多（毫秒级 vs 秒级），比手动 &lt;code&gt;cp -r&lt;/code&gt; 安全得多（git 保证了可追溯和可合并），且天然与 Git 工作流融合（Agent 的改动就是普通分支，review 就是普通 diff）。&lt;/p&gt;
&lt;h3 id=&quot;第二层动态端口分配--网络命名空间隔离&quot;&gt;第二层：动态端口分配 —— 网络命名空间隔离&lt;/h3&gt;
&lt;p&gt;有了独立的工作目录，还需要独立的网络端口。Paseo 的做法是&lt;strong&gt;声明式&lt;/strong&gt;：项目通过 &lt;code&gt;paseo.json&lt;/code&gt; 声明自己有哪些服务，daemon 在运行时分配端口。&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;scripts&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    &quot;web&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &quot;type&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;service&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,                          &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 标记为长期运行的服务&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &quot;command&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;npm run dev -- --port $PASEO_PORT&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 用变量，不写死&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &quot;port&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3000&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;                                 // 默认端口（可选）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    &quot;api&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &quot;type&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;service&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &quot;command&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;go run . --port $PASEO_PORT&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;关键设计决策：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. 为什么是 &lt;code&gt;$PASEO_PORT&lt;/code&gt; 而不是自动检测端口？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;因为自动检测有竞态条件。Agent A 检测到 14001 空闲，但在它 &lt;code&gt;listen()&lt;/code&gt; 之前，Agent B 也可能检测到 14001 空闲。daemon 作为唯一调度者，先分配、后启动，避免了所有竞态。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. 为什么不在 daemon 里强行改写进程的网络栈？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;技术上可以通过 &lt;code&gt;LD_PRELOAD&lt;/code&gt; 劫持 &lt;code&gt;bind()&lt;/code&gt; syscall，或者用网络命名空间。但这会让 dev server 的日志和实际监听的端口不一致，调试噩梦。Paseo 选择了一个更干净的方案：&lt;strong&gt;约定优于注入&lt;/strong&gt;——项目遵守”用 &lt;code&gt;$PASEO_PORT&lt;/code&gt;”的约定，daemon 提供环境变量。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. 为什么端口是分配而非共享？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;因为不同 worktree 的 dev server 可能跑不同版本的代码、不同的数据库状态。共享端口意味着共享后端状态，这会引入更隐蔽的 bug——Agent A 改 API 返回格式，Agent B 的前端莫名其妙报错，因为它们在共用同一个 API 进程。&lt;/p&gt;
&lt;h3 id=&quot;第三层反向代理--人类可读的路由&quot;&gt;第三层：反向代理 —— 人类可读的路由&lt;/h3&gt;
&lt;p&gt;端口是机器友好的（&lt;code&gt;:14001&lt;/code&gt;），但对人类是噪音。Paseo 的反向代理把数字端口映射为可读 URL：&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;http://web--feature-auth--my-app.localhost:6767&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      ─┬── ────┬───── ──┬──&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;       │       │         └─ 项目名&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;       │       └─ 分支名&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;       └─ 服务名&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这个 URL 格式有几个精细的设计：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. 用 &lt;code&gt;--&lt;/code&gt; 分隔，不用 &lt;code&gt;/&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;/&lt;/code&gt; 会让浏览器把 &lt;code&gt;web&lt;/code&gt; 当作路径而非域名的一部分。&lt;code&gt;--&lt;/code&gt; 是合法的主机名字符，且几乎不会出现在实际的服务名或分支名中。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. &lt;code&gt;*.localhost&lt;/code&gt; 不需要 DNS&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;现代操作系统（macOS、Linux、Windows 10+）自动将 &lt;code&gt;*.localhost&lt;/code&gt; 解析到 &lt;code&gt;127.0.0.1&lt;/code&gt;。零配置。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. URL 是确定性的&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;同一个 worktree 的同一个 service，每次重启 URL 不变。因为 URL 只依赖三个稳定的标识符（服务名、分支名、项目名），而不依赖端口号。你可以把这个 URL 存书签、写进 README、发到 Slack——都不会过期（除非 worktree 被 archive）。&lt;/p&gt;
&lt;h3 id=&quot;第四层websocket-透传--代理的最后一公里&quot;&gt;第四层：WebSocket 透传 —— 代理的最后一公里&lt;/h3&gt;
&lt;p&gt;反向代理最难处理的协议就是 WebSocket。HTTP 请求是一次性的——代理转发请求、收到响应、关闭连接。WebSocket 是长连接——代理需要把 TCP 连接升级为全双工隧道，然后一直维持。&lt;/p&gt;
&lt;p&gt;Paseo 的反向代理在检测到 &lt;code&gt;Upgrade: websocket&lt;/code&gt; 请求头后，自动完成升级握手，后续帧双向透明转发。这意味着 Vite 的 HMR、Next.js 的 Fast Refresh、Webpack 的 WDS 热更新全部正常工作，不需要任何额外配置。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;为什么 Nginx 做不到”零配置”？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Nginx 必须显式声明 &lt;code&gt;proxy_set_header Upgrade $http_upgrade&lt;/code&gt; 和 &lt;code&gt;proxy_set_header Connection &quot;upgrade&quot;&lt;/code&gt;。这不是 Nginx 的缺陷——Nginx 的设计目标是通用反向代理，它不能假设所有后端都是 WebSocket。但 Paseo 的设计目标就是 dev server 代理，所有 dev server 都可能发出 WebSocket 升级请求，所以这个假设是安全且合理的。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;工程谱系这不是凭空发明&quot;&gt;工程谱系：这不是凭空发明&lt;/h2&gt;
&lt;p&gt;Paseo 的设计不是凭空冒出来的。它在工程史上有四条清晰的谱系：&lt;/p&gt;
&lt;h3 id=&quot;1-十二因子应用12-factor-app&quot;&gt;1. 十二因子应用（12-Factor App）&lt;/h3&gt;
&lt;p&gt;十二因子的第三因子是”配置存储在环境变量中”——端口不应写死在代码里，而应通过 &lt;code&gt;PORT&lt;/code&gt; 环境变量注入。Paseo 的 &lt;code&gt;$PASEO_PORT&lt;/code&gt; 就是这个原则的 Agent 时代延续。&lt;/p&gt;
&lt;h3 id=&quot;2-服务网格service-mesh&quot;&gt;2. 服务网格（Service Mesh）&lt;/h3&gt;
&lt;p&gt;Istio/Envoy 的 Sidecar 模式：应用不需要知道网络拓扑，sidecar 透明代理所有流量。Paseo daemon 就是 Agent 的 sidecar——Agent 只知道 &lt;code&gt;$PASEO_PORT&lt;/code&gt;，不知道前面有反向代理、不知道还有其他 Agent 实例、不知道自己的 URL 是什么。&lt;/p&gt;
&lt;h3 id=&quot;3-平台工程platform-engineering&quot;&gt;3. 平台工程（Platform Engineering）&lt;/h3&gt;
&lt;p&gt;Heroku、Fly.io、Kubernetes 的核心思想：开发者声明意图，平台负责调度资源。&lt;code&gt;paseo.json&lt;/code&gt; 就是声明，“启动 web 和 api”就是意图，daemon 就是调度器。&lt;/p&gt;
&lt;h3 id=&quot;4-声明式基础设施declarative-infrastructure&quot;&gt;4. 声明式基础设施（Declarative Infrastructure）&lt;/h3&gt;
&lt;p&gt;Terraform、Kubernetes YAML、Nix Flake——“描述想要的状态，而非执行的步骤”。Paseo.json 描述”这个项目有哪些服务”，而不是”在 14001 端口启动 web，在 14002 端口启动 api”。后者是命令式，前者是声明式。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;如果拆成独立模块&quot;&gt;如果拆成独立模块&lt;/h2&gt;
&lt;p&gt;Paseo 的四个核心能力，每一个都可以拆成独立可复用的模块：&lt;/p&gt;








































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;模块&lt;/th&gt;&lt;th&gt;职责&lt;/th&gt;&lt;th&gt;接口&lt;/th&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;strong&gt;Worktree Manager&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;创建/管理隔离工作区，生命周期钩子&lt;/td&gt;&lt;td&gt;&lt;code&gt;Create(opts) → Workspace&lt;/code&gt;, &lt;code&gt;Archive(ws)&lt;/code&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;Port Allocator&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;为多进程分配互不冲突的 HTTP+WS 端口&lt;/td&gt;&lt;td&gt;&lt;code&gt;Allocate(key, PortHTTP/PortWS) → int&lt;/code&gt;&lt;/td&gt;&lt;td&gt;🟢 最易独立&lt;/td&gt;&lt;td&gt;comport (Rust)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Reverse Proxy&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Host 头路由 + WS 自动透传&lt;/td&gt;&lt;td&gt;&lt;code&gt;AddRoute(hostname, target)&lt;/code&gt;, &lt;code&gt;RemoveRoute(hostname)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;🟡 需定义路由管理协议&lt;/td&gt;&lt;td&gt;Caddy/Traefik（偏静态配置）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Env Injector&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;向子进程注入服务地址，实现零配置服务发现&lt;/td&gt;&lt;td&gt;&lt;code&gt;Register(svc)&lt;/code&gt;, &lt;code&gt;EnvFor(svcName) → []string&lt;/code&gt;&lt;/td&gt;&lt;td&gt;🟢 纯数据结构&lt;/td&gt;&lt;td&gt;Docker Compose 网络别名（容器层）&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;组合方式&lt;/strong&gt;：这四个模块只依赖一个共享的 Service 定义结构体，彼此间无代码耦合。你可以只引入 Port Allocator 来管理 monorepo 的并发 dev server，也可以全栈引入四个模块来构建自己的 Agent 平台。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;拆分价值&lt;/strong&gt;：如果有人想写一个新 Agent CLI（不管基于 Claude、Codex、还是自定义模型），不需要从零实现 worktree + 端口管理。直接引入这四个模块，专注做 Agent 逻辑。就像 &lt;code&gt;express&lt;/code&gt; 之于 Node.js HTTP，这些模块可以成为 Agent 开发环境管理领域的标准组件。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;一个可能的开放标准dev-workspace-spec&quot;&gt;一个可能的开放标准：Dev Workspace Spec&lt;/h2&gt;
&lt;p&gt;如果这四层不只是 Paseo 的内部设计，而是社区标准，可以定义一个 &lt;code&gt;dev-workspace.json&lt;/code&gt;：&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;$schema&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;https://dev-workspace-spec.dev/schema.json&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;version&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;1.0&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;project&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;my-app&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;services&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    &quot;web&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &quot;command&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;npm run dev&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &quot;httpPort&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &quot;wsPort&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;24678&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    &quot;api&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &quot;command&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;go run .&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &quot;httpPort&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;8080&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;setup&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;npm ci &amp;#x26;&amp;#x26; cp .env.example .env&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;teardown&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;rm -rf .cache&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这个 spec 可以同时被 Paseo、Multica、CI 系统、甚至 VS Code 插件消费。&lt;code&gt;git clone&lt;/code&gt; 一个项目 → 它自带 &lt;code&gt;dev-workspace.json&lt;/code&gt; → 任何兼容的 runtime 自动创建隔离 worktree + 分配端口 + 启动所有服务 + 生成预览 URL。不管你用什么工具，体验完全一致。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;这定义了 Agent 时代的开发环境标准。&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;结语&quot;&gt;结语&lt;/h2&gt;
&lt;p&gt;Paseo 的四层模型回答了这个问题：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;当开发不再是”一个人 + 一个 IDE”，而是”多个人类 + 多个 Agent + 多台机器”，开发工具链需要做出什么改变？&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;答案不是更好的端口管理器、不是更重的容器、不是更复杂的 CI 配置。答案是&lt;strong&gt;把环境管理从应用层提升到平台层&lt;/strong&gt;——就像 Kubernetes 把部署从”SSH 到机器上手动启动”提升到”声明 Pod 的期望状态”。&lt;/p&gt;
&lt;p&gt;Worktree 隔离、动态端口、反向代理、WS 透传——这些单独看都不新鲜。但把它们组合成一个声明式、零配置、瞬时创建的开发环境层，是 Agent 时代的基础设施创新。&lt;/p&gt;
&lt;p&gt;工具会变，模型会变，但这个”声明意图 → 平台分配 → 透明路由”的模式会留下来。因为无论是什么 Agent、什么框架、什么语言，&lt;strong&gt;不想管端口&lt;/strong&gt;是普遍需求，“&lt;strong&gt;写完代码能立刻看到效果&lt;/strong&gt;”是永远不会过时的体验。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;Paseo 是开源项目（AGPL-3.0），代码托管在 &lt;a href=&quot;https://github.com/getpaseo/paseo&quot;&gt;github.com/getpaseo/paseo&lt;/a&gt;。&lt;/em&gt;&lt;/p&gt;</content:encoded><category>software-engineering</category><category>ai-agent</category><category>platform-engineering</category><category>architecture</category></item><item><title>让界面「有感觉」的细节</title><link>https://feichuans.com/blogs/details-that-make-interfaces-feel-better/</link><guid isPermaLink="true">https://feichuans.com/blogs/details-that-make-interfaces-feel-better/</guid><description>好的界面从来不是一个大招搞定的，而是一堆小细节叠加出来的。这篇文章整理了让 UI 从「能用」变成「好用」的实用技巧，附带可交互的 demo。</description><pubDate>Sun, 10 May 2026 07:00:00 GMT</pubDate><content:encoded>好的界面从来不是一个大招搞定的，而是一堆小细节叠加出来的。这篇文章整理了让 UI 从「能用」变成「好用」的实用技巧，附带可交互的 demo。</content:encoded><category>前端</category><category>CSS</category><category>UI</category><category>设计工程</category></item><item><title>简历计划</title><link>https://feichuans.com/blogs/03-areas/%E8%81%8C%E4%B8%9A%E7%94%9F%E6%B6%AF/%E7%AE%80%E5%8E%86%E8%AE%A1%E5%88%92/</link><guid isPermaLink="true">https://feichuans.com/blogs/03-areas/%E8%81%8C%E4%B8%9A%E7%94%9F%E6%B6%AF/%E7%AE%80%E5%8E%86%E8%AE%A1%E5%88%92/</guid><description>收集我觉得不错的简历进行学习；含 3 份简历 OCR、前端 vs Agent 前端写法对比与 ATS 机制</description><pubDate>Fri, 06 Mar 2026 15:19:41 GMT</pubDate><content:encoded>&lt;p&gt;所有简历都在关键信息进行了打码, 请放心观看&lt;/p&gt;
&lt;h2 id=&quot;1&quot;&gt;1&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://img.feichuans.com/file/1772810468996_20260306232045804.png&quot; alt=&quot;image.png&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;2&quot;&gt;2&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://img.feichuans.com/file/1773113689908_20260310113425583.png&quot; alt=&quot;image.png&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;3&quot;&gt;3&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://img.feichuans.com/file/1783874134366_cb5dc577b817d8d43f7d5a32a158637d.png&quot; alt=&quot;cb5dc577b817d8d43f7d5a32a158637d.png&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;2026-08-05--三份简历-ocr-提取--前端-vs-agent-前端写法对比--ats-机制&quot;&gt;2026-08-05 | 三份简历 OCR 提取 + 前端 vs Agent 前端写法对比 + ATS 机制&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;说明：下方简历 1-3 的正文为图片 OCR 提取（macOS Vision 框架），个别字符可能有识别误差，数字与专有名词已尽量保留。原始图片见上方。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;一简历-1纯前端方向27-届两段中大厂实习&quot;&gt;一、简历 1：纯前端方向（27 届，两段中大厂实习）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;教育：2023.09-2027.06 计算机科学与技术；CET6 622；GPA 专业前 30%；省服务外包大赛三等奖、挑战杯人工智能+专项赛全国二等奖&lt;/li&gt;
&lt;li&gt;实习 A：海康威视（2025.11-2026.03）协议管理平台 PMP2.0 前端开发
&lt;ul&gt;
&lt;li&gt;设计双栈（idStack/pathStack）高亮引用，JSONPath 路径追踪与整块锁定高亮，MutationObserver 支持虚拟滚动动态同步&lt;/li&gt;
&lt;li&gt;双式大数据树渲染：&amp;#x3C;1300 行用 el-table，超阈值切换 xntree 虚拟树，treeToList 扁平化 + 深拷贝隔离响应式&lt;/li&gt;
&lt;li&gt;Vite 构建优化：按需加载 + Tree Shaking，首屏 LCP 缩短 1.7s&lt;/li&gt;
&lt;li&gt;工业协议业务组件：Modbus 寄存器动态映射、协议导入自动化、树形表格递归级联，跨系统操作耗时降约 70%&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;实习 B：杭州聚数智创（2025.03-2025.06）实验室安全准入系统
&lt;ul&gt;
&lt;li&gt;qiankun 微前端架构，模块拆分与子应用协作&lt;/li&gt;
&lt;li&gt;富文本编辑器调研对比，WangEditor v5 二次封装（题库图文混排、多媒体）&lt;/li&gt;
&lt;li&gt;vue-i18n 国际化，主应用下发语言上下文动态切换文本/日期/数字格式&lt;/li&gt;
&lt;li&gt;大文件分片上传：MD5 校验、断点续传、失败重试&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;点评&lt;/strong&gt;：典型传统前端简历。技术栈全、性能数字多（LCP、耗时降 70%），但&lt;strong&gt;技能栏零 AI 关键词&lt;/strong&gt;，投 Agent 岗会被 ATS 过滤；且每条职责偏”做了什么”，少数有量化但缺口径说明。&lt;/p&gt;
&lt;h3 id=&quot;二简历-2前端--ai-萌芽26-届react-native-交易所&quot;&gt;二、简历 2：前端 + AI 萌芽（26 届，React Native 交易所）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;技能栏：前端基础（HTML5/CSS3/ES6+/TS）、框架生态（React/Next.js/React Native/Zustand/Tailwindcss/Vue）、工程化（Vite/Webpack/Turborepo/npm/pnpm/ESLint/Prettier）、服务端（Node.js/NestJS/MongoDB）、&lt;strong&gt;AI 应用落地（LangChain.js/RAG 架构实践）&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;实习：Hibit 加密货币交易所 App（Android/iOS）双端开发（2025.02-2025.08）
&lt;ul&gt;
&lt;li&gt;行情展示、资产信息等核心模块交互与性能优化&lt;/li&gt;
&lt;li&gt;独立负责 RN 旧版升级至最新稳定版并迁移新架构，解决依赖兼容性&lt;/li&gt;
&lt;li&gt;分模块验证 + 回滚机制，升级对线上用户无感&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;另一段经历技术栈：TypeScript / Web Performance API / Web Vitals / React Native / Vue2&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;点评&lt;/strong&gt;：过渡形态。技能栏已带一行 AI（LangChain.js/RAG），但项目主体仍是纯前端（RN 升级），AI 没有项目证据支撑——是”写了关键词但面试撑不住追问”的典型。&lt;/p&gt;
&lt;h3 id=&quot;三简历-3agent-前端向中南大学-98528-届&quot;&gt;三、简历 3：Agent 前端向（中南大学 985，28 届）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;教育：2024.09-2028.06 计算机科学与技术；天梯赛全国三等奖、湖南省程序设计大赛二等奖、蓝桥杯省一等奖&lt;/li&gt;
&lt;li&gt;技能栏（精选）：前端 React/Vue3/Next.js；客户端 Electron/Tauri/Flutter；后端 Node.js(Express)/Spring Boot；&lt;strong&gt;AI：了解 LLM、Agent、RAG、MCP、Skill 和 Harness 等内容，熟悉 Codex 和 Claude Code 的使用&lt;/strong&gt;；工程化 Webpack/Vite/Rollup；性能优化（SSR/SSG、FCP/LCP 实践）；Git/Docker/Linux/Nginx/CI/CD&lt;/li&gt;
&lt;li&gt;项目 1：CSU Star 一站式平台（团队负责人，Next.js+App Router+Zustand+Axios+Tailwind+TS+COS）
&lt;ul&gt;
&lt;li&gt;Axios 拦截器双 Token 无感刷新；RBAC+Zustand 多角色鉴权&lt;/li&gt;
&lt;li&gt;腾讯云 COS+CDN：防盗链、QPS 限流、Header 安全配置，防 XSS/CSRF/DDOS，异常请求拦截率 89%&lt;/li&gt;
&lt;li&gt;分页请求/懒加载/骨架屏/静态缓存，LCP 降至 0.26s；GitHub Actions CI/CD 四端同步迭代&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;项目 2：FaceIt 模拟面试（前端开发，React19+TS+React Router+Zustand+SSE+TTS）
&lt;ul&gt;
&lt;li&gt;封装 useStreamResponse / useTypewriterText 实现打字机 SSE 流式输出&lt;/li&gt;
&lt;li&gt;react-markdown + remark-gfm + react-syntax-highlighter，白名单安全清洗&lt;/li&gt;
&lt;li&gt;讯飞 ASR + Bilibili TTS → 浏览器 TTS 降级策略，纯语音链路面试&lt;/li&gt;
&lt;li&gt;Zustand 原子化状态，持久化认证缓存与对话上下文&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;项目 3：World Echo AI 音乐生成（客户端开发，Flutter+Dart+Provider+Dio+SSE+socket.io+just_audio）
&lt;ul&gt;
&lt;li&gt;文字/图片/声音多模态输入生成歌曲；Dio 请求层封装 Token 注入、SSE 流式响应解析&lt;/li&gt;
&lt;li&gt;SSE 实时展示生成阶段/进度/结果，优化长耗时等待&lt;/li&gt;
&lt;li&gt;socket.io 广场歌曲无感推送；just_audio 全局播放器&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;点评&lt;/strong&gt;：方向正确的 Agent 前端简历——技能栏点名 LLM/Agent/RAG/MCP/Skill/Harness，三个项目两个是 AI 应用（SSE 流式、RAG、语音链路、安全清洗全都有）。&lt;strong&gt;缺口&lt;/strong&gt;：AI 链路缺 Agent 特有量化（任务完成率、工具调用成功率、端到端延迟、token 成本），且未写统计口径；面试官对 SSE 打字机、markdown 清洗、TTS 降级每个点都可以连续追问（见[[面试题]] 的 AI 面经高频考点）。&lt;/p&gt;
&lt;h3 id=&quot;四前端-vs-agent-前端简历四个维度差异&quot;&gt;四、前端 vs Agent 前端简历：四个维度差异&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;th&gt;Agent 前端&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;/td&gt;&lt;td&gt;框架/工程化/网络/测试，按工具名分类&lt;/td&gt;&lt;td&gt;写能力不写框架名：ReAct 推理循环、工具编排、错误恢复/降级、Agent 与 Workflow 选型边界&lt;/td&gt;&lt;td&gt;卡码笔记四方向写法&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;项目结构&lt;/td&gt;&lt;td&gt;功能清单 + 性能数字&lt;/td&gt;&lt;td&gt;四要素：一句话总结+业务场景+核心能力；技术决策+量化结果；难点=问题+方案+效果&lt;/td&gt;&lt;td&gt;手把手改简历帖（浏览 8666）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;量化指标&lt;/td&gt;&lt;td&gt;LCP/FCP、首屏耗时、包体积&lt;/td&gt;&lt;td&gt;追加：任务完成率、工具调用成功率、幻觉率、推理延迟、首 Token 延迟、QPS、Token 成本、显存&lt;/td&gt;&lt;td&gt;卡码笔记指标分类&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;JD 关键词&lt;/td&gt;&lt;td&gt;React/Vue/TS/Webpack/性能/微前端&lt;/td&gt;&lt;td&gt;SSE/WebSocket、RAG、MCP、Function Calling、LangChain、Prompt、向量库、Memory、Eval/Harness&lt;/td&gt;&lt;td&gt;BOSS JD 对比（薪资 20-40K vs 40-150K+）&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;核心洞察（BOSS JD 帖）：&lt;strong&gt;AI Agent 工程师不是替代前端，而是在前端之上的能力叠加&lt;/strong&gt;——“传统前端基础（必备）”。&lt;/p&gt;
&lt;p&gt;常见减分项（多帖交叉）：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;周期短却堆 RAG/流式/鉴权/复杂治理 → 深度存疑&lt;/li&gt;
&lt;li&gt;Agent 只写”调模型、接工具”，不触及运行时、状态机、评测、观测与人在回路&lt;/li&gt;
&lt;li&gt;每个技术名词都是追问入口：写「基于 RAG 优化问答」就要能答为什么用 RAG、文档怎么切、召回怎么做、准确率怎么评估、知识怎么更新&lt;/li&gt;
&lt;li&gt;技术栈罗列与”把 package.json 打印出来”无异&lt;/li&gt;
&lt;li&gt;性能数字无统计口径与复现方式&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;五ats-机制详解2026&quot;&gt;五、ATS 机制详解（2026）&lt;/h3&gt;
&lt;h4 id=&quot;1-ats-是什么&quot;&gt;1. ATS 是什么&lt;/h4&gt;
&lt;p&gt;ATS（Applicant Tracking System）自动收集、解析、评分、排序简历。流程：接收 → 解析文本 → 与 JD 关键词匹配 → 评分排序（只推荐前 10-20%）→ 人工审核。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;反传言&lt;/strong&gt;：92% 招聘者称自家 ATS 不会自动拒人；真实机制是 99.7% 用关键词/Boolean 搜索排序——匹配差的简历沉到后台第 5 页，不是被拒而是没人看到。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2026 变化&lt;/strong&gt;：主流 ATS 在经典解析器上加 LLM 语义打分（Oracle 提交即打 0-5 分），能判断经历含义与 JD 对齐度，非纯关键词。&lt;/p&gt;
&lt;h4 id=&quot;2-各家-ats-打分差异&quot;&gt;2. 各家 ATS 打分差异&lt;/h4&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;Workday&lt;/td&gt;&lt;td&gt;重关键词匹配 + 严格日期解析&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Greenhouse&lt;/td&gt;&lt;td&gt;不做算法评分，拒绝均为人工决定&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Lever&lt;/td&gt;&lt;td&gt;AI 语义匹配，认可同义词&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;iCIMS&lt;/td&gt;&lt;td&gt;Boolean 式技能匹配&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Taleo&lt;/td&gt;&lt;td&gt;最老精确匹配，最严格&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h4 id=&quot;3-关键词策略&quot;&gt;3. 关键词策略&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;目标匹配度 75-85%（Jobscan 推荐 75%，严格 JD 要 90%）；&lt;strong&gt;100% 通常=堆砌，过不了人工关&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;关键词嵌进真实 bullet，不平铺&lt;/li&gt;
&lt;li&gt;国内（AI 筛简历帖）：NLP 语义理解已替代 70% 基础人筛；能区分「优化了接口速度」vs「延迟 500ms→50ms」；写 RAG 必须配套向量库/Embedding/LangChain，技术栈不闭环会降分&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;按 JD 定制两个版本&lt;/strong&gt;：投 Agent 岗缺 AI 关键词直接沉底；投纯前端岗堆 RAG/MCP 反被判不相关&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;4-格式规则&quot;&gt;4. 格式规则&lt;/h4&gt;
&lt;p&gt;标准字体（Arial/Calibri）、11-12pt、简单项目符号、标准板块标题、单栏布局、.docx 或简单 PDF；避免图片/表格/文本框/分栏。约 35% 淘汰与能力无关，纯格式/关键词问题。&lt;/p&gt;
&lt;h3 id=&quot;六来源&quot;&gt;六、来源&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;BOSS JD 对比：&lt;a href=&quot;https://www.nowcoder.com/discuss/885626300134588416&quot;&gt;https://www.nowcoder.com/discuss/885626300134588416&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;手把手改简历：&lt;a href=&quot;https://www.nowcoder.com/discuss/883032780106432512&quot;&gt;https://www.nowcoder.com/discuss/883032780106432512&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;卡码笔记四方向写法：&lt;a href=&quot;https://notes.kamacoder.com/jianli/llm/llm_15.html&quot;&gt;https://notes.kamacoder.com/jianli/llm/llm_15.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;简历减分问题：&lt;a href=&quot;https://www.nowcoder.com/discuss/864516869779222528&quot;&gt;https://www.nowcoder.com/discuss/864516869779222528&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;前端转 Agent 信号：&lt;a href=&quot;https://www.nowcoder.com/discuss/879078076276105216&quot;&gt;https://www.nowcoder.com/discuss/879078076276105216&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;27 届 Agent 简历写法（50 追问）：&lt;a href=&quot;https://www.nowcoder.com/discuss/906102877850980352&quot;&gt;https://www.nowcoder.com/discuss/906102877850980352&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;AI 筛简历：&lt;a href=&quot;https://www.nowcoder.com/discuss/867127642368065536&quot;&gt;https://www.nowcoder.com/discuss/867127642368065536&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;ATS 2026 指南：&lt;a href=&quot;https://www.clever.cv/zh/blog/ats-friendly-resume-guide-2026&quot;&gt;https://www.clever.cv/zh/blog/ats-friendly-resume-guide-2026&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;ATS 七步法：&lt;a href=&quot;https://developer.volcengine.com/articles/7660471069102669878&quot;&gt;https://developer.volcengine.com/articles/7660471069102669878&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;关键词匹配 Prompt：&lt;a href=&quot;https://aitoolsguidebook.com/zh/articles/resume-keyword-matching-prompts/&quot;&gt;https://aitoolsguidebook.com/zh/articles/resume-keyword-matching-prompts/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;ATS 打分机制：&lt;a href=&quot;https://resumeoptimizerpro.com/blog/how-is-ats-score-calculated&quot;&gt;https://resumeoptimizerpro.com/blog/how-is-ats-score-calculated&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Jobscan AI 筛简历：&lt;a href=&quot;https://www.jobscan.co/blog/blog-ai-resume-screening/&quot;&gt;https://www.jobscan.co/blog/blog-ai-resume-screening/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://img.feichuans.com/file/1786435843244_20260811161032212.png&quot; alt=&quot;image.png&quot;&gt;&lt;/p&gt;</content:encoded><category>面试</category><category>前端</category><category>简历</category><category>Agent</category><category>ATS</category></item><item><title>OpenClaw 架构解析：一个生产级 AI Agent 是如何设计的</title><link>https://feichuans.com/blogs/03-areas/ai/openclaw-%E6%9E%B6%E6%9E%84%E8%A7%A3%E6%9E%90%E4%B8%80%E4%B8%AA%E7%94%9F%E4%BA%A7%E7%BA%A7-ai-agent-%E6%98%AF%E5%A6%82%E4%BD%95%E8%AE%BE%E8%AE%A1%E7%9A%84/</link><guid isPermaLink="true">https://feichuans.com/blogs/03-areas/ai/openclaw-%E6%9E%B6%E6%9E%84%E8%A7%A3%E6%9E%90%E4%B8%80%E4%B8%AA%E7%94%9F%E4%BA%A7%E7%BA%A7-ai-agent-%E6%98%AF%E5%A6%82%E4%BD%95%E8%AE%BE%E8%AE%A1%E7%9A%84/</guid><description>深入解析 Claude tool use、Anthropic SDK、Vercel AI SDK 与 pi-ai 的架构差异，结合 git worktree 实现多 Agent 并行隔离执行，附完整代码示例。</description><pubDate>Thu, 05 Mar 2026 09:29:41 GMT</pubDate><content:encoded>&lt;h1 id=&quot;openclaw-架构解析一个生产级-ai-agent-是如何设计的&quot;&gt;OpenClaw 架构解析：一个生产级 AI Agent 是如何设计的&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;OpenClaw / MiniClaw / Anthropic SDK / Vercel AI SDK / pi-ai / parallel-code / Git Worktree&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;目录&quot;&gt;目录&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;#1-openclaw-%E6%9E%B6%E6%9E%84%E4%B8%8E%E6%9C%8D%E5%8A%A1%E5%88%86%E5%B1%82&quot;&gt;OpenClaw 架构与服务分层&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#2-claude-agent-%E5%86%85%E9%83%A8%E5%86%B3%E7%AD%96%E6%B5%81%E7%A8%8B&quot;&gt;Claude Agent 内部决策流程&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#3-%E5%B7%A5%E5%85%B7%E8%B0%83%E7%94%A8%E7%9A%84%E5%AE%8C%E6%95%B4%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F&quot;&gt;工具调用的完整生命周期&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#4-anthropic-sdktool-%E4%BC%A0%E5%85%A5%E4%B8%8E%E8%83%8C%E5%90%8E%E9%80%BB%E8%BE%91&quot;&gt;Anthropic SDK：Tool 传入与背后逻辑&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#5-vercel-ai-sdk%E8%87%AA%E5%8A%A8%E5%8C%96-loop&quot;&gt;Vercel AI SDK：自动化 Loop&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#6-%E4%B8%89%E6%96%B9-sdk-%E6%A8%AA%E5%90%91%E5%AF%B9%E6%AF%94&quot;&gt;三方 SDK 横向对比&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#7-parallel-code-%E5%A4%9A-agent-%E5%B9%B6%E8%A1%8C%E6%9E%B6%E6%9E%84&quot;&gt;parallel-code 多 Agent 并行架构&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#8-git-worktree-%E5%AE%8C%E6%95%B4%E8%A7%A3%E6%9E%90&quot;&gt;Git Worktree 完整解析&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#9-%E7%94%A8-pi-ai-%E5%A4%8D%E7%8E%B0-parallel-code&quot;&gt;用 pi-ai 复现 parallel-code&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id=&quot;1-openclaw-架构与服务分层&quot;&gt;1. OpenClaw 架构与服务分层&lt;/h2&gt;
&lt;h3 id=&quot;定位&quot;&gt;定位&lt;/h3&gt;
&lt;p&gt;OpenClaw 是一个网关（Gateway），一个坐在 AI 模型和外部世界中间的单体运行时，不是框架。&lt;/p&gt;
&lt;h3 id=&quot;五层服务&quot;&gt;五层服务&lt;/h3&gt;
&lt;p&gt;第一层：渠道适配层（Channel Adapter）&lt;/p&gt;
&lt;p&gt;把 Discord、Telegram 等不同平台的输入转成统一消息格式，顺便提取附件。一个 Agent 挂多个渠道靠的就是这层。&lt;/p&gt;
&lt;p&gt;第二层：网关服务器（Gateway Server）&lt;/p&gt;
&lt;p&gt;流量总入口。Session Router 判断消息属于哪个会话，然后交给 Lane Queue（车道队列）做并发管理，避免多个对话同时跑的时候请求撞车或上下文串了。&lt;/p&gt;
&lt;p&gt;第三层：Agent Runner（智能体运行器）&lt;/p&gt;
&lt;p&gt;管模型选择、API Key 轮换冷却、提示词拼装和上下文窗口。&lt;/p&gt;
&lt;p&gt;第四层：Agent Runtime / Agentic Loop&lt;/p&gt;
&lt;p&gt;跑完整的 AI 循环：从会话历史和记忆里拼上下文 → 调模型 → 执行工具（浏览器自动化、文件操作、Canvas、定时任务等）→ 把更新后的状态存下来。&lt;/p&gt;
&lt;p&gt;就是模型说”我要调工具”，系统执行，结果塞回去，模型再想，再调，直到搞定为止。&lt;/p&gt;
&lt;p&gt;第五层：Memory &amp;#x26; Skills&lt;/p&gt;
&lt;p&gt;文件都很朴素：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;events.jsonl&lt;/code&gt;：逐行审计日志&lt;/li&gt;
&lt;li&gt;&lt;code&gt;MEMORY.md&lt;/code&gt;：Markdown 格式的记忆，存摘要和经验&lt;/li&gt;
&lt;li&gt;&lt;code&gt;skills/&lt;/code&gt;：Markdown 技能文件，按关键词匹配动态加载&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;mini-claw-生态&quot;&gt;Mini Claw 生态&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;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;htlin222/mini-claw&lt;/td&gt;&lt;td&gt;TypeScript&lt;/td&gt;&lt;td&gt;极简替代品&lt;/td&gt;&lt;td&gt;理解 Agent Loop&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;xprilion/miniclaw&lt;/td&gt;&lt;td&gt;Python&lt;/td&gt;&lt;td&gt;生产就绪版&lt;/td&gt;&lt;td&gt;完整服务分层实现&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;mattdef/miniclaw&lt;/td&gt;&lt;td&gt;Rust&lt;/td&gt;&lt;td&gt;边缘计算版&lt;/td&gt;&lt;td&gt;&amp;#x3C;15MB，256MB RAM 能跑&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;PLKwan/miniclaw&lt;/td&gt;&lt;td&gt;—&lt;/td&gt;&lt;td&gt;AI-native 无配置版&lt;/td&gt;&lt;td&gt;skills-over-features 思路&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id=&quot;2-claude-agent-内部决策流程&quot;&gt;2. Claude Agent 内部决策流程&lt;/h2&gt;
&lt;h3 id=&quot;工具类型决策&quot;&gt;工具类型决策&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;收到用户消息&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ↓&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;意图识别：是否需要实时信息？&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ↓&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;选择工具类型：&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  web_search（宽泛查询）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    → web_fetch（深入具体页面）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    → bash/file（文件操作任务）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    → 直接回答（知识性问题，无需工具）&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;和-openclaw-的对照&quot;&gt;和 OpenClaw 的对照&lt;/h3&gt;

































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;OpenClaw 层&lt;/th&gt;&lt;th&gt;Claude 的对应&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Channel Adapter&lt;/td&gt;&lt;td&gt;claude.ai 界面 / API → 统一消息格式&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Session Router&lt;/td&gt;&lt;td&gt;对话历史上下文&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Agent Runner&lt;/td&gt;&lt;td&gt;系统提示词 + 工具列表注入&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Agentic Loop&lt;/td&gt;&lt;td&gt;tool_call → result → 再推理 → 再 tool_call&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Memory (AGENTS.md)&lt;/td&gt;&lt;td&gt;系统提示 + 用户偏好&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Skills&lt;/td&gt;&lt;td&gt;&lt;code&gt;/mnt/skills/&lt;/code&gt; 文件系统&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id=&quot;3-工具调用的完整生命周期&quot;&gt;3. 工具调用的完整生命周期&lt;/h2&gt;
&lt;h3 id=&quot;第-1-步发送请求带工具定义&quot;&gt;第 1 步：发送请求（带工具定义）&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;POST /v&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/messages&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;model&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;claude-sonnet-4-6&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;tools&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &quot;name&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;get_weather&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &quot;description&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;查询指定城市的天气&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &quot;input_schema&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;        &quot;type&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;object&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;        &quot;properties&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;          &quot;city&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: { &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;string&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;        &quot;required&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: [&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;city&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;messages&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    { &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;user&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;新加坡今天天气怎么样？&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;第-2-步模型返回-tool_use-块&quot;&gt;第 2 步：模型返回 &lt;code&gt;tool_use&lt;/code&gt; 块&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;role&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;assistant&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;content&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &quot;type&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;tool_use&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &quot;id&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;toolu_01XyZ&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &quot;name&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;get_weather&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &quot;input&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: { &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&quot;city&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Singapore&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;stop_reason&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;tool_use&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;注意 &lt;code&gt;stop_reason&lt;/code&gt; 是 &lt;code&gt;tool_use&lt;/code&gt;，说明模型主动停下来等结果，不是对话结束。&lt;/p&gt;
&lt;h3 id=&quot;第-3-步执行工具回传结果&quot;&gt;第 3 步：执行工具，回传结果&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;messages&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    { &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;user&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;新加坡今天天气怎么样？&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &quot;role&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;assistant&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &quot;content&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: [{ &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;tool_use&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;toolu_01XyZ&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; }]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &quot;role&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;user&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &quot;content&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;          &quot;type&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;tool_result&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;          &quot;tool_use_id&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;toolu_01XyZ&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;          &quot;content&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;{ &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;temp&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;: 31, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;humidity&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;: 84, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;condition&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;Partly Cloudy&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; }&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;注意 &lt;code&gt;tool_result&lt;/code&gt; 挂在 &lt;code&gt;user&lt;/code&gt; role 下面，不是 &lt;code&gt;assistant&lt;/code&gt;。工具执行的结果属于”外部世界”的返回，放在 user 侧。&lt;/p&gt;
&lt;h3 id=&quot;第-4-步生成最终答案&quot;&gt;第 4 步：生成最终答案&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;role&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;assistant&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;content&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: [{ &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;text&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&quot;text&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;新加坡今天天气部分多云，气温 31°C...&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; }],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;stop_reason&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;end_turn&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;流程总结&quot;&gt;流程总结&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;用户消息&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ↓&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;模型 → stop_reason: &quot;tool_use&quot;   （模型不知道天气，停下来）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ↓&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;你的程序调用真实 API&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ↓&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;tool_result 作为 user 消息回传&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ↓&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;模型 → stop_reason: &quot;end_turn&quot;   （现在知道了，给出答案）&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;一句话：模型本身不执行任何工具。它只输出”调用意图”，HTTP 请求、数据库查询这些活儿全是你的程序干的。模型是调度者，不是执行者。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;4-anthropic-sdktool-传入与背后逻辑&quot;&gt;4. Anthropic SDK：Tool 传入与背后逻辑&lt;/h2&gt;
&lt;h3 id=&quot;python-sdk-示例&quot;&gt;Python SDK 示例&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; anthropic&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; json&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;client &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; anthropic.Anthropic()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tools &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        &quot;name&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;get_weather&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        &quot;description&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;查询指定城市的实时天气。当用户询问天气时调用此工具。&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        &quot;input_schema&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;            &quot;type&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;object&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;            &quot;properties&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;                &quot;city&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;                    &quot;type&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;string&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;                    &quot;description&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;城市名，如 Singapore 或 New York&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;                },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;                &quot;unit&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;                    &quot;type&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;string&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;                    &quot;enum&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: [&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;celsius&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;fahrenheit&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;                    &quot;description&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;温度单位&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;                }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;            &quot;required&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: [&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;city&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 第一次调用&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;response &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; client.messages.create(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    model&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;claude-sonnet-4-6&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    max_tokens&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1024&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    tools&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tools,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    messages&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[{&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;user&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;新加坡今天多少度？&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tool_use_id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; response.content[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;].id&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;result &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; get_weather(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;**&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;response.content[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;].input)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 回传结果&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;response2 &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; client.messages.create(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    model&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;claude-sonnet-4-6&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    max_tokens&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1024&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    tools&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tools,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    messages&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        {&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;user&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;新加坡今天多少度？&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        {&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;assistant&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: response.content},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;            &quot;role&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;user&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;            &quot;content&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;                {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;                    &quot;type&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;tool_result&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;                    &quot;tool_use_id&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: tool_use_id,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;                    &quot;content&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: json.dumps(result)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;                }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;背后的-5-个逻辑&quot;&gt;背后的 5 个逻辑&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;tools&lt;/code&gt; 参数被注入系统提示词&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;传入 &lt;code&gt;tools&lt;/code&gt; 时，API 会自动拼一段系统提示：&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;In this environment you have access to a set of tools...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&amp;#x3C;functions&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;{ &quot;name&quot;: &quot;get_weather&quot;, &quot;description&quot;: &quot;...&quot;, &quot;parameters&quot;: { ... } }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&amp;#x3C;/functions&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;工具不是什么魔法，就是被转成 prompt 里的文字描述。模型靠读这段文字来”学会”怎么调用。&lt;/p&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;&lt;code&gt;tool_result&lt;/code&gt; 挂在 &lt;code&gt;user&lt;/code&gt; role 下&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;消息模型只有 &lt;code&gt;user&lt;/code&gt; 和 &lt;code&gt;assistant&lt;/code&gt; 两种 role，工具执行属于外部世界的返回，归 user 侧。&lt;/p&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;&lt;code&gt;tool_choice&lt;/code&gt; 控制调用策略&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tool_choice&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;auto&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}                        &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 默认，模型自行决定&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tool_choice&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;any&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}                         &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 必须调用某个工具&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tool_choice&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;tool&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;get_weather&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;} &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 只能调这个工具&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tool_choice&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;none&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}                        &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 禁止调用工具&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;并行工具调用&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;模型可以在一次响应里返回多个 &lt;code&gt;tool_use&lt;/code&gt; 块，全部执行完后一起回传：&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &quot;role&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;user&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &quot;content&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        {&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;tool_result&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;tool_use_id&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;toolu_001&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;31°C&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        {&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;tool_result&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;tool_use_id&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;toolu_002&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;12°C&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;5&quot;&gt;
&lt;li&gt;Tool Runner（自动化 Agentic Loop，Beta）&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Tool Runner 是个可迭代对象，自动循环处理工具调用。token 用量超过阈值时会自动压缩生成摘要，让长任务可以突破上下文窗口限制。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;5-vercel-ai-sdk自动化-loop&quot;&gt;5. Vercel AI SDK：自动化 Loop&lt;/h2&gt;
&lt;h3 id=&quot;和原生-sdk-的区别&quot;&gt;和原生 SDK 的区别&lt;/h3&gt;
&lt;p&gt;原生 SDK 给你原材料，loop 自己写。Vercel AI SDK 给你成品流水线，&lt;code&gt;execute&lt;/code&gt; 绑定加自动循环。&lt;/p&gt;
&lt;h3 id=&quot;示例&quot;&gt;示例&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;typescript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { tool, generateText } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;ai&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { anthropic } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;@ai-sdk/anthropic&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { z } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;zod&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 定义时直接绑定执行函数&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; getWeather&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; tool&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  description: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;查询指定城市的实时天气&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  inputSchema: z.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;object&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    city: z.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;describe&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;城市名&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    unit: z.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;enum&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;([&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;celsius&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;fahrenheit&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;optional&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  execute&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;async&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ({ &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;city&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;unit&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;celsius&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; }) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; data&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; fetchWeatherAPI&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(city);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { temp: data.temp, condition: data.condition };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;});&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 自动循环直到没有工具调用&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;text&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;steps&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; generateText&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  model: &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;anthropic&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;claude-sonnet-4-6&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  tools: { getWeather },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  stopWhen: &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;stepCountIs&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  prompt: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;新加坡和东京今天天气怎样，哪个更适合旅游？&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;sdk-内部自动干了什么&quot;&gt;SDK 内部自动干了什么&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;你调用 generateText(tools, stopWhen)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ↓&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;SDK 发请求 → 模型返回 tool_use&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ↓&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;SDK 自动找到 execute 函数并调用&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ↓&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;SDK 自动构建 tool_result 消息&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ↓&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;SDK 自动再发一次请求（新的一步）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ↓&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;重复，直到 stop_reason = &quot;end_turn&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ↓&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;返回最终 { text, steps }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;人工审批门控ai-sdk-6&quot;&gt;人工审批门控（AI SDK 6）&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;typescript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; deleteFile&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; tool&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  description: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;删除文件&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  inputSchema: z.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;object&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({ path: z.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() }),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  needsApproval: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,   &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 暂停，等人点确认&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  execute&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;async&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ({ &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; }) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;/* ... */&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;三种执行位置&quot;&gt;三种执行位置&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;th&gt;怎么触发&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Server Tool&lt;/td&gt;&lt;td&gt;服务器（Node.js）&lt;/td&gt;&lt;td&gt;&lt;code&gt;execute&lt;/code&gt; 函数自动调用&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Client Auto Tool&lt;/td&gt;&lt;td&gt;浏览器&lt;/td&gt;&lt;td&gt;&lt;code&gt;onToolCall&lt;/code&gt; 回调&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Client UI Tool&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;hr&gt;
&lt;h2 id=&quot;6-三方-sdk-横向对比&quot;&gt;6. 三方 SDK 横向对比&lt;/h2&gt;
&lt;h3 id=&quot;工具定义方式&quot;&gt;工具定义方式&lt;/h3&gt;





























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;SDK&lt;/th&gt;&lt;th&gt;Schema 格式&lt;/th&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;Anthropic 原生&lt;/td&gt;&lt;td&gt;JSON Schema（纯对象）&lt;/td&gt;&lt;td&gt;手动&lt;/td&gt;&lt;td&gt;无&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Vercel AI SDK&lt;/td&gt;&lt;td&gt;Zod&lt;/td&gt;&lt;td&gt;&lt;code&gt;execute&lt;/code&gt; 绑定&lt;/td&gt;&lt;td&gt;有&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;pi-ai&lt;/td&gt;&lt;td&gt;TypeBox&lt;/td&gt;&lt;td&gt;&lt;code&gt;execute&lt;/code&gt; + &lt;code&gt;onUpdate&lt;/code&gt; 回调&lt;/td&gt;&lt;td&gt;有&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;agent-loop-控制方式&quot;&gt;Agent Loop 控制方式&lt;/h3&gt;



































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;Anthropic SDK&lt;/th&gt;&lt;th&gt;Vercel AI SDK&lt;/th&gt;&lt;th&gt;pi-ai&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Loop 方式&lt;/td&gt;&lt;td&gt;自己写 while&lt;/td&gt;&lt;td&gt;&lt;code&gt;stopWhen: stepCountIs(n)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;自动循环，无 maxSteps&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;停止控制&lt;/td&gt;&lt;td&gt;手动 break&lt;/td&gt;&lt;td&gt;&lt;code&gt;stopWhen&lt;/code&gt; 条件&lt;/td&gt;&lt;td&gt;信任模型自己判断&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;流式事件&lt;/td&gt;&lt;td&gt;无内置&lt;/td&gt;&lt;td&gt;&lt;code&gt;onStepFinish&lt;/code&gt; 回调&lt;/td&gt;&lt;td&gt;完整事件流&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;多 Provider&lt;/td&gt;&lt;td&gt;只支持 Anthropic&lt;/td&gt;&lt;td&gt;支持&lt;/td&gt;&lt;td&gt;支持（含 OpenRouter）&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;pi-ai-独有的东西&quot;&gt;pi-ai 独有的东西&lt;/h3&gt;
&lt;p&gt;Session 树状结构：Session 以树状存储，可以在会话中分支。比如开一个支线任务去修 bug，不消耗主会话的 context，修完后回滚到主会话之前的位置。&lt;/p&gt;
&lt;p&gt;pi-ai 的包分层：&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;pi-ai              ← 只要 LLM 通信（多 Provider 统一接口）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;pi-agent-core      ← 需要 tool loop（Agent 运行时）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;pi-coding-agent    ← 需要完整 coding agent&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;pi-tui             ← 需要 TUI 终端界面&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;OpenClaw 本身用的就是 pi SDK。&lt;/p&gt;
&lt;h3 id=&quot;选型&quot;&gt;选型&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;你的场景是什么？&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;├── 需要完整控制 / 学习底层原理&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   └── Anthropic 原生 SDK（手动 loop）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;├── 快速构建 Next.js / React 应用&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   └── Vercel AI SDK（上手最快，生态完整）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;└── 构建 Terminal 工具 / 编码 Agent / 嵌入 OpenClaw 类产品&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    └── pi-ai（最灵活，无框架锁定）&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2 id=&quot;7-parallel-code-多-agent-并行架构&quot;&gt;7. parallel-code 多 Agent 并行架构&lt;/h2&gt;
&lt;h3 id=&quot;是什么&quot;&gt;是什么&lt;/h3&gt;
&lt;p&gt;parallel-code 是一个 Electron 桌面 App，把三件事捏在一起：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;每个 Agent 有独立 GUI 面板&lt;/li&gt;
&lt;li&gt;每个任务自动用 git worktree 做隔离&lt;/li&gt;
&lt;li&gt;支持同时派 N 个任务然后走开&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;怎么跑的&quot;&gt;怎么跑的&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;用户点击「新建任务」&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ↓&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Electron 主进程自动执行：&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  git worktree add .trees/task-name -b task-name&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ↓&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;在新目录 spawn 一个 pty（伪终端）进程&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  运行 claude / codex / gemini CLI&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ↓&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Electron renderer（前端）通过 IPC 订阅终端输出流&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  在 UI 里渲染每个 Agent 的面板&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;隔离分三层&quot;&gt;隔离分三层&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;文件系统隔离  → git worktree（每个 Agent 在不同目录）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;进程隔离      → 独立 pty 进程（每个 Agent 有独立的 env 和 PATH）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;上下文隔离    → 每个 CLI 进程有独立的会话历史&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2 id=&quot;8-git-worktree-完整解析&quot;&gt;8. Git Worktree 完整解析&lt;/h2&gt;
&lt;h3 id=&quot;git-内部数据模型&quot;&gt;Git 内部数据模型&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;.git/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;├── objects/          ← 对象数据库（所有内容存在这里）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   ├── pack/         ← 压缩后的对象包&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   └── ab/cd1234...  ← 单个对象（blob/tree/commit/tag）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;├── refs/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   ├── heads/        ← 本地 branch 指针&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   │   ├── main      ← 内容: &quot;a1b2c3d4...&quot;（一个 commit hash）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   │   └── feature   ← 内容: &quot;e5f6g7h8...&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   └── remotes/      ← 远程 branch 指针&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;├── HEAD              ← 当前激活的 branch（&quot;ref: refs/heads/main&quot;）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;├── index             ← Staging Area（暂存区）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;└── config            ← 仓库配置&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;objects/&lt;/code&gt; 是仓库的真实数据，文件内容、目录结构、提交历史全在里面。&lt;code&gt;HEAD&lt;/code&gt;、&lt;code&gt;index&lt;/code&gt;、工作目录都只是”视图”。&lt;/p&gt;
&lt;h3 id=&quot;普通-clone-浪费磁盘&quot;&gt;普通 clone 浪费磁盘&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;git&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; clone&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; repo/&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; project-feature-auth&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;   # .git/objects/ → 500MB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;git&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; clone&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; repo/&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; project-feature-ui&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;     # .git/objects/ → 再复制 500MB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;git&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; clone&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; repo/&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; project-bugfix&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;         # .git/objects/ → 再复制 500MB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 总计：1.5GB，其实是同一份数据复制了三次&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;worktree-的磁盘结构&quot;&gt;Worktree 的磁盘结构&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;git&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; worktree&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; add&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; .trees/feature-auth&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -b&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; feature-auth&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;git&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; worktree&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; add&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; .trees/feature-ui&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;   -b&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; feature-ui&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;git&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; worktree&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; add&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; .trees/bugfix-api&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;   -b&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; bugfix-api&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;my-project/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;├── .git/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   ├── objects/                   ← 唯一的对象数据库（所有 worktree 共享）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   ├── refs/heads/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   │   ├── main&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   │   ├── feature-auth&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   │   ├── feature-ui&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   │   └── bugfix-api&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   └── worktrees/                 ← 每个附加 worktree 的元数据&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│       ├── feature-auth/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│       │   ├── HEAD               ← &quot;ref: refs/heads/feature-auth&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│       │   ├── index              ← 独立的暂存区&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│       │   ├── gitdir             ← 指回主 .git 的路径&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│       │   └── commondir          ← &quot;../../&quot; 告诉 Git 去哪找 objects/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│       ├── feature-ui/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│       │   ├── HEAD               ← 独立 HEAD&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│       │   └── index              ← 独立暂存区&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│       └── bugfix-api/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│           ├── HEAD&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│           └── index&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;├── src/                           ← 主工作区文件（main branch）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;├── .trees/feature-auth/           ← 附加工作区（feature-auth branch）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   ├── .git                       ← 不是目录！是一个文件&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   │   └── 内容: &quot;gitdir: ../../.git/worktrees/feature-auth&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   └── src/                       ← 独立的工作文件&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;├── .trees/feature-ui/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;└── .trees/bugfix-api/&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;每个-worktree-独立和共享的部分&quot;&gt;每个 Worktree 独立和共享的部分&lt;/h3&gt;
&lt;p&gt;独立的：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;工作目录（磁盘上的文件）&lt;/li&gt;
&lt;li&gt;HEAD（当前指向哪个 branch）&lt;/li&gt;
&lt;li&gt;index（暂存区，git add 的内容）&lt;/li&gt;
&lt;li&gt;MERGE_HEAD / CHERRY_PICK_HEAD（进行中的操作状态）&lt;/li&gt;
&lt;li&gt;未提交的修改&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;共享的：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;objects/（所有 commit、文件内容的数据库）&lt;/li&gt;
&lt;li&gt;refs/（所有 branch 和 tag 的指针）&lt;/li&gt;
&lt;li&gt;config（remote 配置、用户信息）&lt;/li&gt;
&lt;li&gt;hooks/（git hook 脚本）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;同一-branch-不能被两个-worktree-同时-checkout&quot;&gt;同一 branch 不能被两个 worktree 同时 checkout&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 假设 main 已经在主工作区被 checkout&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;git&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; worktree&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; add&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; .trees/main-copy&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; main&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 报错：fatal: &apos;main&apos; is already checked out at &apos;/my-project&apos;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Git 用 &lt;code&gt;.git/worktrees/&amp;#x3C;name&gt;/locked&lt;/code&gt; 文件来记录锁定状态，防止冲突。&lt;/p&gt;
&lt;h3 id=&quot;常用命令&quot;&gt;常用命令&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 创建新 worktree（自动创建新 branch）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;git&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; worktree&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; add&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; .trees/feature-auth&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -b&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; feature-auth&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 创建新 worktree（从指定 commit/branch 开始）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;git&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; worktree&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; add&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; .trees/hotfix&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; origin/main&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 查看所有 worktree&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;git&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; worktree&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; list&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 输出：&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# /my-project              a1b2c3d [main]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# /my-project/.trees/feature-auth  e5f6g7h [feature-auth]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 删除 worktree&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;git&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; worktree&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; remove&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; .trees/feature-auth&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 强制删除&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;git&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; worktree&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; remove&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --force&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; .trees/feature-auth&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 清理已手动删除的 worktree 的残留元数据&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;git&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; worktree&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; prune&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;为什么-ai-agent-并行要用这个&quot;&gt;为什么 AI Agent 并行要用这个&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Agent 1 在 .trees/feature-auth/ 运行&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  → 读写文件：只影响这个目录&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  → git add / commit：只提交到 feature-auth branch&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  → 跑测试：在这个目录的代码上跑&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Agent 2 在 .trees/feature-ui/ 运行&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  → 完全感知不到 Agent 1 的存在&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  → 两个 Agent 可以同时改&quot;同名文件&quot;（如 src/app.ts）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     但在不同 branch 上，完全不冲突&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;隔离靠的是 Git 原生的分支机制，在文件系统层面就把冲突的可能性断掉了，不需要应用层加锁。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;9-用-pi-ai-复现-parallel-code&quot;&gt;9. 用 pi-ai 复现 parallel-code&lt;/h2&gt;
&lt;h3 id=&quot;方案一nodejs-纯代码并行&quot;&gt;方案一：Node.js 纯代码并行&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;typescript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { createAgentSession } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;@mariozechner/pi-coding-agent&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { execSync } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;child_process&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; path &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;path&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; createWorktree&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;taskName&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;baseBranch&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;main&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; worktreePath&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; path.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;resolve&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;`.trees/${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;taskName&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}`&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  execSync&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;`git worktree add ${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;worktreePath&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;} -b ${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;taskName&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;} ${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;baseBranch&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}`&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; worktreePath;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;async&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; spawnAgent&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;taskName&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;prompt&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; worktreePath&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; createWorktree&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(taskName);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  const&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;session&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; createAgentSession&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    sessionManager: SessionManager.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;inMemory&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    workingDirectory: worktreePath,   &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ← 隔离点&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; session.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;prompt&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(prompt);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 用 Promise.all 并行跑多个 Agent&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; tasks&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  { name: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;feature-auth&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,   prompt: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;实现 OAuth2 登录流程&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  { name: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;feature-search&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, prompt: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;实现全文搜索功能&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  { name: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;bugfix-api&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,     prompt: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;修复 /api/users 的 500 错误&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; results&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Promise&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;all&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  tasks.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;map&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(({ &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;prompt&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; }) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; spawnAgent&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(name, prompt))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;方案二orchestrator-模式&quot;&gt;方案二：Orchestrator 模式&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;typescript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; ParallelOrchestrator&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  private&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt; tasks&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Map&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;TaskState&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  async&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; dispatch&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;taskName&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;prompt&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; worktreePath&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; this&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;createWorktree&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(taskName);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; session&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; this&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;createSession&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(worktreePath);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    this&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.tasks.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(taskName, { status: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;RUNNING&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, worktreePath, session });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // 不 await，让它在背景跑&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    session.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;prompt&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(prompt).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;then&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(() &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      this&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.tasks.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(taskName)&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.status &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;COMPLETE&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  status&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.tasks.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;entries&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()].&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;map&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(([&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;state&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      name, status: state.status, branch: name&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  async&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; merge&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;taskName&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    execSync&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;`git merge ${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;taskName&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}`&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, { cwd: process.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;cwd&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    execSync&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;`git worktree remove .trees/${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;taskName&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}`&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    this&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.tasks.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;delete&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(taskName);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;parallel-code-vs-pi-ai-方案&quot;&gt;parallel-code vs pi-ai 方案&lt;/h3&gt;



































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;隔离层&lt;/th&gt;&lt;th&gt;parallel-code&lt;/th&gt;&lt;th&gt;pi-ai 方案&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;文件系统&lt;/td&gt;&lt;td&gt;git worktree（独立目录）&lt;/td&gt;&lt;td&gt;git worktree（独立目录）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Agent 上下文&lt;/td&gt;&lt;td&gt;独立 CLI 进程&lt;/td&gt;&lt;td&gt;独立 &lt;code&gt;session&lt;/code&gt; 内存对象&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;会话历史&lt;/td&gt;&lt;td&gt;进程级隔离&lt;/td&gt;&lt;td&gt;&lt;code&gt;SessionManager.inMemory()&lt;/code&gt; 各自隔离&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;GUI&lt;/td&gt;&lt;td&gt;Electron 面板&lt;/td&gt;&lt;td&gt;需自己实现&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;合并流程&lt;/td&gt;&lt;td&gt;点击按钮 PR&lt;/td&gt;&lt;td&gt;&lt;code&gt;git merge&lt;/code&gt; 命令&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;整理自对话学习笔记。&lt;/em&gt;&lt;/p&gt;</content:encoded><category>前端工程化</category><category>AI</category><category>Typescript</category><category>OpenClaw架构解析</category></item><item><title>Anthony Fu 的 Vue3 开发规范完整解读</title><link>https://feichuans.com/blogs/05-archive/anthony-fu-%E7%9A%84-vue3-%E5%BC%80%E5%8F%91%E8%A7%84%E8%8C%83%E5%AE%8C%E6%95%B4%E8%A7%A3%E8%AF%BB/</link><guid isPermaLink="true">https://feichuans.com/blogs/05-archive/anthony-fu-%E7%9A%84-vue3-%E5%BC%80%E5%8F%91%E8%A7%84%E8%8C%83%E5%AE%8C%E6%95%B4%E8%A7%A3%E8%AF%BB/</guid><description>基于 antfu/skills 仓库整理翻译的 Vue 3 开发规范中文文档，涵盖 Anthony Fu 编码偏好、Vue 3 核心 API 规范、最佳实践与常见陷阱、以及为什么选择 UnoCSS 而非 Tailwind CSS</description><pubDate>Wed, 11 Feb 2026 04:00:00 GMT</pubDate><content:encoded>&lt;p&gt;// ❌ 避免：一个文件包含所有逻辑
// UserManager.ts (800 lines)
export class UserManager {
validateUser() { /* 50 lines &lt;em&gt;/ }
fetchUserData() { /&lt;/em&gt; 100 lines &lt;em&gt;/ }
updateUserProfile() { /&lt;/em&gt; 150 lines */ }
// …
}&lt;/p&gt;
&lt;p&gt;// ✅ 推荐：按职责拆分
// validation.ts
export function validateUser(user: User) { /* … */ }&lt;/p&gt;
&lt;p&gt;// api.ts
export function fetchUserData(id: string) { /* … */ }&lt;/p&gt;
&lt;p&gt;// profile.ts
export function updateUserProfile(data: ProfileData) { /* … */ }&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;**类型与常量分离**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;```ts&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;// types.ts&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;export interface User {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  id: string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  name: string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  role: UserRole&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;export type UserRole = &apos;admin&apos; | &apos;user&apos; | &apos;guest&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;// constants.ts&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;export const DEFAULT_PAGE_SIZE = 20&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;export const MAX_RETRIES = 3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;export const API_ENDPOINTS = {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  users: &apos;/api/users&apos;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  posts: &apos;/api/posts&apos;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;} as const&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;// user-service.ts&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import type { User, UserRole } from &apos;./types&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import { API_ENDPOINTS } from &apos;./constants&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;export async function fetchUsers(): Promise&amp;#x3C;User[]&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  const response = await fetch(API_ENDPOINTS.users)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  return response.json()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;运行时环境标注&quot;&gt;运行时环境标注&lt;/h3&gt;
&lt;p&gt;编写同构代码时，为环境特定的代码添加明确的注释：&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ts&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ✅ 明确标注环境依赖&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// @env browser&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;export&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; getWindowSize&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    width: window.innerWidth,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    height: window.innerHeight,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// @env node&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;export&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; readConfigFile&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; fs.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;readFileSync&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;./config.json&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;utf-8&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ✅ 同构代码无需标注&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;export&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; formatDate&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;date&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Date&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; date.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;toISOString&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;typescript-最佳实践&quot;&gt;TypeScript 最佳实践&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;显式返回类型&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ts&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ❌ 避免：隐式返回类型&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;export&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; calculateTotal&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;items&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; items.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;reduce&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;((&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;sum&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;item&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; sum &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; item.price, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ✅ 推荐：显式返回类型&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;export&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; calculateTotal&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;items&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Item&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[])&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; number&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; items.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;reduce&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;((&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;sum&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;item&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; sum &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; item.price, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ✅ 复杂类型提取为类型别名&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;export&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; type&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; AsyncResult&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Promise&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;{ &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;data&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; T&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; null&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;data&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; null&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Error&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; }&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;export&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; fetchData&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;url&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; AsyncResult&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  // ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;避免复杂内联类型&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ts&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ❌ 避免：复杂内联类型&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; processUsers&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;  users&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Array&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    id&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    profile&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;      name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;      email&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;      settings&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;        theme&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;light&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;dark&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;        notifications&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; boolean&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  // ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ✅ 推荐：提取类型定义&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;interface&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; UserSettings&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;  theme&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;light&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;dark&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;  notifications&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; boolean&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;interface&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; UserProfile&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;  name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;  email&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;  settings&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; UserSettings&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;interface&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; User&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;  id&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;  profile&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; UserProfile&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; processUsers&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;users&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; User&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[]) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  // ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;注释哲学&quot;&gt;注释哲学&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;解释”为什么”而非”怎么做”&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ts&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ❌ 避免：无意义的注释&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 循环遍历用户数组&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;users.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;forEach&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;user&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  // 打印用户名&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  console.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(user.name)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ✅ 推荐：解释为什么这样做&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 使用 setTimeout 0 延迟执行，确保 DOM 更新完成后再计算高度&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;setTimeout&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(() &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; height&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; element.offsetHeight&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ✅ 解释非直观的业务逻辑&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 价格计算需要先扣除折扣，再加税费，顺序不能颠倒&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 因为税费基于折后价计算（符合当地税法要求）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; finalPrice&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (price &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; discount) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; taxRate)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;测试规范vitest&quot;&gt;测试规范（Vitest）&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;文件组织&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;src/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  utils/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    format.ts&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;          # 源代码&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    format.test.ts&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;     # 测试文件&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  components/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    Button.vue&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    Button.test.ts&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;测试结构&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ts&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// format.test.ts&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { describe, it, expect } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;vitest&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { formatCurrency, formatDate } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;./format&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;describe&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;formatCurrency&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, () &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  it&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;should format USD correctly&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, () &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    expect&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;formatCurrency&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1234.56&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;USD&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;toBe&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;$1,234.56&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  it&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;should handle zero&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, () &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    expect&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;formatCurrency&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;USD&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;toBe&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;$0.00&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  it&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;should round to 2 decimal places&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, () &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    expect&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;formatCurrency&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.234&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;USD&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;toBe&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;$1.23&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;describe&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;formatDate&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, () &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  it&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;should match snapshot&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, () &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; date&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Date&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;2024-01-15T10:30:00Z&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    expect&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;formatDate&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(date)).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;toMatchSnapshot&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;})&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;工具链速查&quot;&gt;工具链速查&lt;/h3&gt;
&lt;h4 id=&quot;antfuni---通用包管理器命令&quot;&gt;@antfu/ni - 通用包管理器命令&lt;/h4&gt;






















































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;命令&lt;/th&gt;&lt;th&gt;npm&lt;/th&gt;&lt;th&gt;yarn&lt;/th&gt;&lt;th&gt;pnpm&lt;/th&gt;&lt;th&gt;bun&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;ni&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;npm install&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;yarn install&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;pnpm install&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;bun install&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;nr dev&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;npm run dev&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;yarn run dev&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;pnpm run dev&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;bun run dev&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;nu&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;npm update&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;yarn upgrade&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;pnpm update&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;bun update&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;nun lodash&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;npm uninstall lodash&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;yarn remove lodash&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;pnpm remove lodash&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;bun remove lodash&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;nci&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;npm ci&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;yarn install --frozen-lockfile&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;pnpm install --frozen-lockfile&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;bun install --frozen-lockfile&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;nlx vitest&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;npx vitest&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;yarn dlx vitest&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;pnpm dlx vitest&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;bunx vitest&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h4 id=&quot;typescript-配置标准&quot;&gt;TypeScript 配置标准&lt;/h4&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;compilerOptions&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    &quot;target&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;ESNext&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    &quot;module&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;ESNext&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    &quot;moduleResolution&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;bundler&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    &quot;lib&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: [&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;ESNext&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;DOM&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;DOM.Iterable&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    &quot;jsx&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;preserve&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    &quot;strict&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    &quot;skipLibCheck&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    &quot;resolveJsonModule&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    &quot;esModuleInterop&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    &quot;isolatedModules&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    &quot;noUncheckedIndexedAccess&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    &quot;paths&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &quot;~/*&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: [&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;./src/*&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;关键配置说明：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;moduleResolution: &quot;bundler&quot;&lt;/code&gt; - 适配 Vite/Rollup 等现代打包工具&lt;/li&gt;
&lt;li&gt;&lt;code&gt;noUncheckedIndexedAccess: true&lt;/code&gt; - 索引访问返回 &lt;code&gt;T | undefined&lt;/code&gt;，更安全&lt;/li&gt;
&lt;li&gt;&lt;code&gt;strict: true&lt;/code&gt; - 启用所有严格类型检查&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;eslint-配置&quot;&gt;ESLint 配置&lt;/h4&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 安装&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;pnpm&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; add&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -D&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; @antfu/eslint-config&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; eslint&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 运行&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;pnpm&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; run&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; lint&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --fix&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ts&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// eslint.config.js&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; antfu &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;@antfu/eslint-config&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;export&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; default&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; antfu&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  vue: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  typescript: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  formatters: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    css: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    html: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    markdown: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;})&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;git-hooks-配置&quot;&gt;Git Hooks 配置&lt;/h4&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 安装&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;pnpm&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; add&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -D&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; simple-git-hooks&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; lint-staged&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// package.json&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;simple-git-hooks&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    &quot;pre-commit&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;pnpm lint-staged&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;lint-staged&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    &quot;*.{js,ts,vue}&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;eslint --fix&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;pnpm-catalogs-最佳实践&quot;&gt;pnpm Catalogs 最佳实践&lt;/h4&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# pnpm-workspace.yaml&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;catalogs&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  # 生产依赖&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;  prod&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;    vue&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;^3.5.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;    pinia&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;^2.2.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  # 内联依赖（会被打包）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;  inlined&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;    lodash-es&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;^4.17.21&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  # 开发依赖&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;  dev&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;    vitest&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;^2.0.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;    typescript&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;^5.6.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  # 前端特定依赖&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;  frontend&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;    unocss&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;^0.63.0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// package.json&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;dependencies&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    &quot;vue&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;catalog:prod&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    &quot;lodash-es&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;catalog:inlined&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;devDependencies&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    &quot;vitest&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;catalog:dev&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    &quot;unocss&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;catalog:frontend&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2 id=&quot;第二部分vue-3-核心规范&quot;&gt;第二部分：Vue 3 核心规范&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;基于 Vue 3.5，优先使用 TypeScript 和 &lt;code&gt;&amp;#x3C;script setup&gt;&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;偏好设定&quot;&gt;偏好设定&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;th&gt;原因&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;语言选择&lt;/td&gt;&lt;td&gt;TypeScript&lt;/td&gt;&lt;td&gt;类型安全、更好的 IDE 支持&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;脚本格式&lt;/td&gt;&lt;td&gt;&lt;code&gt;&amp;#x3C;script setup lang=&quot;ts&quot;&gt;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;更简洁的语法、更好的性能&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;响应式选择&lt;/td&gt;&lt;td&gt;&lt;code&gt;shallowRef&lt;/code&gt; &gt; &lt;code&gt;ref&lt;/code&gt;&lt;/td&gt;&lt;td&gt;大多数场景足够用，性能更好&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;API 风格&lt;/td&gt;&lt;td&gt;Composition API&lt;/td&gt;&lt;td&gt;更好的逻辑复用和类型推导&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Props 解构&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=&quot;标准组件模板&quot;&gt;标准组件模板&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;vue&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;script&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; setup&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; lang&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;ts&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { computed, ref, watch, onMounted } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;vue&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; type&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { ComponentPublicInstance } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;vue&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// Props 定义&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;interface&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Props&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;  title&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;  count&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;?:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; number&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;  disabled&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;?:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; boolean&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; props&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; withDefaults&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;defineProps&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Props&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;(), {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  count: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  disabled: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// Emits 定义&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;interface&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Emits&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;  update&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;value&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;number&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;  submit&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;data&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: { &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; }]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; emit&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; defineEmits&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Emits&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// Model 双向绑定&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; modelValue&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; defineModel&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;({ required: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 响应式状态&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; isLoading&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; ref&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; items&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; ref&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Item&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[]&gt;([])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 计算属性&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; displayTitle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; computed&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(() &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; props.disabled &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; `${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;props&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;} (已禁用)`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; :&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; props.title&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 侦听器&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;watch&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(() &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; props.count, (&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;newVal&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;oldVal&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  console.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;`Count changed from ${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;oldVal&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;} to ${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;newVal&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}`&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 生命周期&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;onMounted&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(() &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  console.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Component mounted&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 方法&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; handleClick&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  emit&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;update&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, props.count &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 暴露给父组件（defineExpose）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;defineExpose&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  focus&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: () &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // 暴露的方法&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;script&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;template&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;h1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;{{ displayTitle }}&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;h1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; @click&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;handleClick&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; :disabled&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;disabled&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      Count: {{ count }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  &amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;template&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;style&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; scoped&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;/* scoped 样式 */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;style&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;关键导入速查&quot;&gt;关键导入速查&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ts&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 核心响应式 API&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  ref,           &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 深层响应式&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  shallowRef,    &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 浅层响应式（推荐）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  reactive,      &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 深层响应式对象&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  shallowReactive, &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 浅层响应式对象&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  readonly,      &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 只读代理&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  computed,      &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 计算属性&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  watch,         &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 侦听器&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  watchEffect,   &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 副作用侦听器&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;} &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;vue&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 生命周期钩子&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  onMounted,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  onUpdated,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  onUnmounted,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  onBeforeMount,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  onBeforeUpdate,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  onBeforeUnmount,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;} &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;vue&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 组件通信&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  defineProps,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  defineEmits,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  defineModel,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  defineExpose,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  defineSlots,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  provide,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  inject,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;} &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;vue&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 工具函数&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  nextTick,      &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 等待 DOM 更新&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  toRef,         &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 转换为 ref&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  toRefs,        &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 解构保持响应式&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  unref,         &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 解包 ref&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  isRef,         &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 判断是否 ref&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  markRaw,       &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 标记为非响应式&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;} &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;vue&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 类型工具&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; type&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  Ref,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  ComputedRef,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  ComponentPublicInstance,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  PropType,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;} &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;vue&apos;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;ref-vs-shallowref-性能对比&quot;&gt;ref vs shallowRef 性能对比&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ts&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ref - 深层响应式（递归代理所有层级）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; deepState&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; ref&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  user: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    profile: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      name: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;John&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      settings: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        theme: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;dark&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 任何层级的修改都会触发响应&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;deepState.value.user.profile.settings.theme &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;light&apos;&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt; // ✅ 响应式&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// shallowRef - 浅层响应式（只代理第一层）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; shallowState&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; shallowRef&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  user: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    profile: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      name: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;John&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      settings: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        theme: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;dark&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 只有整体替换才会触发响应&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;shallowState.value.user.profile.settings.theme &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;light&apos;&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt; // ❌ 不会触发&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;shallowState.value &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;shallowState.value } &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ✅ 触发响应&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 性能建议：大部分场景使用 shallowRef 足够&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2 id=&quot;第三部分vue-3-最佳实践与常见陷阱&quot;&gt;第三部分：Vue 3 最佳实践与常见陷阱&lt;/h2&gt;
&lt;h3 id=&quot;响应式系统&quot;&gt;响应式系统&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;ref vs reactive 如何选择？&lt;/td&gt;&lt;td&gt;优先使用 &lt;code&gt;ref&lt;/code&gt;。&lt;code&gt;ref&lt;/code&gt; 可以存储任何类型，而 &lt;code&gt;reactive&lt;/code&gt; 只能用于对象。&lt;code&gt;ref&lt;/code&gt; 在重新赋值时保持响应性，&lt;code&gt;reactive&lt;/code&gt; 不行。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;什么时候用 shallowRef？&lt;/td&gt;&lt;td&gt;存储大型数据结构（如长列表、复杂嵌套对象）时，用 &lt;code&gt;shallowRef&lt;/code&gt; 避免深层代理的性能开销。更新时需要整体替换对象。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;如何阻止对象变成响应式？&lt;/td&gt;&lt;td&gt;使用 &lt;code&gt;markRaw()&lt;/code&gt;。例如存储第三方库实例（Chart.js、Monaco Editor）时，避免不必要的代理。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;多次修改 ref 会触发多次渲染吗？&lt;/td&gt;&lt;td&gt;不会。Vue 会将同一 tick 内的更新批量处理。如需立即看到 DOM 变化，使用 &lt;code&gt;await nextTick()&lt;/code&gt;。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;ref 解包规则是什么？&lt;/td&gt;&lt;td&gt;在模板中自动解包（&lt;code&gt;{{ count }}&lt;/code&gt;）。在 &lt;code&gt;reactive&lt;/code&gt; 对象中自动解包（&lt;code&gt;state.count&lt;/code&gt;）。在数组和 Map/Set 中不解包（需要 &lt;code&gt;.value&lt;/code&gt;）。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;解构 props 会丢失响应性吗？&lt;/td&gt;&lt;td&gt;是的。使用 &lt;code&gt;toRefs(props)&lt;/code&gt; 或 &lt;code&gt;toRef(props, &apos;key&apos;)&lt;/code&gt; 保持响应性，或在 computed/watch 中访问 &lt;code&gt;props.xxx&lt;/code&gt;。&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;计算属性&quot;&gt;计算属性&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;/td&gt;&lt;td&gt;不应该。计算属性应该是纯函数，只做计算和返回值。副作用应该放在 &lt;code&gt;watch&lt;/code&gt; 或 &lt;code&gt;watchEffect&lt;/code&gt; 中。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;为什么计算属性是只读的？&lt;/td&gt;&lt;td&gt;默认只读，但可以提供 setter。推荐只读设计，修改应通过源数据。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;计算属性什么时候重新计算？&lt;/td&gt;&lt;td&gt;只有当依赖的响应式数据变化时才重新计算（懒执行 + 缓存）。这是相比 &lt;code&gt;method&lt;/code&gt; 的主要优势。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;计算属性的条件依赖如何工作？&lt;/td&gt;&lt;td&gt;只追踪当前执行分支的依赖。&lt;code&gt;if (flag) return a&lt;/code&gt; 时只追踪 &lt;code&gt;flag&lt;/code&gt; 和 &lt;code&gt;a&lt;/code&gt;，不追踪 &lt;code&gt;else&lt;/code&gt; 分支。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;计算属性内使用 array.map 有性能问题吗？&lt;/td&gt;&lt;td&gt;有。每次重新计算都会创建新数组。考虑使用 &lt;code&gt;shallowRef&lt;/code&gt; 存储映射结果，或在 &lt;code&gt;watch&lt;/code&gt; 中手动更新。&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;侦听器&quot;&gt;侦听器&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;watch 的 getter 函数是什么？&lt;/td&gt;&lt;td&gt;&lt;code&gt;watch(() =&gt; obj.count, ...)&lt;/code&gt; 中的箭头函数。推荐用 getter 而非直接传对象，可以精确控制依赖。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;deep: true 有性能问题吗？&lt;/td&gt;&lt;td&gt;有。深度侦听需要遍历对象的所有属性。只在必要时使用，或用 getter 函数精确指定依赖。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;immediate: true 的执行时机是什么？&lt;/td&gt;&lt;td&gt;立即执行一次，此时 DOM 可能未挂载。需要访问 DOM 时注意判断。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;flush 选项有什么区别？&lt;/td&gt;&lt;td&gt;&lt;code&gt;pre&lt;/code&gt;（默认）：DOM 更新前执行。&lt;code&gt;post&lt;/code&gt;：DOM 更新后执行。&lt;code&gt;sync&lt;/code&gt;：同步执行（避免使用）。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;如何在侦听器中访问旧值？&lt;/td&gt;&lt;td&gt;&lt;code&gt;watch(source, (newVal, oldVal) =&gt; {})&lt;/code&gt;。注意对象类型的 &lt;code&gt;oldVal&lt;/code&gt; 和 &lt;code&gt;newVal&lt;/code&gt; 可能指向同一个引用。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;watch vs watchEffect 如何选择？&lt;/td&gt;&lt;td&gt;&lt;code&gt;watchEffect&lt;/code&gt;：自动追踪依赖，简洁。&lt;code&gt;watch&lt;/code&gt;：显式指定侦听源，可访问旧值，更精确。&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;组件通信&quot;&gt;组件通信&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;可以修改 props 吗？&lt;/td&gt;&lt;td&gt;不可以。Props 是单向数据流，只读。需要修改时，emit 事件或使用 &lt;code&gt;defineModel&lt;/code&gt;。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;自定义事件会冒泡吗？&lt;/td&gt;&lt;td&gt;不会。Vue 的自定义事件不像原生 DOM 事件那样冒泡，只触发直接父组件的监听器。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;组件名应该用什么格式？&lt;/td&gt;&lt;td&gt;PascalCase（&lt;code&gt;MyComponent.vue&lt;/code&gt;）。在模板中可以用 &lt;code&gt;&amp;#x3C;MyComponent&gt;&lt;/code&gt; 或 &lt;code&gt;&amp;#x3C;my-component&gt;&lt;/code&gt;，推荐前者。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;defineExpose 何时使用？&lt;/td&gt;&lt;td&gt;当需要父组件通过 ref 调用子组件方法时。默认 &lt;code&gt;&amp;#x3C;script setup&gt;&lt;/code&gt; 不暴露任何内容。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;如何获取组件实例的类型？&lt;/td&gt;&lt;td&gt;&lt;code&gt;InstanceType&amp;#x3C;typeof MyComponent&gt;&lt;/code&gt;，配合 &lt;code&gt;ref&amp;#x3C;InstanceType&amp;#x3C;typeof MyComponent&gt;&gt;()&lt;/code&gt;。&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;props-与-emits&quot;&gt;Props 与 Emits&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;Boolean props 的转换规则？&lt;/td&gt;&lt;td&gt;&lt;code&gt;&amp;#x3C;MyComp disabled&gt;&lt;/code&gt; 等价于 &lt;code&gt;:disabled=&quot;true&quot;&lt;/code&gt;。&lt;code&gt;&amp;#x3C;MyComp&gt;&lt;/code&gt; 则是 &lt;code&gt;undefined&lt;/code&gt;（除非有默认值）。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;解构 props 会丢失响应性吗？&lt;/td&gt;&lt;td&gt;是的。&lt;code&gt;const { title } = defineProps()&lt;/code&gt; 会丢失响应性。使用 &lt;code&gt;toRefs&lt;/code&gt; 或直接访问 &lt;code&gt;props.title&lt;/code&gt;。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;props 命名约定是什么？&lt;/td&gt;&lt;td&gt;JS 中用 camelCase，HTML 中用 kebab-case。&lt;code&gt;defineProps&amp;#x3C;{ userName: string }&gt;()&lt;/code&gt; → &lt;code&gt;&amp;#x3C;Comp user-name=&quot;John&quot;&gt;&lt;/code&gt;。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;emit 事件命名约定？&lt;/td&gt;&lt;td&gt;JS 中用 camelCase，HTML 中用 kebab-case。&lt;code&gt;emit(&apos;updateValue&apos;)&lt;/code&gt; → &lt;code&gt;@update-value=&quot;handler&quot;&lt;/code&gt;。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;defineModel 的优势是什么？&lt;/td&gt;&lt;td&gt;简化 &lt;code&gt;v-model&lt;/code&gt; 实现，自动生成 prop 和 emit。支持修饰符（&lt;code&gt;.trim&lt;/code&gt;、&lt;code&gt;.number&lt;/code&gt; 等）。&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;模板语法&quot;&gt;模板语法&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;v-html 安全吗？&lt;/td&gt;&lt;td&gt;不安全。可能导致 XSS 攻击。只用于可信内容，或使用 DOMPurify 等库清理。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;v-if 和 v-for 能同时用吗？&lt;/td&gt;&lt;td&gt;Vue 3 中 &lt;code&gt;v-if&lt;/code&gt; 优先级高于 &lt;code&gt;v-for&lt;/code&gt;，但不推荐同时使用。应该用 computed 过滤或嵌套 template。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;v-if vs v-show 如何选择？&lt;/td&gt;&lt;td&gt;&lt;code&gt;v-if&lt;/code&gt;：条件渲染，切换开销高。&lt;code&gt;v-show&lt;/code&gt;：CSS 切换，初始渲染开销高。频繁切换用 &lt;code&gt;v-show&lt;/code&gt;。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;key 的作用是什么？&lt;/td&gt;&lt;td&gt;帮助 Vue 识别节点，优化 diff 算法。列表渲染必须提供唯一 key，避免用 index。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;如何绑定多个属性？&lt;/td&gt;&lt;td&gt;&lt;code&gt;v-bind=&quot;attrs&quot;&lt;/code&gt; 可以一次性绑定对象的所有属性。例如 &lt;code&gt;v-bind=&quot;{ id: &apos;foo&apos;, class: &apos;bar&apos; }&quot;&lt;/code&gt;。&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;表单与-v-model&quot;&gt;表单与 v-model&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;defineModel 的修饰符如何使用？&lt;/td&gt;&lt;td&gt;内置 &lt;code&gt;.trim&lt;/code&gt;、&lt;code&gt;.number&lt;/code&gt;、&lt;code&gt;.lazy&lt;/code&gt;。自定义修饰符通过 &lt;code&gt;defineModel&lt;/code&gt; 的第二个参数处理。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;v-model 在组件上的原理？&lt;/td&gt;&lt;td&gt;语法糖：&lt;code&gt;:modelValue=&quot;value&quot; @update:modelValue=&quot;value = $event&quot;&lt;/code&gt;。多个 v-model：&lt;code&gt;v-model:title&lt;/code&gt;。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;如何在 v-model 更新后访问 DOM？&lt;/td&gt;&lt;td&gt;使用 &lt;code&gt;await nextTick()&lt;/code&gt;，因为 Vue 异步更新 DOM。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;textarea 的 v-model 和插值的区别？&lt;/td&gt;&lt;td&gt;&lt;code&gt;&amp;#x3C;textarea v-model=&quot;text&quot;&gt;&lt;/code&gt; 正确。&lt;code&gt;&amp;#x3C;textarea&gt;{{ text }}&amp;#x3C;/textarea&gt;&lt;/code&gt; 不生效，textarea 不支持插值。&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;事件处理与修饰符&quot;&gt;事件处理与修饰符&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;.once 修饰符如何工作？&lt;/td&gt;&lt;td&gt;事件只触发一次后自动移除监听器。&lt;code&gt;@click.once=&quot;handler&quot;&lt;/code&gt;。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;.exact 修饰符的作用？&lt;/td&gt;&lt;td&gt;精确匹配修饰键。&lt;code&gt;@click.ctrl.exact&lt;/code&gt; 只在按下 Ctrl（无其他键）时触发。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;.passive 和 .prevent 冲突吗？&lt;/td&gt;&lt;td&gt;冲突。&lt;code&gt;.passive&lt;/code&gt; 告诉浏览器不调用 &lt;code&gt;preventDefault()&lt;/code&gt;，两者不能同时使用。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;自定义事件可以用修饰符吗？&lt;/td&gt;&lt;td&gt;可以，但需要在子组件中通过 &lt;code&gt;defineEmits&lt;/code&gt; 的第二个参数手动实现验证逻辑。&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;生命周期&quot;&gt;生命周期&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;/td&gt;&lt;td&gt;是的。必须在 &lt;code&gt;setup&lt;/code&gt; 或 &lt;code&gt;&amp;#x3C;script setup&gt;&lt;/code&gt; 的同步代码中调用，不能在 &lt;code&gt;setTimeout&lt;/code&gt; 或 &lt;code&gt;async&lt;/code&gt; 函数中。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;onUpdated 钩子性能如何？&lt;/td&gt;&lt;td&gt;会在任何响应式数据变化导致的重新渲染后调用，可能频繁触发。谨慎使用，考虑用 &lt;code&gt;watch&lt;/code&gt; 替代。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;如何在组件外部注册生命周期？&lt;/td&gt;&lt;td&gt;使用 &lt;code&gt;effectScope&lt;/code&gt; 创建作用域，在其中注册钩子。&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;插槽&quot;&gt;插槽&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;/td&gt;&lt;td&gt;默认插槽只能访问父组件的数据。作用域插槽通过 &lt;code&gt;v-slot=&quot;slotProps&quot;&lt;/code&gt; 接收子组件传递的数据。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;defineSlots 的作用？&lt;/td&gt;&lt;td&gt;仅用于类型定义，帮助 TypeScript 推导插槽的 props 类型。不影响运行时。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;插槽的 fallback content 是什么？&lt;/td&gt;&lt;td&gt;&lt;code&gt;&amp;#x3C;slot&gt;默认内容&amp;#x3C;/slot&gt;&lt;/code&gt; 中的默认内容，当父组件不提供插槽内容时显示。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;动态插槽名如何使用？&lt;/td&gt;&lt;td&gt;&lt;code&gt;v-slot:[dynamicSlotName]&lt;/code&gt; 或 &lt;code&gt;#[dynamicSlotName]&lt;/code&gt;。&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;provide--inject&quot;&gt;Provide / Inject&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;应该用什么作为 injection key？&lt;/td&gt;&lt;td&gt;使用 Symbol 而非字符串，避免命名冲突。&lt;code&gt;export const userKey = Symbol(&apos;user&apos;)&lt;/code&gt;。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;注入的数据可以修改吗？&lt;/td&gt;&lt;td&gt;可以，但建议 mutations 集中在 provider 组件，通过提供修改方法而非直接暴露响应式状态。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;如何为 inject 提供类型？&lt;/td&gt;&lt;td&gt;&lt;code&gt;const user = inject&amp;#x3C;User&gt;(userKey)&lt;/code&gt; 或在定义 key 时指定 &lt;code&gt;InjectionKey&amp;#x3C;User&gt;&lt;/code&gt;。&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;组合式函数&quot;&gt;组合式函数&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;/td&gt;&lt;td&gt;以 &lt;code&gt;use&lt;/code&gt; 开头，camelCase。例如 &lt;code&gt;useMouse&lt;/code&gt;、&lt;code&gt;useFetch&lt;/code&gt;。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;返回值应该是什么？&lt;/td&gt;&lt;td&gt;返回包含响应式状态和方法的对象。使用 &lt;code&gt;readonly()&lt;/code&gt; 保护内部状态。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;何时使用 options 对象模式？&lt;/td&gt;&lt;td&gt;参数超过 2 个时推荐。&lt;code&gt;useFetch(url, { method, headers, onSuccess })&lt;/code&gt;。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;组合式函数可以嵌套调用吗？&lt;/td&gt;&lt;td&gt;可以。一个组合式函数可以调用其他组合式函数。&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ts&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 示例：标准组合式函数&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;export&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; useMouse&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; x&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; ref&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; y&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; ref&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; update&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;event&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; MouseEvent&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    x.value &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; event.clientX&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    y.value &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; event.clientY&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  onMounted&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(() &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; window.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;addEventListener&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;mousemove&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, update))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  onUnmounted&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(() &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; window.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;removeEventListener&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;mousemove&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, update))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    x: &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;readonly&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(x),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    y: &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;readonly&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(y),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;composition-api&quot;&gt;Composition API&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;为什么用 Composition API 替代 mixin？&lt;/td&gt;&lt;td&gt;Mixin 有命名冲突、来源不清晰、难以重用等问题。Composition API 通过函数组合解决这些问题。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Composition API 和 React Hooks 有什么区别？&lt;/td&gt;&lt;td&gt;Vue 的 setup 只执行一次，不受闭包陷阱影响。React Hooks 每次渲染都执行，需要依赖数组。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;何时仍然使用 Options API？&lt;/td&gt;&lt;td&gt;简单组件、团队不熟悉 Composition API、维护老代码时可以使用 Options API。&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;自定义指令&quot;&gt;自定义指令&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;/td&gt;&lt;td&gt;是的。在 &lt;code&gt;unmounted&lt;/code&gt; 钩子中清理事件监听器、定时器等，避免内存泄漏。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;指令命名约定？&lt;/td&gt;&lt;td&gt;以 &lt;code&gt;v&lt;/code&gt; 开头。注册时用 camelCase（&lt;code&gt;vFocus&lt;/code&gt;），使用时用 kebab-case（&lt;code&gt;v-focus&lt;/code&gt;）。&lt;/td&gt;&lt;/tr&gt;&lt;tr&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=&quot;过渡与动画&quot;&gt;过渡与动画&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;Transition 只能包含单个子元素吗？&lt;/td&gt;&lt;td&gt;是的。多个元素需要用 &lt;code&gt;v-if&lt;/code&gt; / &lt;code&gt;v-else&lt;/code&gt; 或 &lt;code&gt;TransitionGroup&lt;/code&gt;。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;为什么列表项需要 key？&lt;/td&gt;&lt;td&gt;&lt;code&gt;TransitionGroup&lt;/code&gt; 使用 key 追踪元素移动，实现平滑的移动动画。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;mode 属性的作用？&lt;/td&gt;&lt;td&gt;&lt;code&gt;out-in&lt;/code&gt;：旧元素先离开，新元素再进入。&lt;code&gt;in-out&lt;/code&gt;：新元素先进入，旧元素再离开。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;如何自定义动画时长？&lt;/td&gt;&lt;td&gt;通过 &lt;code&gt;duration&lt;/code&gt; prop：&lt;code&gt;&amp;#x3C;Transition :duration=&quot;500&quot;&gt;&lt;/code&gt; 或 &lt;code&gt;{ enter: 500, leave: 800 }&lt;/code&gt;。&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;keepalive&quot;&gt;KeepAlive&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;max 属性的作用？&lt;/td&gt;&lt;td&gt;限制缓存组件数量，超出时移除最久未访问的。&lt;code&gt;&amp;#x3C;KeepAlive :max=&quot;10&quot;&gt;&lt;/code&gt;。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;组件必须有 name 属性吗？&lt;/td&gt;&lt;td&gt;使用 &lt;code&gt;include&lt;/code&gt; / &lt;code&gt;exclude&lt;/code&gt; 时需要。&lt;code&gt;&amp;#x3C;script setup&gt;&lt;/code&gt; 组件名默认是文件名。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;特殊生命周期钩子？&lt;/td&gt;&lt;td&gt;&lt;code&gt;onActivated&lt;/code&gt;（激活时）、&lt;code&gt;onDeactivated&lt;/code&gt;（停用时）。用于处理缓存组件的状态恢复。&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;异步组件&quot;&gt;异步组件&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;delay 选项的作用？&lt;/td&gt;&lt;td&gt;延迟显示加载状态，避免加载很快时出现闪烁。默认 200ms。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;hydration 策略是什么？&lt;/td&gt;&lt;td&gt;Vue 3.5+ 支持延迟 hydration：&lt;code&gt;defineAsyncComponent({ loader, hydrate: &apos;visible&apos; })&lt;/code&gt;。&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;typescript-集成&quot;&gt;TypeScript 集成&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;如何为 defineProps 提供类型？&lt;/td&gt;&lt;td&gt;基于类型：&lt;code&gt;defineProps&amp;#x3C;{ title: string }&gt;()&lt;/code&gt;。基于运行时：&lt;code&gt;defineProps({ title: String })&lt;/code&gt;。推荐前者。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;withDefaults 如何使用？&lt;/td&gt;&lt;td&gt;&lt;code&gt;withDefaults(defineProps&amp;#x3C;Props&gt;(), { count: 0 })&lt;/code&gt;，为类型定义的 props 提供默认值。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;如何获取组件实例类型？&lt;/td&gt;&lt;td&gt;&lt;code&gt;InstanceType&amp;#x3C;typeof MyComponent&gt;&lt;/code&gt;，用于 ref 的类型标注。&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ts&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 完整示例&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; MyComponent &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;./MyComponent.vue&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; compRef&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; ref&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;InstanceType&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;typeof&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; MyComponent&gt;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;onMounted&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(() &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  compRef.value?.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;focus&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 类型安全的方法调用&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;})&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;ssr-注意事项&quot;&gt;SSR 注意事项&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;/td&gt;&lt;td&gt;每个请求创建新的应用实例。避免在模块顶层创建响应式状态。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;服务端可以使用哪些 API？&lt;/td&gt;&lt;td&gt;不能用 &lt;code&gt;window&lt;/code&gt;、&lt;code&gt;document&lt;/code&gt; 等浏览器 API。生命周期只有 &lt;code&gt;setup&lt;/code&gt;、&lt;code&gt;onServerPrefetch&lt;/code&gt;。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;getSSRProps 的作用？&lt;/td&gt;&lt;td&gt;在 SSR 时修改组件 props，常用于注入服务端数据。&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;性能优化&quot;&gt;性能优化&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;props 稳定性为什么重要？&lt;/td&gt;&lt;td&gt;子组件使用 &lt;code&gt;shallowRef&lt;/code&gt; 时，props 引用变化会触发重新渲染。尽量保持 props 引用稳定。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;何时使用虚拟滚动？&lt;/td&gt;&lt;td&gt;渲染超过 1000 项的列表时。使用 &lt;code&gt;vue-virtual-scroller&lt;/code&gt; 等库。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;v-once 和 v-memo 的区别？&lt;/td&gt;&lt;td&gt;&lt;code&gt;v-once&lt;/code&gt;：只渲染一次，永不更新。&lt;code&gt;v-memo&lt;/code&gt;：条件性跳过更新，依赖数组未变时复用。&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;sfc-特性&quot;&gt;SFC 特性&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;如何在 scoped 样式中修改子组件？&lt;/td&gt;&lt;td&gt;使用 &lt;code&gt;:deep()&lt;/code&gt; 伪类：&lt;code&gt;.parent :deep(.child) { }&lt;/code&gt;。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;scoped CSS 的限制？&lt;/td&gt;&lt;td&gt;不影响子组件的根元素（会自动添加 scoped 属性）。深层元素需要 &lt;code&gt;:deep()&lt;/code&gt;。&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;插件开发&quot;&gt;插件开发&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;插件应该用 provide/inject 吗？&lt;/td&gt;&lt;td&gt;是的。插件通过 provide 提供功能，组件通过 inject 使用，比全局属性更灵活。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;注入 key 命名约定？&lt;/td&gt;&lt;td&gt;使用 Symbol 避免冲突：&lt;code&gt;export const myPluginKey = Symbol()&lt;/code&gt;。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;如何为插件添加类型支持？&lt;/td&gt;&lt;td&gt;通过模块扩展：&lt;code&gt;declare module &apos;vue&apos; { interface ComponentCustomProperties { $myPlugin: MyPlugin } }&lt;/code&gt;。&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id=&quot;第四部分为什么选择-unocss-而不是-tailwind-css&quot;&gt;第四部分：为什么选择 UnoCSS 而不是 Tailwind CSS？&lt;/h2&gt;
&lt;h3 id=&quot;核心论点unocss-是-tailwind-的超集&quot;&gt;核心论点：UnoCSS 是 Tailwind 的超集&lt;/h3&gt;
&lt;p&gt;UnoCSS 不是 Tailwind 的竞争者，而是增强版。通过预设系统，UnoCSS 可以 &lt;strong&gt;100% 兼容 Tailwind 语法&lt;/strong&gt;：&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ts&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// uno.config.ts&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { defineConfig, presetWind } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;unocss&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;export&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; default&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; defineConfig&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  presets: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    presetWind&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(), &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// Tailwind CSS v3 兼容&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // 或 presetWind({ version: 4 }) // Tailwind CSS v4 兼容&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;})&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;使用 &lt;code&gt;presetWind&lt;/code&gt; 后，所有 Tailwind 类名都能正常工作：&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;html&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;&amp;#x3C;!-- Tailwind 语法完全兼容 --&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;flex items-center justify-between p-4 bg-blue-500 text-white rounded-lg shadow-md hover:bg-blue-600 transition&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;span&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;text-xl font-bold&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;完全兼容&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;span&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;unocss-的独家能力&quot;&gt;UnoCSS 的独家能力&lt;/h3&gt;
&lt;h4 id=&quot;1-纯-css-图标零-js-运行时&quot;&gt;1. 纯 CSS 图标（零 JS 运行时）&lt;/h4&gt;
&lt;p&gt;UnoCSS 通过 &lt;code&gt;presetIcons&lt;/code&gt; 支持 &lt;strong&gt;10 万+ Iconify 图标&lt;/strong&gt;，编译为纯 CSS，零 JavaScript 运行时开销：&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;pnpm&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; add&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -D&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; @iconify-json/carbon&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; @iconify-json/mdi&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;html&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;&amp;#x3C;!-- 直接用 class 引用图标，无需导入 --&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;i-carbon-logo-github text-2xl&quot;&lt;/span&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;i-mdi-home text-red-500&quot;&lt;/span&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;i-carbon-arrow-right hover:i-carbon-arrow-right-filled&quot;&lt;/span&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;编译结果（纯 CSS）：&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;css&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;.i-carbon-logo-github&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  display&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;inline-block&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  width&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;em&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  height&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;em&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  background&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;url&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;data:image/svg+xml;utf8,...&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;no-repeat&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  background-size&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;100&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 100&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;对比 Tailwind + React Icons：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Tailwind：需要导入 React/Vue 组件，增加 bundle 体积&lt;/li&gt;
&lt;li&gt;UnoCSS：纯 CSS，零 JS，图标按需编译&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;2-属性化模式attributify&quot;&gt;2. 属性化模式（Attributify）&lt;/h4&gt;
&lt;p&gt;避免 class 字符串爆炸：&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;html&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;&amp;#x3C;!-- Tailwind：class 字符串过长 --&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded-lg shadow-md transition duration-300 flex items-center gap-2&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  提交&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;&amp;#x3C;!-- UnoCSS：属性化模式 --&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  bg&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;blue-500 hover:blue-600&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  text&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;white&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  font&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;bold&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  p&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;y-2 x-4&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  rounded&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;lg&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  shadow&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;md&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  transition&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  duration&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;300&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  flex&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  items&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;center&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  gap&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;2&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  提交&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;3-variant-group变体组简写&quot;&gt;3. Variant Group（变体组简写）&lt;/h4&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;html&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;&amp;#x3C;!-- Tailwind：重复写 hover --&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;hover:bg-red-500 hover:text-white hover:scale-105&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;&amp;#x3C;!-- UnoCSS：Variant Group --&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;hover:(bg-red-500 text-white scale-105)&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;4-自定义规则引擎&quot;&gt;4. 自定义规则引擎&lt;/h4&gt;
&lt;p&gt;Tailwind 需要配置复杂的插件系统，UnoCSS 支持正则和函数定义原子类：&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ts&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// uno.config.ts&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { defineConfig } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;unocss&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;export&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; default&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; defineConfig&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  rules: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // 正则匹配：自定义间距&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    [&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;^&lt;/span&gt;&lt;span style=&quot;color:#DBEDFF&quot;&gt;m-(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;\d&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#DBEDFF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, ([, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ({ margin: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;`${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;d&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}px`&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; })],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // 函数定义：自定义颜色&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    [&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;text-brand&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, { color: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;#3b82f6&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; }],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // 动态值：任意单位&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    [&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;^&lt;/span&gt;&lt;span style=&quot;color:#DBEDFF&quot;&gt;gap-(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;\d&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#DBEDFF&quot;&gt;)(px&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:#DBEDFF&quot;&gt;rem&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:#DBEDFF&quot;&gt;em)&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, ([, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;num&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;unit&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ({ gap: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;`${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;num&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;unit&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}`&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; })],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  shortcuts: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // 快捷组合类&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &apos;btn-primary&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;})&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;5-编译模式compile-class&quot;&gt;5. 编译模式（Compile Class）&lt;/h4&gt;
&lt;p&gt;将多个原子类编译为一个哈希类，减少 HTML 体积：&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;html&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;&amp;#x3C;!-- 开发模式：原子类 --&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;flex items-center gap-4 bg-blue-500 p-4&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;&amp;#x3C;!-- 生产模式：编译为单个类 --&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;uno-abc123&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;style&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;.uno-abc123&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  display&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;flex&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  align-items&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;center&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  gap&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;rem&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  background&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;#3b82f6&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  padding&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;rem&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;style&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;对比总结&quot;&gt;对比总结&lt;/h3&gt;


















































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;特性&lt;/th&gt;&lt;th&gt;Tailwind CSS&lt;/th&gt;&lt;th&gt;UnoCSS&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;基础原子类&lt;/td&gt;&lt;td&gt;✅ 完整支持&lt;/td&gt;&lt;td&gt;✅ 完全兼容（presetWind）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;图标方案&lt;/td&gt;&lt;td&gt;需要额外库（React Icons 等）&lt;/td&gt;&lt;td&gt;✅ 内置 10 万+ 图标（纯 CSS）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;属性化模式&lt;/td&gt;&lt;td&gt;❌ 不支持&lt;/td&gt;&lt;td&gt;✅ presetAttributify&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Variant Group&lt;/td&gt;&lt;td&gt;❌ 不支持&lt;/td&gt;&lt;td&gt;✅ &lt;code&gt;hover:(bg-red text-white)&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&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;/td&gt;&lt;td&gt;❌ 不支持&lt;/td&gt;&lt;td&gt;✅ 编译为哈希类&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;性能&lt;/td&gt;&lt;td&gt;JIT 编译快&lt;/td&gt;&lt;td&gt;✅ 更快（Vite 原生）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;生态整合&lt;/td&gt;&lt;td&gt;Standalone&lt;/td&gt;&lt;td&gt;✅ Vite/Nuxt 深度集成&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;与-anthony-fu-技术栈的协同&quot;&gt;与 Anthony Fu 技术栈的协同&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Vite 原生设计&lt;/strong&gt;：UnoCSS 为 Vite 设计，HMR 极快&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Nuxt 一等公民&lt;/strong&gt;：&lt;code&gt;@nuxt/unocss&lt;/code&gt; 开箱即用&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;作者生态&lt;/strong&gt;：Anthony Fu 同时是 UnoCSS 和 Iconify 的作者，工具链深度整合&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;完整配置示例&quot;&gt;完整配置示例&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ts&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// uno.config.ts&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  defineConfig,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  presetAttributify,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  presetIcons,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  presetTypography,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  presetUno,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  presetWebFonts,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  transformerDirectives,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  transformerVariantGroup,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;} &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;unocss&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;export&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; default&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; defineConfig&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  // 预设&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  presets: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    presetUno&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(), &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 默认预设（类似 Tailwind）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    presetAttributify&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(), &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 属性化模式&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    presetIcons&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      scale: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      cdn: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;https://esm.sh/&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    presetTypography&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(), &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 排版预设&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    presetWebFonts&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      fonts: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        sans: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Inter&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        mono: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Fira Code&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  // 转换器&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  transformers: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    transformerDirectives&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(), &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// @apply 指令&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    transformerVariantGroup&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(), &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// Variant Group&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  // 自定义规则&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  rules: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    [&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;text-brand&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, { color: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;#3b82f6&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; }],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  // 快捷方式&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  shortcuts: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &apos;btn&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;px-4 py-2 rounded inline-block cursor-pointer&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &apos;btn-primary&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;btn bg-blue-500 text-white hover:bg-blue-600&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  // 主题扩展&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  theme: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    colors: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      brand: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        primary: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;#3b82f6&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        secondary: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;#8b5cf6&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;})&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;安装命令：&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;pnpm&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; add&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -D&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; unocss&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;pnpm&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; add&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -D&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; @iconify-json/carbon&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; @iconify-json/mdi&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2 id=&quot;第五部分配套工具链一览&quot;&gt;第五部分：配套工具链一览&lt;/h2&gt;






































































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;工具&lt;/th&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;strong&gt;Vue 3.5+&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;渐进式 JavaScript 框架&lt;/td&gt;&lt;td&gt;Composition API、性能优化、TypeScript 支持&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Nuxt 3&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Vue 元框架&lt;/td&gt;&lt;td&gt;SSR/SSG、文件路由、服务端 API、SEO 优化&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Pinia&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;状态管理&lt;/td&gt;&lt;td&gt;直观的 API、完整的 TypeScript 支持、Vue DevTools 集成&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Vite&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;构建工具&lt;/td&gt;&lt;td&gt;极速 HMR、原生 ESM、Rollup 生产构建&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;VitePress&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;静态站点生成器&lt;/td&gt;&lt;td&gt;Vue 驱动、Markdown 扩展、主题定制&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Vitest&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;单元测试&lt;/td&gt;&lt;td&gt;Vite 原生、与 Jest 兼容的 API、快速执行&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;UnoCSS&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;原子化 CSS 引擎&lt;/td&gt;&lt;td&gt;Tailwind 超集、纯 CSS 图标、Vite 深度集成&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;pnpm&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;包管理器&lt;/td&gt;&lt;td&gt;磁盘高效、严格依赖管理、monorepo 支持&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;VueUse&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;组合式函数集合&lt;/td&gt;&lt;td&gt;200+ 实用工具、SSR 友好、Tree-shakable&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Slidev&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;开发者幻灯片&lt;/td&gt;&lt;td&gt;Markdown 编写、Vue 组件、录制功能&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;tsdown&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;TypeScript 打包工具&lt;/td&gt;&lt;td&gt;零配置、类型声明生成、ESM/CJS 双输出&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Vue Router&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=&quot;快速开始命令&quot;&gt;快速开始命令&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 创建 Vue 3 项目（Vite）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;pnpm&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; create&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; vite&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; my-vue-app&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --template&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; vue-ts&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 创建 Nuxt 3 项目&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;pnpm&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; dlx&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; nuxi@latest&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; init&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; my-nuxt-app&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 添加 UnoCSS&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;pnpm&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; add&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -D&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; unocss&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 添加 VueUse&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;pnpm&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; add&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; @vueuse/core&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 添加 Pinia&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;pnpm&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; add&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; pinia&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 添加 Vitest&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;pnpm&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; add&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -D&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; vitest&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2 id=&quot;总结&quot;&gt;总结&lt;/h2&gt;
&lt;p&gt;Anthony Fu 的开发规范强调：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;类型安全优先&lt;/strong&gt;：TypeScript + 显式类型定义&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;性能意识&lt;/strong&gt;：&lt;code&gt;shallowRef&lt;/code&gt; &gt; &lt;code&gt;ref&lt;/code&gt;、避免深度侦听、虚拟滚动&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;工具链协同&lt;/strong&gt;：Vite + UnoCSS + Vitest 深度整合&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;代码质量&lt;/strong&gt;：单一职责、ESLint 自动化、Git Hooks&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;现代化实践&lt;/strong&gt;：Composition API、&lt;code&gt;&amp;#x3C;script setup&gt;&lt;/code&gt;、组合式函数&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;通过遵循这些规范，可以构建更快、更可维护、更具扩展性的 Vue 3 应用。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;参考资料：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/antfu/skills&quot;&gt;antfu/skills&lt;/a&gt; - Anthony Fu 的技能标准文档&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vuejs.org/&quot;&gt;Vue 3 官方文档&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://unocss.dev/&quot;&gt;UnoCSS 文档&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vueuse.org/&quot;&gt;VueUse 文档&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;译者注：&lt;/strong&gt; 本文基于 antfu/skills 仓库于 2026 年 2 月的内容整理翻译，随着生态演进，部分实践可能更新，请以官方文档为准。&lt;/p&gt;</content:encoded><category>Vue</category><category>前端工程化</category><category>Typescript</category></item><item><title>Lenis 与 GSAP ScrollTrigger 深度解析</title><link>https://feichuans.com/blogs/05-archive/lenis-%E4%B8%8E-gsap-scrolltrigger-%E6%B7%B1%E5%BA%A6%E8%A7%A3%E6%9E%90/</link><guid isPermaLink="true">https://feichuans.com/blogs/05-archive/lenis-%E4%B8%8E-gsap-scrolltrigger-%E6%B7%B1%E5%BA%A6%E8%A7%A3%E6%9E%90/</guid><description>深入剖析 Lenis 平滑滚动与 GSAP ScrollTrigger 的工作原理，从浏览器原生滚动到虚拟滚动，从 scrollerProxy 配置到实战应用，带你彻底理解现代网页滚动动画的实现机制</description><pubDate>Thu, 29 Jan 2026 16:50:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;lenis-与-gsap-scrolltrigger-深度解析&quot;&gt;Lenis 与 GSAP ScrollTrigger 深度解析&lt;/h1&gt;
&lt;p&gt;在现代网页设计中，流畅的滚动体验已经成为高品质网站的标配。本文将深入剖析 Lenis 平滑滚动库与 GSAP ScrollTrigger 的协作原理，带你从底层理解如何打造丝滑的滚动动画。&lt;/p&gt;
&lt;h2 id=&quot;一浏览器原生滚动-vs-虚拟滚动&quot;&gt;一、浏览器原生滚动 vs 虚拟滚动&lt;/h2&gt;
&lt;h3 id=&quot;原生滚动的局限&quot;&gt;原生滚动的局限&lt;/h3&gt;
&lt;p&gt;浏览器原生的滚动机制虽然简单直接，但存在明显的问题：&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 浏览器原生滚动&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;window.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;scrollTo&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 立即跳转，生硬&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 用户滚轮事件&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;document.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;addEventListener&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;wheel&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, (&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;e&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  // 浏览器直接改变 scrollTop，没有缓动&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  window.scrollY &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; e.deltaY;  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;主要问题：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;❌ 滚动是离散的、跳跃的&lt;/li&gt;
&lt;li&gt;❌ 没有惯性效果&lt;/li&gt;
&lt;li&gt;❌ 不同设备滚动速度差异大&lt;/li&gt;
&lt;li&gt;❌ 无法自定义缓动曲线&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;虚拟滚动lenis的核心思想&quot;&gt;虚拟滚动（Lenis）的核心思想&lt;/h3&gt;
&lt;p&gt;Lenis 通过”虚拟滚动”技术彻底改变了这一现状：&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;真实滚动：&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;┌─────────────┐&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│  viewport   │ ← 固定不动（overflow: hidden）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;└─────────────┘&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      ↓&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;   内容通过 transform 移动&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      ↓&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;┌─────────────┐&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   content   │ ← transform: translateY(-1000px)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│             │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   (很长)    │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;└─────────────┘&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;工作流程：&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;用户滚轮 → Lenis 监听 → 计算目标位置 → RAF 动画循环 → 更新 transform&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;关键点：页面实际上&lt;strong&gt;没有滚动&lt;/strong&gt;，只是内容元素通过 &lt;code&gt;transform&lt;/code&gt; 属性在移动，产生滚动的视觉效果。&lt;/p&gt;
&lt;h2 id=&quot;二lenis-配置详解&quot;&gt;二、Lenis 配置详解&lt;/h2&gt;
&lt;h3 id=&quot;基础配置示例&quot;&gt;基础配置示例&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; lenis&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Lenis&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  wrapper: document.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;querySelector&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;.smooth-wrapper&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  content: document.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;querySelector&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;.smooth-content&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  duration: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  easing&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: (&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;t&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; Math.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;min&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.001&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; Math.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;pow&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; t)),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  orientation: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;vertical&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  gestureOrientation: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;vertical&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  smoothWheel: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  wheelMultiplier: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  smoothTouch: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  touchMultiplier: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  infinite: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;关键参数深度解析&quot;&gt;关键参数深度解析&lt;/h3&gt;
&lt;h4 id=&quot;1-wrapper-与-content双层结构的必要性&quot;&gt;1. &lt;code&gt;wrapper&lt;/code&gt; 与 &lt;code&gt;content&lt;/code&gt;：双层结构的必要性&lt;/h4&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;html&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;smooth-wrapper&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;     ← wrapper（视口，overflow: hidden）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;smooth-content&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;   ← content（被移动的内容）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;article&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;...&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;article&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;article&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;...&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;article&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  &amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;为什么需要两层？&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;wrapper&lt;/code&gt;：固定尺寸的视口容器，用户实际看到的区域&lt;/li&gt;
&lt;li&gt;&lt;code&gt;content&lt;/code&gt;：真实内容容器，通过 &lt;code&gt;transform: translateY()&lt;/code&gt; 移动&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这种分离设计是虚拟滚动的基础，&lt;code&gt;wrapper&lt;/code&gt; 负责”窗口”，&lt;code&gt;content&lt;/code&gt; 负责”画布”。&lt;/p&gt;
&lt;h4 id=&quot;2-duration-12缓动响应时间&quot;&gt;2. &lt;code&gt;duration: 1.2&lt;/code&gt;：缓动响应时间&lt;/h4&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 注意：这不是&quot;滚动到目标位置的总时间&quot;！&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 而是&quot;缓动响应速度&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 举例：&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;用户滚轮滚动 100px&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    ↓&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;Lenis 不会立即移动 100px&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    ↓&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;而是在约 &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; 秒内&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;追赶&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;到目标位置&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    ↓&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;产生平滑、有惯性的效果&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;数值越大，滚动越”慵懒”；越小，响应越灵敏。&lt;/p&gt;
&lt;h4 id=&quot;3-easing-函数自定义缓动曲线&quot;&gt;3. &lt;code&gt;easing&lt;/code&gt; 函数：自定义缓动曲线&lt;/h4&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;easing&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: (&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;t&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; Math.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;min&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.001&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; Math.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;pow&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; t))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;//       ↑&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;//    t = 0 到 1 的进度值&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 这是一个&quot;ease-out&quot;曲线：&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// t=0   → 0      (开始快)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// t=0.5 → 0.999  (中间快)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// t=1   → 1      (结束慢)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 效果：滚动快速启动，然后自然减速停止&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;你可以使用任何缓动函数，比如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;t =&gt; t&lt;/code&gt;：线性&lt;/li&gt;
&lt;li&gt;&lt;code&gt;t =&gt; t * t&lt;/code&gt;：ease-in&lt;/li&gt;
&lt;li&gt;&lt;code&gt;t =&gt; 1 - Math.pow(1 - t, 3)&lt;/code&gt;：ease-out cubic&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;4-smoothwheel-true惯性滚动的关键&quot;&gt;4. &lt;code&gt;smoothWheel: true&lt;/code&gt;：惯性滚动的关键&lt;/h4&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// false: 每次滚轮事件立即到达目标&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;document.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;addEventListener&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;wheel&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, (&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;e&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  scrollTo&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(current &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; e.deltaY);  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 立即跳转，无缓动&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;});&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// true: 滚轮事件累积速度，产生惯性&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; velocity &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;document.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;addEventListener&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;wheel&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, (&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;e&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  velocity &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; e.deltaY;  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 累积速度&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  // RAF 循环中逐渐应用速度，形成惯性&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;开启后，滚动会有”物理感”，就像真实世界中推动一个物体。&lt;/p&gt;
&lt;h3 id=&quot;lenis-内部运作机制&quot;&gt;Lenis 内部运作机制&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// Lenis 内部简化版伪代码&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Lenis&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  raf&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // 1. 获取当前滚动位置&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; current&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; this&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.scroll;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // 2. 获取目标位置（用户想滚动到哪里）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; target&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; this&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.targetScroll;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // 3. 计算差值并应用缓动&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; delta&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; target &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; current;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; easedDelta&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; delta &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; this&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;easing&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(progress);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    this&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.scroll &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; easedDelta;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // 4. 更新 DOM（核心！）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    this&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.content.style.transform &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; `translateY(-${&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;scroll&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}px)`&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // 5. 触发 scroll 事件供外部监听&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    this&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;emit&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;scroll&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, { scroll: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.scroll });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // 6. 继续下一帧&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    requestAnimationFrame&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;((&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;t&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; this&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;raf&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(t));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;关键点：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;使用 &lt;code&gt;requestAnimationFrame&lt;/code&gt; 保证 60fps 流畅度&lt;/li&gt;
&lt;li&gt;每帧计算缓动，逐渐接近目标位置&lt;/li&gt;
&lt;li&gt;通过 &lt;code&gt;transform&lt;/code&gt; 而非 &lt;code&gt;scrollTop&lt;/code&gt; 移动内容（GPU 加速）&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;三scrolltrigger-与虚拟滚动的冲突&quot;&gt;三、ScrollTrigger 与虚拟滚动的冲突&lt;/h2&gt;
&lt;h3 id=&quot;scrolltrigger-的默认行为&quot;&gt;ScrollTrigger 的默认行为&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ScrollTrigger 默认监听 window.scroll 事件&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;window.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;addEventListener&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;scroll&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, () &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; scrollY&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; window.scrollY;  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 获取滚动位置&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  // 检查每个 trigger 元素&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  triggers.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;forEach&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;trigger&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; rect&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; trigger.element.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;getBoundingClientRect&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (rect.top &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; window.innerHeight) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      trigger.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;activate&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 触发动画&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;核心问题lenis-不触发-scroll-事件&quot;&gt;核心问题：Lenis 不触发 scroll 事件&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// Lenis 的滚动是虚拟的：&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;content.style.transform &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;translateY(-1000px)&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;//                        ↑&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;//                 DOM 没有真正滚动！&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 所以：&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;window.scrollY                  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 永远是 0 ❌&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;document.documentElement.scrollTop  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 永远是 0 ❌&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ScrollTrigger 完全检测不到滚动！&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这就是为什么简单地结合 Lenis 和 ScrollTrigger 会失败的原因。&lt;/p&gt;
&lt;h2 id=&quot;四scrollerproxy桥接两个世界&quot;&gt;四、scrollerProxy：桥接两个世界&lt;/h2&gt;
&lt;h3 id=&quot;为什么需要-scrollerproxy&quot;&gt;为什么需要 scrollerProxy？&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;scrollerProxy&lt;/code&gt; 是 GSAP 提供的 API，用于告诉 ScrollTrigger：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;如何获取自定义滚动容器的滚动位置&lt;/li&gt;
&lt;li&gt;如何设置滚动位置&lt;/li&gt;
&lt;li&gt;容器的边界信息&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;完整配置示例&quot;&gt;完整配置示例&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;ScrollTrigger.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;scrollerProxy&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;.smooth-wrapper&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  // 1. 滚动位置的获取/设置&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  scrollTop&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;value&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;arguments&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;length&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;      // ScrollTrigger 想设置滚动位置&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      lenis.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;scrollTo&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(value, { immediate: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // ScrollTrigger 想获取滚动位置&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; lenis.scroll;  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 返回 Lenis 的虚拟滚动位置&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  // 2. 容器边界信息&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  getBoundingClientRect&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      top: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      left: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      width: window.innerWidth,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      height: window.innerHeight,  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 视口高度&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  // 3. 定位模式&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  pinType: wrapper.style.transform &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;transform&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; :&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;fixed&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;深度解析每个方法&quot;&gt;深度解析每个方法&lt;/h3&gt;
&lt;h4 id=&quot;scrolltopvalue双向桥接&quot;&gt;&lt;code&gt;scrollTop(value)&lt;/code&gt;：双向桥接&lt;/h4&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;scrollTop&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(value) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;arguments&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;length&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // 有参数 = ScrollTrigger 想设置滚动位置&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    lenis.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;scrollTo&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(value, { immediate: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    //                      ↑&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    //         立即跳转，不要动画&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    //        （ScrollTrigger 自己控制动画）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  // 无参数 = ScrollTrigger 想获取当前位置&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; lenis.scroll;  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 返回虚拟滚动位置&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ScrollTrigger 内部会频繁调用：&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; pos&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; scroller.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;scrollTop&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 获取位置&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;scroller.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;scrollTop&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);          &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 设置位置（用于 pin 等功能）&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;getboundingclientrect定义视口&quot;&gt;&lt;code&gt;getBoundingClientRect()&lt;/code&gt;：定义视口&lt;/h4&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;getBoundingClientRect&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  // ScrollTrigger 需要知道&quot;视口&quot;的位置和尺寸&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    top: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,        &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 容器顶部 = 视口顶部&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    left: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    width: window.innerWidth,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    height: window.innerHeight,  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 容器高度 = 视口高度&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ScrollTrigger 用它来计算：&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// &quot;trigger 元素距离容器顶部的距离&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// &quot;start/end 位置的具体像素值&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;为什么是固定值？&lt;/strong&gt;
因为 &lt;code&gt;.smooth-wrapper&lt;/code&gt; 总是填满整个视口，所以边界就是窗口边界。&lt;/p&gt;
&lt;h4 id=&quot;pintype固定元素的定位方式&quot;&gt;&lt;code&gt;pinType&lt;/code&gt;：固定元素的定位方式&lt;/h4&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;pinType&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: wrapper.style.transform &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;transform&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; :&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;fixed&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 用于 ScrollTrigger 的 pin 功能&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 如果容器使用了 transform，固定元素也要用 transform&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 否则用 CSS fixed 定位&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;同步更新机制&quot;&gt;同步更新机制&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// Lenis 每帧更新时，通知 ScrollTrigger&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;lenis.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;on&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;scroll&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, ({ &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;scroll&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;limit&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; }) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  ScrollTrigger.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;update&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 强制 ScrollTrigger 重新计算所有触发器&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;});&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ScrollTrigger.update() 内部做什么？&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 1. 调用 scrollerProxy.scrollTop() 获取最新滚动位置&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 2. 重新计算所有 trigger 的状态（是否进入触发区）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 3. 激活应该播放的动画&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;完整的同步代码：&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 在 GSAP ticker 中运行 Lenis&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;gsap.ticker.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;add&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;((&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  lenis.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;raf&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(time &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// time 是秒，Lenis 需要毫秒&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;});&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 禁用 lag smoothing，避免帧率波动时的卡顿&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;gsap.ticker.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;lagSmoothing&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 当 ScrollTrigger 刷新时，也刷新 Lenis&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;ScrollTrigger.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;addEventListener&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;refresh&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, () &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; lenis.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;resize&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;());&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;五实战博客列表滚动动画&quot;&gt;五、实战：博客列表滚动动画&lt;/h2&gt;
&lt;h3 id=&quot;完整配置代码&quot;&gt;完整配置代码&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 初始化动画&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; initScrollAnimations&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; blogItems&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; document.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;querySelectorAll&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;.blog-item&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; scroller&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; document.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;querySelector&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;.smooth-wrapper&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  blogItems.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;forEach&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;((&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;item&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;index&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // 设置初始状态&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    gsap.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(item, {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      y: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;100&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,       &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 向下偏移 100px&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      opacity: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,   &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 完全透明&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // 创建滚动触发动画&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    gsap.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;to&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(item, {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      y: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,           &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 移动到原位&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      opacity: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 完全不透明&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      duration: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 动画持续 1.2 秒&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      ease: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;power3.out&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 缓动函数&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      scrollTrigger: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        trigger: item,                 &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 触发元素&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        scroller: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;.smooth-wrapper&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,   &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 自定义滚动容器&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        start: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;top bottom-=100&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,      &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 开始位置&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        end: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;top center&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,             &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 结束位置&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        toggleActions: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;play none none none&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        markers: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,                 &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 调试标记&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  ScrollTrigger.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;refresh&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;参数详解&quot;&gt;参数详解&lt;/h3&gt;
&lt;h4 id=&quot;trigger-item&quot;&gt;&lt;code&gt;trigger: item&lt;/code&gt;&lt;/h4&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;视口 (viewport)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;┌─────────────────┐&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│                 │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│                 │  ← item 的位置&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;└─────────────────┘&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;       ↑&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  监听这个元素相对于视口的位置&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;scroller-smooth-wrapper&quot;&gt;&lt;code&gt;scroller: &quot;.smooth-wrapper&quot;&lt;/code&gt;&lt;/h4&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 告诉 ScrollTrigger：&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// &quot;不要监听 window，监听 .smooth-wrapper&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ScrollTrigger 会：&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 1. 查找之前定义的 scrollerProxy(&quot;.smooth-wrapper&quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 2. 使用 proxy 的 scrollTop() 获取滚动位置&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 3. 使用 proxy 的 getBoundingClientRect() 计算边界&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;start-top-bottom-100&quot;&gt;&lt;code&gt;start: &quot;top bottom-=100&quot;&lt;/code&gt;&lt;/h4&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;语法: &quot;[trigger位置] [scroller位置]&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&quot;top bottom-=100&quot; 含义：&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;┌──────────────────┐ ← scroller top&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│                  │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   viewport       │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│                  │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│                  │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;├──────────────────┤ ← scroller bottom&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│      ↑           │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│    100px         │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;├──────────────────┤ ← bottom-100 (触发线)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│      ↑           │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│  当 trigger.top 到达这里时开始动画&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│                  │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;└──────────────────┘&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;// 效果：元素还没完全进入视口时，就提前开始动画&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;end-top-center&quot;&gt;&lt;code&gt;end: &quot;top center&quot;&lt;/code&gt;&lt;/h4&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&quot;top center&quot; 含义：&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;┌──────────────────┐ ← scroller top&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│                  │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;├──────────────────┤ ← scroller center (50% 高度)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│      ↑           │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│  trigger.top 到达这里时动画结束&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│                  │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;└──────────────────┘ ← scroller bottom&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;// 动画从 start 到 end 之间的滚动距离内完成&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;toggleactions-play-none-none-none&quot;&gt;&lt;code&gt;toggleActions: &quot;play none none none&quot;&lt;/code&gt;&lt;/h4&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;toggleActions&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;onEnter onLeave onEnterBack onLeaveBack&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;//              ↓       ↓        ↓           ↓&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;//           向下滚   向下滚    向上滚      向上滚&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;//           进入     离开      再次进入    再次离开&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;play none none none&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; 含义：&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; 向下滚动进入触发区：play（播放动画）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; 向下滚动离开触发区：none（保持状态）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; 向上滚动回到触发区：none（保持状态）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; 向上滚动离开触发区：none（保持状态）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 效果：只在第一次进入时播放一次，之后保持结束状态&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 其他常用配置：&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// &quot;play reverse play reverse&quot;  - 完全可逆的动画&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// &quot;play pause resume reset&quot;    - 离开时暂停，回来时继续&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;六完整的事件流程图&quot;&gt;六、完整的事件流程图&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;用户滚动鼠标滚轮&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    ↓&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Lenis 监听 wheel 事件&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    ↓&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Lenis 计算目标滚动位置&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    ↓&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Lenis RAF 循环（每帧）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    ↓&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;应用缓动，更新 lenis.scroll&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    ↓&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;更新 content.style.transform = `translateY(-${scroll}px)`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    ↓&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;触发 lenis.on(&apos;scroll&apos;) 事件&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    ↓&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;调用 ScrollTrigger.update()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    ↓&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;ScrollTrigger 调用 scrollerProxy.scrollTop()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    ↓&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;ScrollTrigger 获取最新虚拟滚动位置&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    ↓&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;ScrollTrigger 遍历检查所有 trigger&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    ↓&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;计算 trigger 元素的 getBoundingClientRect()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    ↓&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;判断是否进入触发区域&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    ↓&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;触发区域内的动画开始播放&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    ↓&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;GSAP 更新元素的 transform/opacity 等属性&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    ↓&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;浏览器重绘（GPU 加速）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    ↓&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;用户看到流畅的滚动动画&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;七常见问题与调试技巧&quot;&gt;七、常见问题与调试技巧&lt;/h2&gt;
&lt;h3 id=&quot;问题-1动画完全不触发&quot;&gt;问题 1：动画完全不触发&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;症状：&lt;/strong&gt; 滚动页面，元素没有任何动画效果。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;排查步骤：&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 1. 检查 scrollerProxy 是否配置&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;console.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(ScrollTrigger.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;getScrollFunc&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;.smooth-wrapper&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 应该返回一个函数，如果是 null，说明 proxy 未配置&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 2. 检查 Lenis 是否正常工作&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;lenis.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;on&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;scroll&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, (&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;e&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  console.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Lenis scroll:&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, e.scroll);  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 应该看到滚动值变化&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;});&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 3. 检查 ScrollTrigger 是否收到更新&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;lenis.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;on&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;scroll&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, () &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  console.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Updating ScrollTrigger&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  ScrollTrigger.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;update&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 确认这行有执行&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;});&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 4. 检查 scroller 参数&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;gsap.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;to&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;.item&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  scrollTrigger: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    scroller: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;.smooth-wrapper&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 必须匹配 scrollerProxy 的选择器&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;问题-2markers-位置不正确&quot;&gt;问题 2：markers 位置不正确&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;症状：&lt;/strong&gt; 开启 &lt;code&gt;markers: true&lt;/code&gt; 后，绿色/红色标记线位置异常。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;原因：&lt;/strong&gt; &lt;code&gt;getBoundingClientRect()&lt;/code&gt; 返回值不正确。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解决：&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;getBoundingClientRect&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    top: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,                    &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 必须是 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    left: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,                   &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 必须是 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    width: window.innerWidth,  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 视口宽度&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    height: window.innerHeight, &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 视口高度（不是 wrapper.offsetHeight！）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;问题-3滚动不流畅或卡顿&quot;&gt;问题 3：滚动不流畅或卡顿&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;可能原因：&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;RAF 同步问题&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 确保 Lenis 在 GSAP ticker 中运行&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;gsap.ticker.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;add&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;((&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  lenis.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;raf&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(time &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 注意：time 是秒，需要转换为毫秒&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;});&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 禁用 lag smoothing&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;gsap.ticker.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;lagSmoothing&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;&lt;strong&gt;动画性能问题&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ❌ 不好：使用 width/height/top/left（触发 layout）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;gsap.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;to&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(element, { width: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;500&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, height: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;300&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ✅ 好：只使用 transform 和 opacity（GPU 加速）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;gsap.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;to&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(element, { &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  x: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;100&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,       &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// transform: translateX&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  y: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;50&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,        &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// transform: translateY&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  scale: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,   &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// transform: scale&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  opacity: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.5&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  // opacity&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;&lt;strong&gt;过多的 ScrollTrigger 实例&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ❌ 不好：为每个元素创建独立的 ScrollTrigger&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;items.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;forEach&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;item&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  gsap.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;to&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(item, {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    scrollTrigger: { trigger: item }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;});&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ✅ 更好：批量处理&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;gsap.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;to&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;.item&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  y: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  stagger: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 交错动画&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  scrollTrigger: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    trigger: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;.container&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 统一触发区域&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;调试工具箱&quot;&gt;调试工具箱&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 查看所有 ScrollTrigger 实例&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;ScrollTrigger.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;getAll&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;forEach&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;((&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;st&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  console.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;`Trigger ${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}:`&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    trigger: st.trigger,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    start: st.start,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    end: st.end,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    scroller: st.scroller,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    progress: st.progress,  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 当前进度 0-1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;});&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 手动刷新所有 ScrollTrigger&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;ScrollTrigger.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;refresh&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 查看当前滚动位置对比&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;console.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  lenis: lenis.scroll,        &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// Lenis 虚拟滚动位置&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  window: window.scrollY,     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 应该是 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  proxy: ScrollTrigger.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;getScrollFunc&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;.smooth-wrapper&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)(),  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 应该等于 lenis.scroll&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;});&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 杀死所有 ScrollTrigger（重新初始化时）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;ScrollTrigger.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;getAll&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;forEach&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;st&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; st.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kill&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;());&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;八性能优化建议&quot;&gt;八、性能优化建议&lt;/h2&gt;
&lt;h3 id=&quot;1-使用-will-change-提示浏览器&quot;&gt;1. 使用 will-change 提示浏览器&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;css&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;.blog-item&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  /* 提前告诉浏览器这些属性会变化 */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  will-change&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: transform, opacity;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;/* 但不要滥用！只在必要时使用 */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;/* 过多的 will-change 会消耗内存 */&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;2-批量处理元素&quot;&gt;2. 批量处理元素&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ✅ 推荐：使用 stagger 批量动画&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;gsap.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;to&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;.blog-item&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  y: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  opacity: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  stagger: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    each: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,        &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 每个元素间隔 0.1 秒&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    from: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;start&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,    &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 从第一个开始&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  scrollTrigger: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    trigger: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;.blog-list&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    start: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;top bottom&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;3-防抖节流滚动事件&quot;&gt;3. 防抖/节流滚动事件&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 如果你需要在滚动时执行自定义逻辑&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; rafId;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;lenis.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;on&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;scroll&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, (&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;e&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  // 使用 RAF 防抖&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (rafId) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  rafId &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; requestAnimationFrame&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(() &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // 你的逻辑&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    console.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Scroll position:&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, e.scroll);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    rafId &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; null&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;4-懒加载动画&quot;&gt;4. 懒加载动画&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 只为视口附近的元素创建 ScrollTrigger&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; observer&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; IntersectionObserver&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;((&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;entries&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  entries.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;forEach&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;entry&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (entry.isIntersecting) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;      // 元素接近视口时才创建动画&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;      createScrollAnimation&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(entry.target);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      observer.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;unobserve&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(entry.target);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}, { rootMargin: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;200px&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;document.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;querySelectorAll&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;.blog-item&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;forEach&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;item&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  observer.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;observe&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(item);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;九总结&quot;&gt;九、总结&lt;/h2&gt;
&lt;p&gt;Lenis + GSAP ScrollTrigger 的组合强大之处在于：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Lenis&lt;/strong&gt; 提供丝滑的虚拟滚动体验&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ScrollTrigger&lt;/strong&gt; 提供强大的滚动动画能力&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;scrollerProxy&lt;/strong&gt; 桥接两者，让它们完美协作&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;关键要点：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;理解虚拟滚动的本质：内容通过 &lt;code&gt;transform&lt;/code&gt; 移动，而非真实滚动&lt;/li&gt;
&lt;li&gt;&lt;code&gt;scrollerProxy&lt;/code&gt; 是连接 Lenis 和 ScrollTrigger 的关键&lt;/li&gt;
&lt;li&gt;性能优化：优先使用 &lt;code&gt;transform&lt;/code&gt; 和 &lt;code&gt;opacity&lt;/code&gt;，避免触发 layout&lt;/li&gt;
&lt;li&gt;调试技巧：善用 &lt;code&gt;markers&lt;/code&gt;、console.log 和 ScrollTrigger API&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;掌握这些原理后，你就可以打造出媲美 Apple、Awwwards 获奖网站的高品质滚动体验了！&lt;/p&gt;
&lt;h2 id=&quot;参考资源&quot;&gt;参考资源&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://lenis.studiofreight.com/&quot;&gt;Lenis 官方文档&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://greensock.com/docs/v3/Plugins/ScrollTrigger&quot;&gt;GSAP ScrollTrigger 文档&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://codepen.io/GreenSock/pen/wvYJZNM&quot;&gt;Lenis + ScrollTrigger 官方示例&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>前端</category><category>动画</category><category>GSAP</category><category>Lenis</category></item><item><title>被 AI 逼疯的前端：从手搓流式打字机，到浏览器端跑 React</title><link>https://feichuans.com/blogs/03-areas/frontend/%E8%A2%AB-ai-%E9%80%BC%E7%96%AF%E7%9A%84%E5%89%8D%E7%AB%AF%E4%BB%8E%E6%89%8B%E6%90%93%E6%B5%81%E5%BC%8F%E6%89%93%E5%AD%97%E6%9C%BA%E5%88%B0%E6%B5%8F%E8%A7%88%E5%99%A8%E7%AB%AF%E8%B7%91-react/</link><guid isPermaLink="true">https://feichuans.com/blogs/03-areas/frontend/%E8%A2%AB-ai-%E9%80%BC%E7%96%AF%E7%9A%84%E5%89%8D%E7%AB%AF%E4%BB%8E%E6%89%8B%E6%90%93%E6%B5%81%E5%BC%8F%E6%89%93%E5%AD%97%E6%9C%BA%E5%88%B0%E6%B5%8F%E8%A7%88%E5%99%A8%E7%AB%AF%E8%B7%91-react/</guid><description>为了防止被认为是菜鸡, 所以先说一句, 第一关到第三关我还是会的 😭 面试官不要再学历挂我了好吗 前言 ： 上周一，产品经理搬着椅子坐到了我旁边：“咱们的 AI 助手体验太‘古典’了，请求发出去要转圈五秒钟才吐字。你看人家 ChatGPT，那个字是一个个蹦出来的，多解压！还有，能不能让 AI 给我写个 R…</description><pubDate>Thu, 08 Jan 2026 14:37:48 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;为了防止被认为是菜鸡, 所以先说一句, 第一关到第三关我还是会的 😭
面试官不要再学历挂我了好吗&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;前言&lt;/strong&gt;：
上周一，产品经理搬着椅子坐到了我旁边：“咱们的 AI 助手体验太‘古典’了，请求发出去要转圈五秒钟才吐字。你看人家 ChatGPT，那个字是一个个蹦出来的，多解压！还有，能不能让 AI 给我写个 React 组件，直接渲染出来让我点？就像那个 Gemini Canvas 或者 Vercel v0 一样？”&lt;/p&gt;
&lt;p&gt;我看着手里还在用 &lt;code&gt;await fetch().json()&lt;/code&gt; 的代码，陷入了沉思。
这不是加个 CSS 动画能解决的事，这是一场从网络层到渲染层的全面重构。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;这几天，我像是经历了一场前端技术的“大航海”，踩了无数坑，终于把这套 &lt;strong&gt;流式渲染（Streaming Rendering）&lt;/strong&gt; 架构跑通了。这篇文章就是我的“航海日志”，希望能帮同样在做 AI 应用的兄弟们少掉几根头发。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;第一关放弃-setinterval--真正的流式传输&quot;&gt;第一关：放弃 &lt;code&gt;setInterval&lt;/code&gt; —— 真正的流式传输&lt;/h2&gt;
&lt;p&gt;刚接手时，由于思维还停留在传统的 CRUD 模式，我天真地想：后端能不能先把生成好的文案发给我，我自己在前端搞个 &lt;code&gt;setInterval&lt;/code&gt;，每 50ms 往 &lt;code&gt;div&lt;/code&gt; 里追加一个字？&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;被打脸的瞬间&lt;/strong&gt;：
这种“伪流式”根本解决不了核心痛点——&lt;strong&gt;首字节延迟（TTFB）&lt;/strong&gt;。
如果是复杂的推理任务，后端生成完整回复可能需要 15 秒。难道让用户盯着空白屏幕转圈看 15 秒？AI 时代，&lt;strong&gt;“快”&lt;strong&gt;不代表总时长短，而代表&lt;/strong&gt;“响应开始得早”&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;所以，必须上 &lt;strong&gt;Server-Sent Events (SSE)&lt;/strong&gt; 或者 &lt;strong&gt;HTTP Chunked Transfer&lt;/strong&gt;。&lt;/p&gt;
&lt;h3 id=&quot;11-fetch-的另一面&quot;&gt;1.1 &lt;code&gt;fetch&lt;/code&gt; 的另一面&lt;/h3&gt;
&lt;p&gt;我开始深入研究 &lt;code&gt;fetch&lt;/code&gt; API。以前我们只用 &lt;code&gt;response.json()&lt;/code&gt;，但面对流，我们要用 &lt;code&gt;response.body.getReader()&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;这扇新世界的大门打开后，全是坑：&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ❌ 错误示范：以为拿到的是字符串&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; reader&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; response.body.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;getReader&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;while&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  const&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;done&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;value&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; reader.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;read&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (done) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;break&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  console.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(value); &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 打印出来全是 Uint8Array [233, 189, 128...] ???&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;12-致命的-unicode-截断&quot;&gt;1.2 致命的 Unicode 截断&lt;/h3&gt;
&lt;p&gt;拿到的 value 是 Uint8Array 二进制流。必须引入 TextDecoder 来翻译。&lt;/p&gt;
&lt;p&gt;这里藏着一个巨大的隐患：中文和 Emoji 是多字节的。&lt;/p&gt;
&lt;p&gt;一个汉字（如“好”）占 3 个字节。网络传输时，TCP 包可能会把这 3 个字节切开：前一个 Chunk 包含前 2 个字节，后一个 Chunk 包含第 3 个字节。&lt;/p&gt;
&lt;p&gt;如果你直接 decode 前一个 Chunk，会得到一个乱码符号 “。&lt;/p&gt;
&lt;p&gt;✅ 正确姿势：&lt;/p&gt;
&lt;p&gt;必须配置 { stream: true }，告诉 Decoder 内部维护一个 buffer，如果字节没凑齐一个字，就先攒着不吐出来。&lt;/p&gt;
&lt;p&gt;JavaScript&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const decoder = new TextDecoder(&apos;utf-8&apos;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;// 必须处理流式解码，防止汉字被截断导致乱码&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const chunk = decoder.decode(value, { stream: true }); &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2 id=&quot;第二关页面在跳舞-markdown-渲染的防抖算法&quot;&gt;第二关：页面在跳舞？—— Markdown 渲染的“防抖”算法&lt;/h2&gt;
&lt;p&gt;流接通了，字也能吐出来的。我兴冲冲地把这段实时变长的文本丢进 &lt;code&gt;react-markdown&lt;/code&gt; 里，结果迎来了第二个噩梦：&lt;strong&gt;Layout Shift（视觉抖动）&lt;/strong&gt;。&lt;/p&gt;
&lt;h3 id=&quot;21-灾难现场还原&quot;&gt;2.1 灾难现场还原&lt;/h3&gt;
&lt;p&gt;当 AI 试图写一段代码时，它是这样吐字的：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;收到 `👉 页面渲染为普通文本。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;收到 “ 👉 解析器认为这是 &lt;strong&gt;行内代码 (Inline Code)&lt;/strong&gt;，瞬间把这行字变成了灰色背景的小方块，字体变小，行高变矮。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;收到 “ ` 👉 &lt;strong&gt;砰！&lt;/strong&gt; 解析器判定这是 &lt;strong&gt;代码块 (Code Block)&lt;/strong&gt; 的开始，页面瞬间撑开一个占据整行宽度的黑色大框，把下面的内容全部顶飞。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;在这个毫秒级的过程中，页面像是在蹦迪，忽大忽小，用户体验极差。&lt;/p&gt;
&lt;h3 id=&quot;22-主动干预算法看不清就别画&quot;&gt;2.2 主动干预算法：看不清，就别画&lt;/h3&gt;
&lt;p&gt;查了一圈资料，没找到现成的库能完美解决这个问题。于是我写了一个预处理函数（Middleware），核心逻辑只有一句话：&lt;strong&gt;“看不清，就别画”&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;我们需要在数据交给 Markdown 组件之前，先进行清洗。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;核心代码逻辑&lt;/strong&gt;：&lt;/p&gt;
&lt;p&gt;TypeScript&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;function smoothMarkdown(content: string) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  // 1. 防抖策略：如果末尾悬挂 1 个或 2 个反引号，先暂时切掉不渲染&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  // 只有当攒够 3 个变成了 ```，或者是 `text` 这种明确格式时才放行&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  if (content.endsWith(&apos;``&apos;)) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    return content.slice(0, -2); // 🔪 切掉，等下一个包&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  } else if (content.endsWith(&apos;`&apos;)) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    return content.slice(0, -1); // 🔪 切掉&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  // 2. 自动闭合：防止代码块渲染了一半样式崩坏&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  const codeBlockCount = (content.match(/```/g) || []).length;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  if (codeBlockCount % 2 !== 0) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    return content + &apos;\n```&apos;; // 🧱 帮它补全&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  return content;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;加上这段只有几行的代码后，那个“闪烁的灰色小方块”彻底消失了。用户看到的是：文本 -&gt; 文本 -&gt; 稳稳出现的黑色代码框。&lt;strong&gt;丝滑！&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;第三关不仅是聊天--复杂数据的-ndjson-救赎&quot;&gt;第三关：不仅是聊天 —— 复杂数据的 NDJSON 救赎&lt;/h2&gt;
&lt;p&gt;需求升级了。产品经理不满足于纯文本，想让 AI 在聊天中直接丢出一个实时的“销售报表”或者“用户信息卡片”。&lt;/p&gt;
&lt;h3 id=&quot;31-jsonparse-的死穴&quot;&gt;3.1 &lt;code&gt;JSON.parse&lt;/code&gt; 的死穴&lt;/h3&gt;
&lt;p&gt;纯文本流我搞定了，但结构化数据怎么办？&lt;/p&gt;
&lt;p&gt;如果我让 AI 返回一个巨大的 JSON，万一它生成到一半卡住了，前端拿到的就是个残缺的字符串 {“user”: “Ale…。&lt;/p&gt;
&lt;p&gt;这时候 JSON.parse 是极其严格的，会直接报错抛出异常。我们总不能等整个 JSON 传完了再渲染吧？那流式就没意义了。&lt;/p&gt;
&lt;h3 id=&quot;32-救星ndjson-newline-delimited-json&quot;&gt;3.2 救星：NDJSON (Newline Delimited JSON)&lt;/h3&gt;
&lt;p&gt;我引入了一个后端架构模式：Single Request, Multiple Updates。&lt;/p&gt;
&lt;p&gt;简单说，就是让后端别一次性把所有数据给我，而是像发弹幕一样，把一个大任务拆成多个小事件，用换行符分隔：&lt;/p&gt;
&lt;p&gt;JSON&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;{&quot;type&quot;: &quot;init&quot;, &quot;status&quot;: &quot;thinking&quot;} \n&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;{&quot;type&quot;: &quot;user_info&quot;, &quot;data&quot;: {&quot;name&quot;: &quot;Alex&quot;, &quot;role&quot;: &quot;admin&quot;}} \n&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;{&quot;type&quot;: &quot;chart_data&quot;, &quot;data&quot;: {&quot;q1&quot;: 100}, &quot;isPartial&quot;: true} \n&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;33-前端-buffer-池设计&quot;&gt;3.3 前端 Buffer 池设计&lt;/h3&gt;
&lt;p&gt;在前端，我不能简单地 split(‘\n’)，因为网络包的边界可能刚好切在一行 JSON 的中间。&lt;/p&gt;
&lt;p&gt;我必须设计一个 Buffer 缓冲池：&lt;/p&gt;
&lt;p&gt;JavaScript&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;let buffer = &apos;&apos;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;while (true) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  const { value } = await reader.read();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  buffer += decoder.decode(value, { stream: true });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  // 关键：按换行符切割，但要保留最后一个可能不完整的片段&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  const lines = buffer.split(&apos;\n&apos;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  buffer = lines.pop(); // 把最后那半句塞回 buffer，等下一次拼接&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  for (const line of lines) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    if (line.trim()) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      dispatch(JSON.parse(line)); // 放心 Parse，这一行肯定是完整的&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这种感觉就像是在拼图，后端不断递给我碎片，我实时把它们拼到 Redux/Context 的状态树上。页面不再是尴尬的“Loading”，而是生动的**“Growing”**。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;第四关魔法时刻--浏览器端编译-runtime-bundling&quot;&gt;第四关：魔法时刻 —— 浏览器端编译 (Runtime Bundling)&lt;/h2&gt;
&lt;p&gt;这是最让我头秃，也最让我兴奋的一关。&lt;/p&gt;
&lt;p&gt;产品经理指着 Vercel v0 说：“你看人家，生成的 React 代码直接就跑起来了，还能点，还能交互。咱们能不能也搞一个？”&lt;/p&gt;
&lt;p&gt;灵魂发问：&lt;/p&gt;
&lt;p&gt;AI 返回的是字符串啊！浏览器只能跑 JS，怎么跑 JSX？而且 React 组件通常还要 import { Button } from ‘antd’，浏览器去哪找 node_modules？&lt;/p&gt;
&lt;h3 id=&quot;41-玩具版iframe--babel-standalone&quot;&gt;4.1 玩具版：Iframe + Babel Standalone&lt;/h3&gt;
&lt;p&gt;一开始，我试着在 Iframe 里硬塞了一个 &lt;code&gt;babel.min.js&lt;/code&gt;。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;原理&lt;/strong&gt;：利用 Babel 在浏览器端实时把 JSX 编译成 &lt;code&gt;React.createElement&lt;/code&gt;。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;结果&lt;/strong&gt;：简单的 &lt;code&gt;&amp;#x3C;div&gt;Hello&amp;#x3C;/div&gt;&lt;/code&gt; 能跑。但一旦 AI 写了 &lt;code&gt;import&lt;/code&gt;，控制台直接炸了：&lt;code&gt;Uncaught ReferenceError: require is not defined&lt;/code&gt;。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;我意识到，我缺的不是编译器，而是一个&lt;strong&gt;打包器 (Bundler)&lt;/strong&gt;。&lt;/p&gt;
&lt;h3 id=&quot;42-工业版拥抱-sandpack-web-worker-bundler&quot;&gt;4.2 工业版：拥抱 Sandpack (Web Worker Bundler)&lt;/h3&gt;
&lt;p&gt;深挖之后，我发现了 Vercel v0 背后的神级技术栈：&lt;strong&gt;Sandpack&lt;/strong&gt;（源自 CodeSandbox）。&lt;/p&gt;
&lt;p&gt;它的原理极其硬核：它在浏览器里起了一个 &lt;strong&gt;Web Worker&lt;/strong&gt;，在这个 Worker 里运行了一个微型的 Webpack。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;它是怎么工作的？&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;拦截 Import&lt;/strong&gt;：当代码里出现 &lt;code&gt;import { BarChart } from &apos;recharts&apos;&lt;/code&gt;。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;动态拉包&lt;/strong&gt;：Worker 拦截请求，去专门的 CDN (如 esm.sh) 拉取 &lt;code&gt;recharts&lt;/code&gt; 的元数据和代码。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;内存构建&lt;/strong&gt;：它在内存里建立虚拟文件系统，把这些包和 AI 生成的代码打包在一起。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;安全执行&lt;/strong&gt;：最后把打包好的 JS 丢给 Iframe 执行。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;我的集成代码&lt;/strong&gt;：&lt;/p&gt;
&lt;p&gt;JavaScript&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import { Sandpack } from &quot;@codesandbox/sandpack-react&quot;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;// AI 生成的代码流直接喂给 files&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&amp;#x3C;Sandpack &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  template=&quot;react&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  files={{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &quot;/App.js&quot;: aiGeneratedCode, // 👈 就算是流式传输的残缺代码，它也能容错&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  customSetup={{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    dependencies: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      &quot;recharts&quot;: &quot;latest&quot;, // 👈 预置好依赖，AI 随便调&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      &quot;lucide-react&quot;: &quot;latest&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;那一刻，屏幕上那个柱状图随着 AI 的打字机效果一点点画出来，还能跟随鼠标交互时，我感觉自己不再只是一个写页面的前端，而是在构建一个**“容器”**。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;总结从切图仔到容器架构师&quot;&gt;总结：从“切图仔”到“容器架构师”&lt;/h2&gt;
&lt;p&gt;回顾这几天的折腾，从一开始的懵懂无知到现在的豁然开朗，我发现 AI 时代的前端开发逻辑变了：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;以前&lt;/strong&gt;：我们追求&lt;strong&gt;静态的完美&lt;/strong&gt;（Pixel Perfect），所有的状态、文案、组件都是预设好的。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;现在&lt;/strong&gt;：我们追求&lt;strong&gt;动态的流畅&lt;/strong&gt;（Streaming Perfection）。我们要处理的不仅是数据流，还有视觉流、代码流。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;以前&lt;/strong&gt;：我们&lt;strong&gt;写代码&lt;/strong&gt;给浏览器跑，我们是代码的创造者。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;现在&lt;/strong&gt;：我们&lt;strong&gt;写环境&lt;/strong&gt;让 AI 的代码跑，我们成了代码的“监护人”和“架构师”。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这条路还在继续，但我已经不再迷茫了。下一个挑战：如何在浏览器里跑 Python 进行数据分析？&lt;strong&gt;WebAssembly&lt;/strong&gt;，我来了！&lt;/p&gt;</content:encoded><category>Javascript</category><category>AI</category><category>Nodejs</category></item><item><title>拒绝临时性-生活AI版</title><link>https://feichuans.com/blogs/05-archive/%E6%8B%92%E7%BB%9D%E4%B8%B4%E6%97%B6%E6%80%A7-%E7%94%9F%E6%B4%BBai%E7%89%88/</link><guid isPermaLink="true">https://feichuans.com/blogs/05-archive/%E6%8B%92%E7%BB%9D%E4%B8%B4%E6%97%B6%E6%80%A7-%E7%94%9F%E6%B4%BBai%E7%89%88/</guid><description>你说说你说说, AI 咋就这么会写呢 什么是「临时性生活」 人一旦习惯用“临时”来定义当下，就很容易在不知不觉中，把整个人生过成一段 无限期的过渡期 。 我们太熟悉这种话术了—— “等我熬过这段时间就好了。” “等条件再好一点再说。” “现在没必要讲究。” 刘震云说过一句话，大意是： 骗子最常用的伎俩，就是…</description><pubDate>Sun, 28 Dec 2025 05:46:45 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;你说说你说说, AI 咋就这么会写呢&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1 id=&quot;什么是临时性生活&quot;&gt;什么是「临时性生活」&lt;/h1&gt;
&lt;p&gt;人一旦习惯用“临时”来定义当下，就很容易在不知不觉中，把整个人生过成一段&lt;strong&gt;无限期的过渡期&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;我们太熟悉这种话术了——&lt;br&gt;
“等我熬过这段时间就好了。”&lt;br&gt;
“等条件再好一点再说。”&lt;br&gt;
“现在没必要讲究。”&lt;/p&gt;
&lt;p&gt;刘震云说过一句话，大意是：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;骗子最常用的伎俩，就是编造辉煌的过去，许诺精彩的未来，然后让你牺牲现在。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;后来我意识到，“临时生活”其实也是同一种结构。&lt;br&gt;
只是这一次，骗子不是别人，而是我们自己。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;所谓临时性生活，并不是生活真的短暂，而是一个人把现实当成过渡，把希望全部押在未来，从而不断合理化对当下的敷衍与忍耐。&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;临时生活最常见的样子&quot;&gt;临时生活最常见的样子&lt;/h2&gt;
&lt;p&gt;它通常发生在某段“正在路上”的时期：&lt;br&gt;
实习、备考、刚到一座新城市、刚换工作。&lt;/p&gt;
&lt;p&gt;你住在一个不太理想的房间里，也知道这只是暂时的。于是，面对每天的生活，你会在下面两种选择中，几乎下意识地走向其中一种。&lt;/p&gt;
&lt;h3 id=&quot;a典型的临时生活心态&quot;&gt;A：典型的「临时生活」心态&lt;/h3&gt;
&lt;p&gt;你心里很清楚地告诉自己：&lt;br&gt;
&lt;strong&gt;“这只是个睡觉的地方，反正很快就要走了。”&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;桌子乱了，你也懒得收拾。衣服随手丢在椅子上，只要还能坐就行。&lt;br&gt;
外卖到了，你直接在塑料盒里吃，甚至不拿出来，免得弄脏桌面。&lt;br&gt;
吃饭的时候刷着短视频，眼睛在看，脑子却是空的。你说这是放松，但心里始终悬着明天的事。&lt;/p&gt;
&lt;p&gt;你真正的潜台词是：&lt;br&gt;
&lt;strong&gt;“我真正的人生，还没开始。”&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;现在的一切，不过是用来熬过去的。&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;b拒绝临时感的心态&quot;&gt;B：拒绝「临时感」的心态&lt;/h3&gt;
&lt;p&gt;你同样知道这房子是租的，是过渡的。&lt;br&gt;
但你也清楚一件事：&lt;strong&gt;你正在这里度过的每一分钟，都不会重来。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;于是你花了十分钟，把桌面整理了一下。&lt;br&gt;
衣服挂好，空瓶子丢掉，铺上一块干净的桌布，或者打开一盏暖光的台灯。&lt;/p&gt;
&lt;p&gt;外卖到了，你把它倒进常用的碗里，给自己倒一杯水。&lt;br&gt;
哪怕只有你一个人，你也坐直了身体，认真吃完这一顿。&lt;/p&gt;
&lt;p&gt;吃饭的时候你不刷手机，放一首熟悉的歌，或者看一部一直想看的电影。&lt;br&gt;
饭后你会感觉到一种真实的“休息感”，而不是空虚后的疲惫。&lt;/p&gt;
&lt;p&gt;你心里想的是：&lt;br&gt;
&lt;strong&gt;“哪怕明天就要离开，今晚我也要把自己照顾好。”&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;我不把生活的尊严，寄托在未来。&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;临时性生活的本质&quot;&gt;临时性生活的本质&lt;/h2&gt;
&lt;p&gt;临时性生活，本质上是一种逃避。&lt;/p&gt;
&lt;p&gt;它让人沉迷于一个想象中的未来：&lt;br&gt;
等考完这场试、等工作稳定、等条件成熟，生活就会自动进入一个更好的阶段。&lt;/p&gt;
&lt;p&gt;但问题在于——&lt;br&gt;
&lt;strong&gt;生活并不会“突然开始”。&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;核心误区等待开始的幻觉&quot;&gt;核心误区：等待开始的幻觉&lt;/h2&gt;
&lt;p&gt;临时生活最致命的地方，在于它制造了一种错觉：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;只要我熬过这一段，生活自然会变好。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;可现实是，未来并不会奖励一个长期习惯敷衍的人。&lt;br&gt;
如果你现在习惯凑合、忍耐、将就，那么这种惯性，大概率会被你一并带进所谓的“好日子”。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;更隐蔽的危险披着努力外衣的逃避&quot;&gt;更隐蔽的危险：披着努力外衣的逃避&lt;/h2&gt;
&lt;p&gt;临时生活之所以危险，是因为它&lt;strong&gt;看起来很正当&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;表面上，你在忍耐、在奋斗、在为未来做准备。&lt;br&gt;
但实际上，你在一点点切断自己与当下生活的联系。&lt;/p&gt;
&lt;p&gt;你不愿意经营居住环境，因为“反正要走”。&lt;br&gt;
你不愿意投入关系，因为“迟早会分开”。&lt;br&gt;
生活被压缩成最低配版本，只剩下生存功能。&lt;/p&gt;
&lt;p&gt;你不是没有付出，而是把一切情感、秩序和尊严，都延迟到了未来。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;最昂贵的代价能力的退化&quot;&gt;最昂贵的代价：能力的退化&lt;/h2&gt;
&lt;p&gt;真正不可逆的损失，往往发生在你毫无察觉的时候。&lt;/p&gt;
&lt;p&gt;当你长期练习忍耐和敷衍，你会慢慢失去一些能力：&lt;br&gt;
感受快乐的能力，&lt;br&gt;
专注当下的能力，&lt;br&gt;
以及掌控生活的信心。&lt;/p&gt;
&lt;p&gt;等你终于走到那个期盼已久的“稳定阶段”，&lt;br&gt;
你可能已经不知道，怎样好好生活了。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;破局之道从将来再说到现在开始&quot;&gt;破局之道：从「将来再说」到「现在开始」&lt;/h2&gt;
&lt;p&gt;拒绝临时生活，并不是放弃奋斗，也不是假装一切都很完美。&lt;/p&gt;
&lt;p&gt;它只要求一件事：&lt;br&gt;
&lt;strong&gt;在不完美的条件下，依然认真对待正在发生的生活。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;不是等有空了再照顾身体，而是在忙碌中也不彻底透支自己。&lt;br&gt;
不是等稳定了再生活，而是在动荡中，依然保持基本的体面和秩序。&lt;/p&gt;
&lt;p&gt;未来不会凭空降临。&lt;br&gt;
它只是由无数个被认真对待的今天，一点点累积而成。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;每日自检&quot;&gt;每日自检&lt;/h2&gt;
&lt;p&gt;每天结束时，可以问自己三个简单的问题：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;我今天有没有心不在焉地活着？&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;我有没有为了所谓的“将来”，而敷衍了今天？&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;有哪些事情，其实今天就可以开始？&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这不是为了苛责自己。&lt;br&gt;
只是为了确认——&lt;br&gt;
&lt;strong&gt;今天，我有没有再把人生往后推一天。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;不必追求立刻改变。&lt;br&gt;
但每一次不再“临时”的选择，都会在你身上留下痕迹。&lt;/p&gt;</content:encoded><category>认知</category></item><item><title>拒绝临时性-生活</title><link>https://feichuans.com/blogs/05-archive/%E6%8B%92%E7%BB%9D%E4%B8%B4%E6%97%B6%E6%80%A7-%E7%94%9F%E6%B4%BB/</link><guid isPermaLink="true">https://feichuans.com/blogs/05-archive/%E6%8B%92%E7%BB%9D%E4%B8%B4%E6%97%B6%E6%80%A7-%E7%94%9F%E6%B4%BB/</guid><description>什么是临时性生活? 所谓“临时性生活”，并不是生活真的短暂，而是一个人用“将来会更好”作为借口，系统性地放弃对当下生活的经营与尊重。 人一旦习惯用 &quot;临时&quot;来定义当下, 就会在不知不觉中将整个人生过成一段无限期的 过渡期 全天下的骗子只有一个伎俩，那就是编造辉煌的历史，并许诺你精彩的未来，然后，要你牺牲你的…</description><pubDate>Sun, 28 Dec 2025 05:09:36 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://s2.loli.net/2025/12/28/ObAi8mZLwT9HoX2.png&quot; alt=&quot;image.png&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;什么是临时性生活&quot;&gt;什么是临时性生活?&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;所谓“临时性生活”，并不是生活真的短暂，而是一个人用“将来会更好”作为借口，系统性地放弃对当下生活的经营与尊重。&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;人一旦习惯用 “临时”来定义当下, 就会在不知不觉中将整个人生过成一段无限期的&lt;strong&gt;过渡期&lt;/strong&gt;
&lt;strong&gt;全天下的骗子只有一个伎俩，那就是编造辉煌的历史，并许诺你精彩的未来，然后，要你牺牲你的现在。我被这种伎俩骗的太久了，于是习惯的用“临时”来定义当下。很多事情本来可以立马开始的，但就是说不清道不明的，要等条件好一点再开始。&lt;/strong&gt; &lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot; id=&quot;user-content-fnref-1&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;
From &lt;a href=&quot;https://www.zhihu.com/question/431861103/answer/1987899018479683264&quot;&gt;Zhihu&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;临时性生活最常见的几种形态是:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;只要我度过这段时间, 生活就会一个崭新的阶段, 而我可以在新的阶段开始一个美好的生活&lt;/li&gt;
&lt;li&gt;你正在一段过渡期 (实习, 准备考研, 刚到新城市), 你租了一个并不算太好的小单间, 或者住在拥挤的宿舍中, 接下来的选择中你更倾向于选择 A/B？
&lt;ol&gt;
&lt;li&gt;A:典型的“临时生活”心态
&lt;ol&gt;
&lt;li&gt;你心里想：“这只是个睡觉的地方，反正过几个月我就搬走了/考上就解脱了，没必要折腾。”&lt;/li&gt;
&lt;li&gt;关于环境： 你把椅子上的衣服随手推到床上，腾出一个坐的地方。你不打算收拾桌子，觉得“反正还会乱，等我有空了/搬家了再好好布置”。&lt;/li&gt;
&lt;li&gt;关于晚餐： 你没有把外卖倒进碗里，而是直接打开塑料盖子，甚至都不把外卖拿出来，就在塑料袋里吃（怕漏油弄脏桌子）。&lt;/li&gt;
&lt;li&gt;关于时间： 你一边吃，一边机械地刷着短视频，或者看着并不感兴趣的剧。你告诉自己这是在“放松”，但其实心里很空虚，还在焦虑明天的计划。&lt;/li&gt;
&lt;li&gt;内心潜台词： “现在的日子就是为了熬过去的。等我以后有钱了/成功了，我要住在宽敞的房子里，每天做精致的饭菜，好好享受生活。”&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;B：拒绝“临时感”的心态
&lt;ol&gt;
&lt;li&gt;你心里想：“虽然这房子是租的/临时的，但我在这里度过的每一分钟，都是我生命的一部分。”&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;关于环境：&lt;/strong&gt; 你花 &lt;strong&gt;10分钟&lt;/strong&gt; 快速整理了一下桌面，扔掉空水瓶，把衣服挂起来。你可能还在桌上铺了一块便宜但干净的桌布，或者开了一盏暖色调的台灯。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;关于晚餐：&lt;/strong&gt; 你把外卖倒进自己喜欢的陶瓷碗里，倒了一杯水。即使是一个人的晚餐，你也坐直了身体，认真地去品尝食物的味道，而不是囫囵吞枣。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;关于时间：&lt;/strong&gt; 吃饭时你没有刷手机，而是放了一首喜欢的歌，或者看了一部一直想看的好电影。吃完饭，你感到一种真实的“休息感”和“回血感”。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;内心潜台词：&lt;/strong&gt; &lt;strong&gt;“哪怕明天就要搬走，今晚我也要让自己过得舒服、体面。我不把生活的尊严寄托在未来，我要在现在的限制里，过得尽量好。”&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;临时性生活就是, 幻想一个美好的未来, 并在一条名为未来的岔道上一路狂奔, 缺忽略了名为&lt;strong&gt;当下&lt;/strong&gt;的正道。&lt;/p&gt;
&lt;p&gt;当然也有很多别的词语、词汇来概括: 实事求是, 活在当下, 第一性原理。&lt;/p&gt;
&lt;h2 id=&quot;临时性生活的坏处&quot;&gt;临时性生活的坏处&lt;/h2&gt;
&lt;h3 id=&quot;核心误区--等待开始幻觉&quot;&gt;核心误区 : “等待开始”幻觉&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;心态: 只要我熬过这一段时间（考完这场, 找到新工作,）, 美好的生活就会自动降临&lt;/li&gt;
&lt;li&gt;现实: 生活不会因为你达到某个阶段就&lt;strong&gt;突然&lt;/strong&gt;变好, 如果我习惯了凑合和敷衍, 这种惯性会延续到我所谓的未来当中。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;隐蔽的危险-披着努力的外衣&quot;&gt;隐蔽的危险: 披着努力的外衣&lt;/h3&gt;
&lt;p&gt;过去我常常认为自己的努力的, 直到今天我才发现做的是无用功。&lt;/p&gt;
&lt;p&gt;这种心态最可怕的地方在于它 &lt;strong&gt;具有欺骗性&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;表面上：&lt;/strong&gt; 你看起来很努力，在为了未来忍耐、奋斗。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;实际上：&lt;/strong&gt; 你切断了与当下的联系。你不愿意经营生活环境（比如租房就不布置），不愿意建立深度关系（比如觉得迟早要分开）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;后果：&lt;/strong&gt; 生活只剩下吃饭、睡觉、打卡和熬时间，而不再让人感到被滋养。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;不可逆的代价能力的丧失&quot;&gt;不可逆的代价：能力的丧失&lt;/h3&gt;
&lt;p&gt;文章提出了一个非常痛点的警示：&lt;strong&gt;有些东西是无法在未来补回来的。&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;消耗品：&lt;/strong&gt; 健康、专注力、热情、好奇心。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;能力的退化：&lt;/strong&gt; 如果你长期练习“敷衍”和“忍耐”，你会逐渐丧失“感知快乐”和“掌控生活”的能力。当你终于等到了所谓的“好日子”，你可能已经失去了享受它的心境和能力。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;破局之道-把将来再说变成现在开始&quot;&gt;破局之道 ：把“将来再说”变成“现在开始”&lt;/h2&gt;
&lt;p&gt;文章给出的解决方案不是让你放弃奋斗，而是改变&lt;strong&gt;对待当下的态度&lt;/strong&gt;。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;承认现实：&lt;/strong&gt; 外部环境永远不会完美（永远有压力和风险）。成熟是学会在不完美中建立秩序。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;具体行动：&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;不是等有空了再健身，而是忙碌中也要照顾身体。&lt;/li&gt;
&lt;li&gt;不是等稳定了再生活，而是即使在动荡中，也要保持内心的体面和自尊。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;核心逻辑：&lt;/strong&gt; 未来的美好生活，是由无数个“被认真对待的今天”累积而成的，而不是某一天突然掉下来的奖赏。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;每日自检清单&quot;&gt;每日自检清单&lt;/h3&gt;
&lt;p&gt;每天结束时, 问自己三个问题（问 AI 告诉他你今天做了什么）:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;我今天有三心二意吗？心猿意马&lt;/li&gt;
&lt;li&gt;我今天有没有为了所谓的 “未来” 而敷衍/牺牲现在?&lt;/li&gt;
&lt;li&gt;有哪些我今天就可以做但没有做的事？&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;不必奢求短期的骤然改变, 而是坚持长期主义, 不必因为忘记一两次而烦恼, 但要为每次坚持的自己鼓掌。&lt;/p&gt;
&lt;section data-footnotes=&quot;&quot; class=&quot;footnotes&quot;&gt;&lt;h2 class=&quot;sr-only&quot; id=&quot;footnote-label&quot;&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li id=&quot;user-content-fn-1&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://www.sohu.com/a/895529729_122295860&quot;&gt;刘震云说：骗子再高明，其实用的都只有一个伎俩，那就是：编造辉煌的过去，并许诺你精彩的未来，然后，蛊惑你牺牲现在的所有_生活_虚幻_宜善&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-1&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content:encoded><category>认知</category></item><item><title>Tmux速记</title><link>https://feichuans.com/blogs/05-archive/tmux%E9%80%9F%E8%AE%B0/</link><guid isPermaLink="true">https://feichuans.com/blogs/05-archive/tmux%E9%80%9F%E8%AE%B0/</guid><description>提升命令行使用体验──tmux 终端复用 LUG @ USTC Tmux 使用教程 阮一峰的网络日志 App+1 \ AeroSpace：消除窗口重叠，世界属于平铺 少数派 [!note]+ Tmux 是什么? Tmux 是一个可以保存终端状态和记录的终端复用器 ( T erminal Mu ltiple…</description><pubDate>Sun, 21 Sep 2025 14:25:17 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://lug.ustc.edu.cn/planet/2025/07/how-to-use-tmux/&quot;&gt;提升命令行使用体验──tmux 终端复用 - LUG @ USTC&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.ruanyifeng.com/blog/2019/10/tmux.html&quot;&gt;Tmux 使用教程 - 阮一峰的网络日志&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://sspai.com/post/84935&quot;&gt;App+1 | AeroSpace：消除窗口重叠，世界属于平铺 - 少数派&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;markdown-alert markdown-alert-note&quot; dir=&quot;auto&quot;&gt;
&lt;p class=&quot;markdown-alert-title&quot; dir=&quot;auto&quot;&gt;&lt;svg class=&quot;octicon&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot; height=&quot;16&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.5 7.75A.75.75 0 0 1 7.25 7h1a.75.75 0 0 1 .75.75v2.75h.25a.75.75 0 0 1 0 1.5h-2a.75.75 0 0 1 0-1.5h.25v-2h-.25a.75.75 0 0 1-.75-.75ZM8 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;NOTE&lt;/p&gt;
&lt;p&gt;+ Tmux 是什么?
Tmux 是一个可以保存终端状态和记录的终端复用器 (&lt;strong&gt;T&lt;/strong&gt;erminal &lt;strong&gt;Mu&lt;/strong&gt;ltiple&lt;strong&gt;X&lt;/strong&gt;er). 可以保存一个终端并在以后重新连接并且显示之前的输出. 并且可以在同一个终端内创建多个窗口 (分屏) ,每个窗口都运行独立的 Shell 进程.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Tmux 的原理: 将终端(Terminal)和会话(Sesstion)进行了分离, 用户可以随时退出(detach)当前会话, 会话会在后台保持运行, 之后用户可以通过 (attach) 重新连接上会话.&lt;/p&gt;
&lt;h1 id=&quot;常用命令&quot;&gt;常用命令&lt;/h1&gt;
&lt;p&gt;Tmux 有两种操作方式, 一种是通过键盘触发键 &lt;code&gt;ctrl+b&lt;/code&gt; 一种是直接在终端输入 &lt;code&gt;tmux&lt;/code&gt; 命令.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;新建会话: &lt;code&gt;tmux new -s &amp;#x3C;sesstion-name&gt;&lt;/code&gt; 默认窗口编号是 0, 之后是 1 以此类推&lt;/li&gt;
&lt;li&gt;分离会话: &lt;code&gt;tmux detach&lt;/code&gt; 将当前会话和终端窗口分离 &lt;code&gt;ctrl + b d&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;显示会话列表: &lt;code&gt;tmux ls or tmux list-session&lt;/code&gt; &lt;code&gt;ctrl + b s&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;接入会话: &lt;code&gt;tmux attach -t &amp;#x3C;session-name&gt; or &amp;#x3C;number&gt;&lt;/code&gt; 输入名称或编号&lt;/li&gt;
&lt;li&gt;杀死会话: &lt;code&gt;tmux kill-session&lt;/code&gt; 参数和上面相同&lt;/li&gt;
&lt;li&gt;切换会话: &lt;code&gt;tmux switch&lt;/code&gt; 相同&lt;/li&gt;
&lt;li&gt;重命名会话: &lt;code&gt;tmux-rename-session -t 0 &amp;#x3C;new-name&gt;&lt;/code&gt; &lt;code&gt;ctrl+b $&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;窗格操作&quot;&gt;窗格操作&lt;/h2&gt;
&lt;p&gt;Tmux 可以将一个终端窗口(Window)分成多个窗格 (Pane), 每个窗格运行着不同的 &lt;code&gt;Session&lt;/code&gt; 实例.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;划分窗格: &lt;code&gt;tmux split-window &amp;#x3C;option&gt;&lt;/code&gt; 将窗口划分为上下两个窗格若带上 &lt;code&gt;-h&lt;/code&gt; 则划分为左右两个 &lt;code&gt;ctrl+b % 左右划分&lt;/code&gt;, &lt;code&gt;ctrl+b &quot; 上下划分&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;修改聚焦的窗格 (移动光标所在窗格): &lt;code&gt;tmux select-pane -LRDU&lt;/code&gt; 将光标移动到 &lt;code&gt;左右下上&lt;/code&gt; 窗格 (基于当前位置)&lt;/li&gt;
&lt;li&gt;交换窗格位置: &lt;code&gt;tmux swap-pane -LRDU&lt;/code&gt; 将当前窗格移动到 &lt;code&gt;左右上下&lt;/code&gt; 窗格
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Ctrl+b &amp;#x3C;arrow key&gt;&lt;/code&gt; 光标切换到其他窗格&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Ctrl+b ;&lt;/code&gt;：光标切换到上一个窗格。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Ctrl+b o&lt;/code&gt;：光标切换到下一个窗格。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Ctrl+b {&lt;/code&gt;：当前窗格与上一个窗格交换位置。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Ctrl+b }&lt;/code&gt;：当前窗格与下一个窗格交换位置。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Ctrl+b Ctrl+o&lt;/code&gt;：所有窗格向前移动一个位置，第一个窗格变成最后一个窗格。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Ctrl+b Alt+o&lt;/code&gt;：所有窗格向后移动一个位置，最后一个窗格变成第一个窗格。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Ctrl+b x&lt;/code&gt;：关闭当前窗格。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Ctrl+b !&lt;/code&gt;：将当前窗格拆分为一个独立窗口。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Ctrl+b z&lt;/code&gt;：当前窗格全屏显示，再使用一次会变回原来大小。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Ctrl+b Ctrl+&amp;#x3C;arrow key&gt;&lt;/code&gt;：按箭头方向调整窗格大小。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Ctrl+b q&lt;/code&gt;：显示窗格编号。&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>Linux</category></item><item><title>面试题</title><link>https://feichuans.com/blogs/03-areas/%E8%81%8C%E4%B8%9A%E7%94%9F%E6%B6%AF/%E9%9D%A2%E8%AF%95%E9%A2%98/</link><guid isPermaLink="true">https://feichuans.com/blogs/03-areas/%E8%81%8C%E4%B8%9A%E7%94%9F%E6%B6%AF/%E9%9D%A2%E8%AF%95%E9%A2%98/</guid><description>1.具体在做小程序的什么？（我在实习中提到【公告通知】这个功能） 2.微信订阅消息推送的链路，用户怎么收到推送的？想了解用到什么协议 3.get 和 post 怎么理解？ 4.get 和 post 在网络传输链路上有什么区别？ 5.小程序上也有 url 的长度限制吗？（上个问题我说到了 get 的 url…</description><pubDate>Tue, 16 Sep 2025 07:41:21 GMT</pubDate><content:encoded>&lt;p&gt;1.具体在做小程序的什么？（我在实习中提到【公告通知】这个功能）&lt;br&gt;
2.微信订阅消息推送的链路，用户怎么收到推送的？想了解用到什么协议&lt;br&gt;
3.get 和 post 怎么理解？&lt;br&gt;
4.get 和 post 在网络传输链路上有什么区别？&lt;br&gt;
5.小程序上也有 url 的长度限制吗？（上个问题我说到了 get 的 url 长度限制）这个限制是谁做的？&lt;br&gt;
6.简单请求和飞简单请求？&lt;br&gt;
7.自定义请求头是指什么？（上个问题我提到复杂请求可能是包含自定义请求头）&lt;br&gt;
8.get 幂等，post 非幂等，主要什么原因导致的这种区别？&lt;br&gt;
9.URI 是指？（我提到 uri，面试官说没有太理解到 uri 的概念）所有请求都一定是返回 uri 吗？&lt;br&gt;
10.get 请求的默认缓存能力？&lt;br&gt;
11.浏览器缓存有磁盘缓存和内存缓存，这个了解吗？浏览器怎么控制这两个缓存空间？两个的主要作用？&lt;br&gt;
12.强缓存和协商缓存什么时候走内存/磁盘缓存？&lt;br&gt;
13.settimeout 时间不准确的问题？&lt;br&gt;
14.setTimeout  与浏览器渲染帧率的关系？&lt;br&gt;
15.requestAnimationFrame 怎么解决 settimeout 时间不准确的问题？&lt;br&gt;
16.async/await 和 promise 怎么解决回掉地狱？两者有什么区别？&lt;br&gt;
17.两个数组相加在浏览器中执行结果：[1, 2, 3] + [4, 5, 6]？&lt;br&gt;
18.解构赋值通过什么触发的？解构赋值是什么?（这个问题是因为我上个问题做错了，我以为两个数组相加就直接是对应索引值相加，解释时提到【解构赋值】，所以面试官才问的）&lt;br&gt;
19.用 var 实现 const，写伪代码即可&lt;br&gt;
20.实现 promise.all&lt;/p&gt;
&lt;p&gt;作者：拜托 offer 吻上来&lt;br&gt;
链接：&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/82f6c6b453994a2fa6ed9827d316f936?sourceSSR=search&quot;&gt;https://www.nowcoder.com/feed/main/detail/82f6c6b453994a2fa6ed9827d316f936?sourceSSR=search&lt;/a&gt;&lt;br&gt;
来源：牛客网&lt;/p&gt;
&lt;h1 id=&quot;小鹏前端一面&quot;&gt;小鹏前端一面&lt;/h1&gt;
&lt;p&gt;1.浏览器渲染？&lt;br&gt;
2.reflow，repaint&lt;br&gt;
3.CSS  选择器优先级如何计算？&lt;br&gt;
4.什么是  BFC？如何触发？&lt;br&gt;
5.什么是  DOCTYPE？&lt;br&gt;
6.盒模型有哪两种？区别是什么？&lt;br&gt;
7.原型和原型链？&lt;br&gt;
8.js 事件传播机制&lt;br&gt;
9.防抖和节流的区别？各用在什么场景？&lt;br&gt;
10.Promise ？如何链式调用？&lt;br&gt;
11.async/await  的本质？&lt;br&gt;
12.常见的  HTTP  状态码有哪些？&lt;br&gt;
13.GET  和  POST ？&lt;br&gt;
14.浏览器缓存有哪几种？如何设置？&lt;br&gt;
15.Vue  双向绑定的原理是什么？&lt;br&gt;
16.Vue  组件通信有哪些方式？&lt;br&gt;
17.虚拟 DOM 和真实 DOM？&lt;br&gt;
18.Vue  路由的模式及区别？&lt;br&gt;
19.前端性能优化从哪些方面入手？&lt;br&gt;
20.模块化规范有哪些？CommonJS  和  ES6 Module  区别？&lt;br&gt;
21.TypeScript  相比  JS  的优势？&lt;br&gt;
22.interface 和 type&lt;br&gt;
23.如何检测前端内存泄漏？&lt;br&gt;
24.如何调试前端代码？有哪些工具？&lt;br&gt;
还有些项目内容&lt;a href=&quot;/creation/subject/1bd9e77417b74119a9564658998d2edd&quot;&gt;#我的秋招日记#&lt;/a&gt;&lt;a href=&quot;/creation/subject/c00859d1b35c4e7bae80843e5958bd70&quot;&gt;#听到哪句话代表面试稳&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;作者：SssRi&lt;br&gt;
链接：&lt;a href=&quot;https://www.nowcoder.com/?&quot;&gt;https://www.nowcoder.com/?&lt;/a&gt;&lt;br&gt;
来源：牛客网&lt;/p&gt;
&lt;h1 id=&quot;影石前端一面已过&quot;&gt;影石前端一面(已过)&lt;/h1&gt;
&lt;p&gt;八股&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;html 渲染，遇到 script 标签会怎样&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;async 和 defer 有啥区别，怎么执行的&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;http 缓存(强缓存，协商缓存)&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;4.跨域&lt;/p&gt;
&lt;p&gt;5.跨域的表现是什么样的，发出去无响应/压根没发?&lt;/p&gt;
&lt;p&gt;6.请求发出去以后，根据啥判断是否跨域?&lt;/p&gt;
&lt;ol start=&quot;7&quot;&gt;
&lt;li&gt;option 请求&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;8.介绍一些 es6 和更新的 API&lt;/p&gt;
&lt;p&gt;9.箭头函数和 function 区别&lt;/p&gt;
&lt;ol start=&quot;10&quot;&gt;
&lt;li&gt;事件循环&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;11.怎么利用事件循环机制，优化大量计算导致的页面卡顿问题&lt;/p&gt;
&lt;p&gt;12.了解 requestAnimationFrame 吗，他在事件循环中的位置是啥&lt;/p&gt;
&lt;p&gt;13.怎么理解 react 中的 hooks，为啥不用类组件，好在哪&lt;/p&gt;
&lt;p&gt;14.自己有封装自定义的 hook 吗?为啥不用普通的方法函数&lt;/p&gt;
&lt;p&gt;15.有了解 ahooks 库里的 useAsync 吗，啥原理&lt;/p&gt;
&lt;ol start=&quot;16&quot;&gt;
&lt;li&gt;
&lt;p&gt;AI 的数据流式返回是啥原理?(实习相关)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Zustand 和 Redux 是啥区别&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;setState 为啥不能立刻拿到更新后的值&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;场景&lt;/p&gt;
&lt;p&gt;1.浏览器输入 url 之后，白屏时间过长，哪些环节可以优化&lt;/p&gt;
&lt;p&gt;2.可以用缓存优化吗&lt;/p&gt;
&lt;p&gt;3.如果分页的时候快速连续点了第二页和第三页，结果第二页的请求比第三页的返回更慢，出现问题，因为其实想看第三页。怎么解决这个问题&lt;/p&gt;
&lt;p&gt;作者：Offer 心愿达成中 ​&lt;br&gt;
链接：&lt;a href=&quot;https://www.nowcoder.com/?&quot;&gt;https://www.nowcoder.com/?&lt;/a&gt;&lt;br&gt;
来源：牛客网&lt;/p&gt;
&lt;h1 id=&quot;字节前端一面75-分钟&quot;&gt;字节前端一面（75 分钟）&lt;/h1&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;自我介绍&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;介绍一下项目及基础架构&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;项目拷打（大约 20 分钟、围绕简历提问）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;性能优化怎么做的（大约 20 分钟）&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;性能优化会从性能指标到阶段分析到优化细问&lt;/p&gt;
&lt;ol start=&quot;5&quot;&gt;
&lt;li&gt;
&lt;p&gt;JSBridge 和客户端底层怎么进行通信的&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Ts 的 keyof、tyoeof、泛型、装饰器；ts 在前端工程化有什么作用呢&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;JS 基础数据类型、通过哪些方法可以判断一个变量是数组类型？（问了 5 种方法）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;做移动端的时候怎么保证视觉的还原度&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;如果视觉走查的某个视觉问题反复调整都无法完美还原怎么解决&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;AI 视觉稿转代码详细说说&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;为什么移动端上图片会展示模糊呢？&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;DRP 对图片渲染模糊有什么关联&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;移动端的动画选型和动画类型&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;有没有自己使用过 canvas 做一些绘制或动画渲染呢？&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;js 驱动的动画遇到卡顿怎么优化和处理呢&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;重绘重排在渲染层为什么会有不同的性能影响&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;React 的常用 hooks；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;React 对比直接使用 js 有什么提升？&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;React18 之前的版本对比 React18 有什么不同&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;服务端渲染 ssr、rsc 与 csr 的对比；水合失败会怎样&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;http 0.9, http 1.0 ,http 1.1， http2，http3 的区别，队头阻塞在各个阶段的问题和解决方案&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;TCP vs UDP，介绍一下 TCP 的慢启动，强缓存+协商缓存&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;csrf xss&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;加密方式了解哪些，介绍一下对称加密，非对称加密&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;日常怎么使用 AI 的，在工作中有哪些提效&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;两道题&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;26.1. 手写数组的 flat 方法&lt;/p&gt;
&lt;p&gt;26.2. 手写一个 PromiseAll，写完后顺便问了 Promise 的其他方法&lt;/p&gt;
&lt;p&gt;整个过程都通过聊天去问一些问题，面试体验很棒，回答的还不错，百分之 95 都回答上来了，手写题也是秒了，结果还是挂了&lt;/p&gt;
&lt;p&gt;作者：关关过的奋斗青春 ​&lt;br&gt;
链接：&lt;a href=&quot;https://www.nowcoder.com/?type=818_1&quot;&gt;https://www.nowcoder.com/?type=818_1&lt;/a&gt;&lt;br&gt;
来源：牛客网&lt;/p&gt;
&lt;h3 id=&quot;fiber&quot;&gt;Fiber&lt;/h3&gt;
&lt;p&gt;React 16 以前是同步任务, 不可中断, 导致更新容易卡死。&lt;/p&gt;
&lt;p&gt;Fiber 架构是将一个庞大的更新任务, 拆分成 &lt;strong&gt;可中断, 异步, 可恢复&lt;/strong&gt;的微小工作单元 (Fiber)&lt;/p&gt;
&lt;p&gt;每完成一个单元就将控制权交还给浏览器, 检查是否有更高优先级的任务 (用户输入, 滚动, 其他地方的动画)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;为了实现 &lt;code&gt;可中断&lt;/code&gt;, React 将工作流拆分成了两个阶段&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;渲染/调和阶段
&lt;ol&gt;
&lt;li&gt;可中断的异步 working in process tree&lt;/li&gt;
&lt;li&gt;计算出所有节点的变更&lt;/li&gt;
&lt;li&gt;可以暂停, 重做, 丢弃, 没有影响用户的副作用&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;提交阶段 (Commit Phase)
&lt;ol&gt;
&lt;li&gt;不可中断的同步阶段&lt;/li&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;2026-07-15-1121--firecrawl-牛客前端-agent-同步&quot;&gt;2026-07-15 11:21 | Firecrawl 牛客前端 Agent 同步&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;本次检索词：&lt;code&gt;site:nowcoder.com &quot;前端&quot; &quot;Agent&quot; &quot;面经&quot;&lt;/code&gt;；&lt;code&gt;site:nowcoder.com &quot;前端&quot; &quot;Agent&quot; &quot;简历&quot;&lt;/code&gt;；&lt;code&gt;site:nowcoder.com &quot;AI Agent&quot; &quot;前端&quot; &quot;面试&quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;新增面经：5 条；新增简历/岗位材料：3 条。&lt;/li&gt;
&lt;li&gt;数据来源：&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/0eb3f9b46a4843c086f6d575d20b15b4%EF%BC%9Bhttps://www.nowcoder.com/feed/main/detail/0ee219e39f254208bef730ca1e928fcc%EF%BC%9Bhttps://www.nowcoder.com/feed/main/detail/350d8666f74a4d5cb35c4f6abd07dfda%EF%BC%9Bhttps://www.nowcoder.com/feed/main/detail/4e8cafa5d36c43f9b1c3a4e0c0e5cbc8%EF%BC%9Bhttps://www.nowcoder.com/feed/main/detail/96cc5b7e2cb84f148eb48be23952f647%EF%BC%9Bhttps://www.nowcoder.com/discuss/879078076276105216%EF%BC%9Bhttps://www.nowcoder.com/feed/main/detail/21ecd02d94d2403f94d508bb8a209eba%EF%BC%9Bhttps://www.nowcoder.com/feed/main/detail/5ac85cc8e30142689e7d0bd6294ded05&quot;&gt;https://www.nowcoder.com/feed/main/detail/0eb3f9b46a4843c086f6d575d20b15b4；https://www.nowcoder.com/feed/main/detail/0ee219e39f254208bef730ca1e928fcc；https://www.nowcoder.com/feed/main/detail/350d8666f74a4d5cb35c4f6abd07dfda；https://www.nowcoder.com/feed/main/detail/4e8cafa5d36c43f9b1c3a4e0c0e5cbc8；https://www.nowcoder.com/feed/main/detail/96cc5b7e2cb84f148eb48be23952f647；https://www.nowcoder.com/discuss/879078076276105216；https://www.nowcoder.com/feed/main/detail/21ecd02d94d2403f94d508bb8a209eba；https://www.nowcoder.com/feed/main/detail/5ac85cc8e30142689e7d0bd6294ded05&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;面经&quot;&gt;面经&lt;/h3&gt;
&lt;h4 id=&quot;快手-ai-agent-前端二面&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/0eb3f9b46a4843c086f6d575d20b15b4&quot;&gt;快手 AI Agent 前端二面&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;原帖问题与答案：原帖列出 9 个问题，均未提供答案。
&lt;ol&gt;
&lt;li&gt;React Fiber 架构解决了什么问题，工作原理是什么？&lt;/li&gt;
&lt;li&gt;开发 Agent 产品时，如何实现流畅的打字机输出？&lt;/li&gt;
&lt;li&gt;如何处理 Agent 长文本中的 Markdown 和 LaTeX 公式渲染？&lt;/li&gt;
&lt;li&gt;项目如何做前端性能优化，有哪些量化指标？&lt;/li&gt;
&lt;li&gt;Webpack 构建流程是什么，做过哪些打包优化？&lt;/li&gt;
&lt;li&gt;为什么需要微前端，常用方案有哪些？&lt;/li&gt;
&lt;li&gt;Agent 复杂状态应用选择什么状态管理方案，为什么？&lt;/li&gt;
&lt;li&gt;是否了解小程序、KwaiNative 等跨端方案？&lt;/li&gt;
&lt;li&gt;前端如何捕获异常，如何监控白屏？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可复习问题：
&lt;ol&gt;
&lt;li&gt;Agent 流式打字机、Markdown/LaTeX 渲染和复杂状态管理如何设计？&lt;/li&gt;
&lt;li&gt;前端性能、构建、跨端与异常监控如何落到量化指标？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;百度-ai-agent-前端研发实习生面经&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/0ee219e39f254208bef730ca1e928fcc&quot;&gt;百度 AI Agent 前端研发实习生面经&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;原帖问题与答案：原帖列出 40 个技术问题，均未提供答案。
&lt;ol&gt;
&lt;li&gt;AI 辅助开发的完整工作流和真实使用场景是什么？&lt;/li&gt;
&lt;li&gt;如何固化 AI 工作流的 case、方案和收益？&lt;/li&gt;
&lt;li&gt;如何把能力封装为 Skill，如何定义触发条件和意图识别中的人工干预？&lt;/li&gt;
&lt;li&gt;多 Skill 串行或嵌套时，如何处理依赖冲突、参数不兼容和编排优先级？&lt;/li&gt;
&lt;li&gt;AI 工作流上线后如何做全链路监控、异常告警和幻觉兜底？&lt;/li&gt;
&lt;li&gt;Agent 为什么选 LangChain，而不是直接调用 OpenAI 接口？&lt;/li&gt;
&lt;li&gt;文案解析到自动剪辑是否独立开发，有哪些优化点，Skill 如何定义和拆步？&lt;/li&gt;
&lt;li&gt;为什么引入有限状态机，6 个核心状态和流转规则如何用 transitions 实现？&lt;/li&gt;
&lt;li&gt;如何保证状态幂等并防止任务重复执行？&lt;/li&gt;
&lt;li&gt;任务成功率 99.5% 如何统计，每条任务是否标记状态？&lt;/li&gt;
&lt;li&gt;调度、工具编排和异步流程是否独立完成？&lt;/li&gt;
&lt;li&gt;使用什么大模型，如何控制调用成本？&lt;/li&gt;
&lt;li&gt;如何排查和熔断状态机卡死、悬停与死循环？&lt;/li&gt;
&lt;li&gt;FFmpeg 导致 CPU 或内存突增时，Agent 如何动态限流、分片和降级？&lt;/li&gt;
&lt;li&gt;切换国产大模型时，提示词和工具调用逻辑要改什么？&lt;/li&gt;
&lt;li&gt;海量积压时，RabbitMQ 死信队列和延迟队列如何保障稳定消费？&lt;/li&gt;
&lt;li&gt;旧埋点为什么需要深层组件嵌套传参？&lt;/li&gt;
&lt;li&gt;为什么用 Context 优化埋点，作用域是全局还是组件级？&lt;/li&gt;
&lt;li&gt;优化前后组件嵌套结构有什么变化？&lt;/li&gt;
&lt;li&gt;新旧埋点并行改造时，如何保证旧代码和线上运行稳定？&lt;/li&gt;
&lt;li&gt;Context 频繁更新引发重渲染时，memo、useMemo、useCallback 如何落地？&lt;/li&gt;
&lt;li&gt;大规模存量页面如何灰度上线新埋点，AB 分流和数据校验怎么做？&lt;/li&gt;
&lt;li&gt;AI 对话为什么优先 SSE 而不是轮询？&lt;/li&gt;
&lt;li&gt;SSE 与 WebSocket 有什么区别，能否独立实现聊天通信逻辑？&lt;/li&gt;
&lt;li&gt;SSE 返回什么数据结构？&lt;/li&gt;
&lt;li&gt;如何实现断线自动重连、指数退避和断点续传，避免丢文本？&lt;/li&gt;
&lt;li&gt;打字机逐字输出如何实现，渲染间隔设多少？&lt;/li&gt;
&lt;li&gt;超长文本打字机卡顿如何用分片和异步队列优化？&lt;/li&gt;
&lt;li&gt;音频可视化效果和处理后的数据格式是什么？&lt;/li&gt;
&lt;li&gt;基于 FFT 的完整开发思路和技术选型依据是什么？&lt;/li&gt;
&lt;li&gt;频谱柱状高度如何适配不同屏幕？&lt;/li&gt;
&lt;li&gt;移动端后台锁屏导致音频采集中断时，如何捕获并重启 WebAudio 上下文？&lt;/li&gt;
&lt;li&gt;FCP、LCP 通过什么方式采集？&lt;/li&gt;
&lt;li&gt;首屏性能优化前后如何对比，为什么主动做性能埋点？&lt;/li&gt;
&lt;li&gt;页面滚动优化是自研还是第三方库？&lt;/li&gt;
&lt;li&gt;LCP 被大体积音频阻塞时，预加载和分片加载如何落地？&lt;/li&gt;
&lt;li&gt;Agent 和普通 Chatbot 有什么区别？&lt;/li&gt;
&lt;li&gt;Agent 的核心组成模块有哪些？&lt;/li&gt;
&lt;li&gt;RAG + Agent 中如何用重排和过滤改善检索幻觉、无关文档召回？&lt;/li&gt;
&lt;li&gt;Multi-Agent 如何设计分工和冲突协商机制？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可复习问题：
&lt;ol&gt;
&lt;li&gt;Skill 编排、状态机、幂等、熔断、成本和可观测如何组成可运行的 Agent 工作流？&lt;/li&gt;
&lt;li&gt;SSE 重连、断点续传、打字机性能和 WebAudio 可视化如何实现？&lt;/li&gt;
&lt;li&gt;RAG 检索质量与 Multi-Agent 协作如何落地？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;百度-ai-agent-前端二面&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/350d8666f74a4d5cb35c4f6abd07dfda&quot;&gt;百度 AI Agent 前端二面&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;原帖问题与答案：正文明确提到 3 个问题，均未提供答案；配图中的其他问题无法从 Scrape 正文证明。
&lt;ol&gt;
&lt;li&gt;如何实现带超时时间和超时次数的 Promise 重试？&lt;/li&gt;
&lt;li&gt;Zustand 为什么轻量化？&lt;/li&gt;
&lt;li&gt;如何结合工作流进行开发？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可复习问题：
&lt;ol&gt;
&lt;li&gt;Promise 重试如何同时控制单次超时和总重试次数？&lt;/li&gt;
&lt;li&gt;Zustand 的轻量化体现在哪里？&lt;/li&gt;
&lt;li&gt;Agent Workflow 如何映射到实际开发流程？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;商汤科技-ai-agent-开发面经&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/4e8cafa5d36c43f9b1c3a4e0c0e5cbc8&quot;&gt;商汤科技 AI Agent 开发面经&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;原帖问题与答案：原帖列出 4 个问题，均未提供答案。
&lt;ol&gt;
&lt;li&gt;设计类似 LangFlow 的 AI Agent 工作流编排画布时，选择什么技术栈，核心难点是什么？&lt;/li&gt;
&lt;li&gt;RAG 系统中，前端如何优化长文档展示和引用来源跳转？&lt;/li&gt;
&lt;li&gt;AI 时代前端工程师的角色发生了什么变化？&lt;/li&gt;
&lt;li&gt;如何在 AI 快速迭代时兼顾团队技术栈的稳定性与前瞻性？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可复习问题：
&lt;ol&gt;
&lt;li&gt;Agent 可视化编排画布的节点模型、连线、状态同步与性能难点是什么？&lt;/li&gt;
&lt;li&gt;RAG 长文档和引用跳转的交互如何设计？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;百度-agent-前端一面&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/96cc5b7e2cb84f148eb48be23952f647&quot;&gt;百度 Agent 前端一面&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;原帖问题与答案：
&lt;ol&gt;
&lt;li&gt;日常开发如何使用 AI？原帖回答涉及让 AI 编写覆盖正常和边界情况的测试脚本。&lt;/li&gt;
&lt;li&gt;已有测试 Skill 时如何使用，如何确保执行？原帖回答涉及渐进式加载 Skill，以及用固定 Workflow 承载主流程、由 Agent 或 LLM 执行节点任务；面试官补充可把 Workflow 写入 system prompt。&lt;/li&gt;
&lt;li&gt;项目打字机效果如何实现，帧率如何计算？原帖未提供答案。&lt;/li&gt;
&lt;li&gt;Markdown 渲染如何防 XSS？原帖只提到 GFM 白名单，未展开。&lt;/li&gt;
&lt;li&gt;什么是 CSRF 攻击？原帖未提供答案。&lt;/li&gt;
&lt;li&gt;为什么 AI 输出用 SSE 而不是 WebSocket？原帖未提供答案。&lt;/li&gt;
&lt;li&gt;AI 生成歌曲耗时较长时，如何改善等待体验？原帖未提供答案。&lt;/li&gt;
&lt;li&gt;等待进度条当前 task 如何实现？原帖提到 SSE 自定义事件，未展开。&lt;/li&gt;
&lt;li&gt;为什么播放器使用全局状态管理？原帖未提供答案。&lt;/li&gt;
&lt;li&gt;如何根据音乐做音波震动效果？原帖回答可用现成库，或定期分析音乐特征生成主波频并用噪声模拟小波频；面试官补充音乐文件可解析为包含特征信息的数组。&lt;/li&gt;
&lt;li&gt;为什么项目使用 Next.js？原帖提到高交互区域不适合使用 SSR。&lt;/li&gt;
&lt;li&gt;知道哪些性能指��，如何监测？原帖未提供答案。&lt;/li&gt;
&lt;li&gt;简历中的性能优化具体怎么做？原帖未给出细节。&lt;/li&gt;
&lt;li&gt;AI 是否会取代前端？原帖未提供答案。&lt;/li&gt;
&lt;li&gt;了解哪些动画库或 UI 库？原帖未提供答案。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可复习问题：
&lt;ol&gt;
&lt;li&gt;如何用 Skill + Workflow 固化 AI 测试流程并保证节点执行？&lt;/li&gt;
&lt;li&gt;SSE 自定义事件如何驱动任务进度和流式文本？&lt;/li&gt;
&lt;li&gt;Markdown 安全、音频可视化、SSR 边界和性能指标如何回答？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;简历岗位材料&quot;&gt;简历/岗位材料&lt;/h3&gt;
&lt;h4 id=&quot;2026-年ai-全栈时代到了前端简历别再只写前端技术了&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/discuss/879078076276105216&quot;&gt;2026 年，AI 全栈时代到了，前端简历别再只写前端技术了&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;信号：
&lt;ol&gt;
&lt;li&gt;原帖认为仅写调模型、工具调用和聊天界面缺少区分度，项目应体现 Agent Runtime、显式状态机、评测回归、可观测、安全、成本和人工干预。&lt;/li&gt;
&lt;li&gt;前端优势应落在过程可视化、步骤和工具状态、审批、中断重试、异常恢复，以及 token 和成本展示。&lt;/li&gt;
&lt;li&gt;简历中的性能数字需要说明统计口径和复现方式，项目描述需要包含场景、难点、个人职责和可验证结果。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可追问方向：Agent Loop 如何显式建模；步数、超时、预算和取消如何由 Runtime 控制；高风险工具调用如何审批；trace、评测集和发布闸门如何闭环；token、step、progress 事件如何统一建模。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;通过-jd-看-ai-时代前端开发者需要具备的技能&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/21ecd02d94d2403f94d508bb8a209eba&quot;&gt;通过 JD 看 AI 时代前端开发者需要具备的技能&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;信号：
&lt;ol&gt;
&lt;li&gt;原帖归纳的前端 Agent 岗位能力包括 React/Vue/TypeScript、状态管理、可视化编辑器、SSE/WebSocket，以及 Agent 多轮对话和工作流界面。&lt;/li&gt;
&lt;li&gt;AI IDE 方向涉及 Monaco Editor、WebAssembly、代码生成与理解、知识问答、插件生态和工具链。&lt;/li&gt;
&lt;li&gt;多模态方向涉及 Canvas/WebGL/WebGPU、WebRTC、内容预览编辑、FPS 和内存优化；AI 工程化还涉及模型接入、Token、缓存、延迟、数据脱敏和内容审核。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可追问方向：Agent 编排画布如何建模；SSE/WebSocket 如何选型；Monaco 与 AI 代码生成如何集成；多模态预览的性能如何衡量；模型输出如何做安全合规。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;前端转-agent-是如何拿到三个大厂-offer-的&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/5ac85cc8e30142689e7d0bd6294ded05&quot;&gt;前端转 Agent 是如何拿到三个大厂 offer 的&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;信号：
&lt;ol&gt;
&lt;li&gt;原帖将前端转 Agent 的真实技术点归纳为上下文管理、工具调用、任务轨迹、Memory/State、成本和延迟控制，而不是只写 Prompt + API Demo。&lt;/li&gt;
&lt;li&gt;前端的状态管理、模块化、API 设计和工程结构可以迁移到 Agent Loop、Tool、Observation 和 Context Engineering。&lt;/li&gt;
&lt;li&gt;项目描述应给出 latency、token cost、success rate 等量化指标，说明方案取舍，并强调解决具体问题和落地。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可追问方向：Agent 轨迹如何记录和回放；Tool 与 Observation 如何设计；上下文和状态如何管理；延迟、token 成本和成功率如何定义统计口径。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;2026-07-15-1204--firecrawl-牛客前端-agent-同步&quot;&gt;2026-07-15 12:04 | Firecrawl 牛客前端 Agent 同步&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;本次检索词：&lt;code&gt;site:nowcoder.com &quot;前端&quot; &quot;Agent&quot; &quot;面经&quot;&lt;/code&gt;；&lt;code&gt;site:nowcoder.com &quot;前端&quot; &quot;Agent&quot; &quot;简历&quot;&lt;/code&gt;；&lt;code&gt;site:nowcoder.com &quot;AI Agent&quot; &quot;前端&quot; &quot;面试&quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;新增面经：5 条；新增简历/岗位材料：5 条。&lt;/li&gt;
&lt;li&gt;数据来源：&lt;a href=&quot;https://www.nowcoder.com/discuss/892108187820650496%EF%BC%9Bhttps://www.nowcoder.com/feed/main/detail/22c08e97f0e34becbae6d388131209f3%EF%BC%9Bhttps://www.nowcoder.com/feed/main/detail/0be454f3836b44bab988cc3c1130b5e1%EF%BC%9Bhttps://www.nowcoder.com/discuss/866140938798718976%EF%BC%9Bhttps://www.nowcoder.com/feed/main/detail/563b8cda26004293afcd5098b53fded0%EF%BC%9Bhttps://www.nowcoder.com/discuss/868082243900559360%EF%BC%9Bhttps://www.nowcoder.com/feed/main/detail/85c91d9e791449a684a6364f6fd95cf4%EF%BC%9Bhttps://www.nowcoder.com/feed/main/detail/291ba3fdde0d498cb84e9e89e23d3160%EF%BC%9Bhttps://www.nowcoder.com/discuss/861207388076900352%EF%BC%9Bhttps://www.nowcoder.com/discuss/897824104030531584%E3%80%82&quot;&gt;https://www.nowcoder.com/discuss/892108187820650496；https://www.nowcoder.com/feed/main/detail/22c08e97f0e34becbae6d388131209f3；https://www.nowcoder.com/feed/main/detail/0be454f3836b44bab988cc3c1130b5e1；https://www.nowcoder.com/discuss/866140938798718976；https://www.nowcoder.com/feed/main/detail/563b8cda26004293afcd5098b53fded0；https://www.nowcoder.com/discuss/868082243900559360；https://www.nowcoder.com/feed/main/detail/85c91d9e791449a684a6364f6fd95cf4；https://www.nowcoder.com/feed/main/detail/291ba3fdde0d498cb84e9e89e23d3160；https://www.nowcoder.com/discuss/861207388076900352；https://www.nowcoder.com/discuss/897824104030531584。&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;面经-1&quot;&gt;面经&lt;/h3&gt;
&lt;h4 id=&quot;知乎前端面经&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/discuss/892108187820650496&quot;&gt;知乎前端面经&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;原帖问题与答案：
&lt;ol&gt;
&lt;li&gt;SSE 流式返回机制。原帖未提供答案。&lt;/li&gt;
&lt;li&gt;图表生成失败怎么考虑。原帖未提供答案。&lt;/li&gt;
&lt;li&gt;MCP Server 怎么理解。原帖未提供答案。&lt;/li&gt;
&lt;li&gt;AI 上下文治理，包括污染、回退、Sub Agent 隔离、压缩、Skill。原帖未提供答案。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可复习问题：
&lt;ol&gt;
&lt;li&gt;SSE 流式返回机制是什么？&lt;/li&gt;
&lt;li&gt;图表生成失败时如何处理？&lt;/li&gt;
&lt;li&gt;如何理解 MCP Server？&lt;/li&gt;
&lt;li&gt;如何处理 AI 上下文污染、回退、Sub Agent 隔离、压缩与 Skill？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;美团前端暑期一二面面经&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/22c08e97f0e34becbae6d388131209f3&quot;&gt;美团前端暑期一二面面经&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;原帖问题与答案：以下问题原帖均未提供答案。
&lt;ol&gt;
&lt;li&gt;如何理解 AI？分享哪些好用的 AI 工具，主要用 AI 解决什么问题？&lt;/li&gt;
&lt;li&gt;项目中很多场景可由 AI 完成，应该怎么看，未来如何提升竞争力？是否实际尝试过 AI 工具？&lt;/li&gt;
&lt;li&gt;智能对话平台项目中，AI 对话流式输出为什么用 SSE 而不是 WebSocket？SSE 的好处、原理、断线风险与心跳保活如何处理？&lt;/li&gt;
&lt;li&gt;为什么选 DeepSeek？项目的关键技术点和 AI 部分如何实现？&lt;/li&gt;
&lt;li&gt;项目代码中 AI 生成占比多少，如何让 AI 生成代码并把控质量？AI 输出不符合预期甚至“欺骗”时如何处理？&lt;/li&gt;
&lt;li&gt;性能优化是否由 AI 辅助，优化代码由谁编写？&lt;/li&gt;
&lt;li&gt;如何处理语音噪声？若让 AI 做前端语音降噪，如何提出实现要求并验证方案可靠性？&lt;/li&gt;
&lt;li&gt;如何测试验收项目，如何覆盖弱网、噪音和真实使用场景？&lt;/li&gt;
&lt;li&gt;用过哪些 AI 工具，如何使用？是否部署过 LLM 服务？&lt;/li&gt;
&lt;li&gt;AI 自动生成周报任务如何理解并拆分模块？数据如何采集、采集哪些信息？哪些步骤必须人工介入？空数据如何处理？&lt;/li&gt;
&lt;li&gt;AI 自动生成周报工程目录中各 TS 文件有什么作用，为什么设计 base collector 基类，数据处理模块处理什么，还可如何改进？&lt;/li&gt;
&lt;li&gt;AI 时代如何应对多端技术要求，如何保持对 AI 代码的判断力，看不懂时怎么办，如何快速提升技术认知？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可复习问题：
&lt;ol&gt;
&lt;li&gt;SSE 流式输出、断线恢复与心跳保活如何设计？&lt;/li&gt;
&lt;li&gt;如何控制 AI 生成代码的质量并完成工程验收？&lt;/li&gt;
&lt;li&gt;如何拆解 AI 自动生成周报任务并划定人工介入边界？&lt;/li&gt;
&lt;li&gt;如何验证 AI 提供的前端语音降噪方案？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;前端ai-面试题真题&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/0be454f3836b44bab988cc3c1130b5e1&quot;&gt;前端+AI 面试题真题&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;原帖问题与答案：
&lt;ol&gt;
&lt;li&gt;SSE 与 WebSocket 有什么区别？原帖从通信方向、协议、数据类型、重连、使用成本和适用场景进行对比：SSE 基于 HTTP、服务端单向推送、只传文本且浏览器支持自动重连，适合 AI 流式输出；WebSocket 为 ws/wss 全双工协议，支持文本和二进制，需要自行实现心跳与重连，适合聊天、游戏和协同编辑等双向实时场景。&lt;/li&gt;
&lt;li&gt;RAG、Agent、Function Call、MCP、Skills 是什么？原帖将 RAG 概括为先检索再生成，Agent 负责规划并调用工具，Function Call 用于调用外部接口，MCP 统一模型与工具的通信，Skills 封装可复用能力。&lt;/li&gt;
&lt;li&gt;个人 AI 技能如何描述？原帖列出提示词工程、RAG 私有知识库、Agent 工作流与 Function Call、前端对话界面与流式输出、多 Agent 协作及需求拆解和方案落地。&lt;/li&gt;
&lt;li&gt;主流模型及应用场景有哪些？原帖列举 GPT-4o、Gemini、Claude、Llama、文心一言、通义千问、讯飞星火和 Kimi，并给出概括性特点；这些特点未提供进一步证据，标记 uncertain。&lt;/li&gt;
&lt;li&gt;使用哪些 IDE，如何对比？原帖比较 VS Code、WebStorm、Cursor 和 Zed，并建议按日常开发、AI 开发和大型项目选择。&lt;/li&gt;
&lt;li&gt;如何理解多 Agent？原帖描述为主管 Agent 分配任务、多个智能体分工执行并汇总，列出 AutoGen、CrewAI、LangGraph。&lt;/li&gt;
&lt;li&gt;AI 在实习部门有哪些应用场景？原帖列出智能客服与内部问答、代码生成、文档生成与总结、页面生成、自然语言转图表和测试生成。&lt;/li&gt;
&lt;li&gt;ReAct 与 Transformer 如何理解？原帖将 ReAct 概括为思考、行动、观察的循环，将 Transformer 概括为以自注意力理解上下文的模型基础架构。&lt;/li&gt;
&lt;li&gt;现有需求如何用 AI 实现？原帖给出需求拆解、/plan、/spec、实现、测试、上线优化的步骤，并要求关注幻觉、流式稳定性和异常处理。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可复习问题：
&lt;ol&gt;
&lt;li&gt;SSE 与 WebSocket 如何按 AI 交互场景选型？&lt;/li&gt;
&lt;li&gt;RAG、Agent、Function Call、MCP、Skills 如何协作？&lt;/li&gt;
&lt;li&gt;多 Agent 的分工、通信与汇总流程是什么？&lt;/li&gt;
&lt;li&gt;如何用 /plan 和 /spec 把现有需求拆解为可实现、可测试的 AI 功能？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;为什么-ai-agent-多用-sse以及-sse-和-websocket-技术选型&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/discuss/866140938798718976&quot;&gt;为什么 AI Agent 多用 SSE？以及 SSE 和 WebSocket 技术选型&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;原帖问题与答案：为什么 Agent 项目选择 SSE 而不是 WebSocket？原帖认为，大模型对话多为服务端到客户端的单向流式输出，SSE 基于 HTTP，接入和运维成本较低，并支持自动重连；当场景需要语音实时打断、多端协同、高频双向交互或二进制传输时，应考虑 WebSocket。原帖把 SSE 称为“长轮询升级版”，这一表述不严谨，标记 uncertain。&lt;/li&gt;
&lt;li&gt;可复习问题：
&lt;ol&gt;
&lt;li&gt;为什么 AI Agent 流式输出通常优先考虑 SSE？&lt;/li&gt;
&lt;li&gt;哪些实时交互场景必须改用 WebSocket？&lt;/li&gt;
&lt;li&gt;SSE 与 WebSocket 在重连、心跳、多实例和运维上的成本分别是什么？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;前端面试中怎么应对-ai-相关问题&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/563b8cda26004293afcd5098b53fded0&quot;&gt;前端面试中怎么应对 AI 相关问题&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;原帖问题与答案：
&lt;ol&gt;
&lt;li&gt;工作中如何使用 AI，主要解决什么问题，如何更高效使用 AI？原帖建议基于真实场景诚实回答，并补充 AI 痛点和 Prompt 设计等思考。&lt;/li&gt;
&lt;li&gt;Model、Agent、RAG、MCP、Vibe Coding、Function Calling 等概念如何区分与关联？原帖建议掌握概念及相互关系，未提供具体答案。&lt;/li&gt;
&lt;li&gt;流式数据交互如何实现？原帖未提供答案。&lt;/li&gt;
&lt;li&gt;MCP Server 如何传递数据？原帖未提供答案。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可复习问题：
&lt;ol&gt;
&lt;li&gt;如何用真实项目说明 AI 工具的使用方式与边界？&lt;/li&gt;
&lt;li&gt;Model、Agent、RAG、MCP、Vibe Coding、Function Calling 有什么区别与联系？&lt;/li&gt;
&lt;li&gt;前端流式数据交互和 MCP Server 数据传递如何实现？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;简历岗位材料-1&quot;&gt;简历/岗位材料&lt;/h3&gt;
&lt;h4 id=&quot;开源-agent-项目推荐--如何用它们丰富简历&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/discuss/868082243900559360&quot;&gt;开源 Agent 项目推荐 + 如何用它们丰富简历&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;信号：
&lt;ol&gt;
&lt;li&gt;原帖把已合并 PR、针对具体问题的深度实践、源码分析文章和 Issue 排查列为可验证的开源产出，强调必须写清改动内容，而不是只写项目名或“跑通”。&lt;/li&gt;
&lt;li&gt;对前端方向，原帖点名 Open WebUI 的 Streaming 展示、工具调用可视��、多轮对话和文件上传；也建议自行开发 MCP Server，或为 Agent 项目接入 Langfuse 可观测性。&lt;/li&gt;
&lt;li&gt;原帖建议简历项目包含明确问题、技术取舍、对比实验与结论；文中的具体 PR 数量和性能指标均是写法示例，不是作者已验证成果。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可追问方向：Streaming 与工具调用 UI 如何组织？MCP Server 的工具注册、参数 Schema 和通信如何实现？如何用 Trace 回放 Agent 步骤并验证改进效果？&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;前端转-ai-agent&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/85c91d9e791449a684a6364f6fd95cf4&quot;&gt;前端转 AI Agent&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;信号：
&lt;ol&gt;
&lt;li&gt;原帖列出的前端切入方向包括 AI 应用端 Agent、MCP/工具调用、RAG、全栈 Agent、企业流程 Agent、端侧 WebLLM 与 Agent 平台。&lt;/li&gt;
&lt;li&gt;可迁移能力集中在 SSE 流式渲染、复杂交互与状态管理、工具调用前端对接、引用溯源、文档渲染、Node 服务和浏览器运行时。&lt;/li&gt;
&lt;li&gt;原帖关于“薪资高”“爆款”“无缝转型”等市场判断没有数据支撑，标记 uncertain。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可追问方向：如何渲染工具调用与流式事件？如何管理多轮会话和记忆状态？如何在浏览器端运行轻量模型并处理性能与隐私？&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;适合写进简历的-agent-项目推荐&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/291ba3fdde0d498cb84e9e89e23d3160&quot;&gt;适合写进简历的 Agent 项目推荐&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;信号：
&lt;ol&gt;
&lt;li&gt;原帖认为适合面试展开的项目需要同时体现业务场景、系统设计和工程实现，而不只是接入模型。&lt;/li&gt;
&lt;li&gt;AI Coding/代码仓库问答可涉及代码切片、RAG、Tool Calling、上下文、状态管理、AST、调用链与测试生成；Deep Research 可涉及查询拆分、多源抽取、去重、重排和引用。&lt;/li&gt;
&lt;li&gt;长期记忆/个人知识库可围绕长短期记忆划分、写入时机和旧信息污染展开；AIOps 可围绕日志、指标、告警、runbook 与人工接管展开。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可追问方向：代码仓库如何切片和组织上下文？联网研究结果如何去重、重排并保留引用？长期记忆如何写入、召回和避免污染？&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;一个好的简历-agent-项目必须具备的几个关键因素&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/discuss/861207388076900352&quot;&gt;一个好的简历 Agent 项目，必须具备的几个关键因素&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;信号：
&lt;ol&gt;
&lt;li&gt;原帖建议项目覆盖 API 服务、数据库、会话管理、日志、错误处理、兜底与并发处理，体现可上线的系统工程能力。&lt;/li&gt;
&lt;li&gt;Agent 能力应体现意图识别、任务路由、工具调用或多 Agent 协作；原帖同时指出，并非所有场景都需要 Multi-Agent，单链路工作流可能更可控。&lt;/li&gt;
&lt;li&gt;上下文管理、Trace/Session/User 维度的可观测性和自动化评测被列为可深入追问的工程点。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可追问方向：什么时候选择单 Agent 工作流或 Multi-Agent？如何治理上下文共享与污染？如何记录工具调用、模型请求并构建自动化评测？&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;做了个-ai-agent-面试题库&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/discuss/897824104030531584&quot;&gt;做了个 AI Agent 面试题库&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;信号：
&lt;ol&gt;
&lt;li&gt;原帖公开了一个 React + Ant Design 前端、FastAPI + SQLite 后端的 Agent 面试题库，并明确说明主要由 Cursor/Claude Code 生成。&lt;/li&gt;
&lt;li&gt;项目使用 SQLite FTS5 做全文检索，并以关键词匹配方式关联开源项目；作者明确承认答案由 AI 生成，可能不准确。&lt;/li&gt;
&lt;li&gt;该项目真实技术点是 AI 辅助实现、全文检索和知识引用；内容正确性验证与相关度算法仍是明显追问点。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可追问方向：如何审核 AI 生成代码和答案？为什么选择 FTS5，如何评价检索质量？关键词相关度如何升级为可验证的召回与排序方案？&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;2026-07-16-1252--firecrawl-牛客前端-agent-同步&quot;&gt;2026-07-16 12:52 | Firecrawl 牛客前端 Agent 同步&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;本次检索词：&lt;code&gt;site:nowcoder.com &quot;前端&quot; &quot;Agent&quot; &quot;面经&quot;&lt;/code&gt;；&lt;code&gt;site:nowcoder.com &quot;前端&quot; &quot;Agent&quot; &quot;简历&quot;&lt;/code&gt;；&lt;code&gt;site:nowcoder.com &quot;AI Agent&quot; &quot;前端&quot; &quot;面试&quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;新增面经：0 条；新增简历/岗位材料：1 条。&lt;/li&gt;
&lt;li&gt;数据来源：&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/871d36feff2d4411a26ec7baf0127675%E3%80%82&quot;&gt;https://www.nowcoder.com/feed/main/detail/871d36feff2d4411a26ec7baf0127675。&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;简历岗位材料-2&quot;&gt;简历/岗位材料&lt;/h3&gt;
&lt;h4 id=&quot;教你如何快速包装简历agent相关&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/871d36feff2d4411a26ec7baf0127675&quot;&gt;教你如何快速包装简历（Agent相关）&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;信号：
&lt;ol&gt;
&lt;li&gt;原帖建议 Agent 项目写清多步任务分解、任务状态机、模型推理与规则约束结合的路由，以及统一、可插拔的工具接口。&lt;/li&gt;
&lt;li&gt;稳定性与工程化技术点包括参数和 Schema 校验、重试与 fallback、长短期记忆及上下文压缩、日志与 tracing、任务级监控。&lt;/li&gt;
&lt;li&gt;原帖建议用任务完成率、工具调用准确率、响应延迟和 token 成本建立评估闭环；其中 X% 和 XX% 均为占位写法，并非可验证成果，标记 uncertain。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可追问方向：任务状态机和 tool routing 如何实现；RAG 的向量检索、语义重排与 Agent 决策上下文如何协同；记忆压缩、超时降级、评测集和 tracing 如何形成工程闭环。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;2026-07-16-1257--firecrawl-牛客前端-agent-同步&quot;&gt;2026-07-16 12:57 | Firecrawl 牛客前端 Agent 同步&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;本次检索词：&lt;code&gt;site:nowcoder.com &quot;前端&quot; &quot;Agent&quot; &quot;面经&quot;&lt;/code&gt;；&lt;code&gt;site:nowcoder.com &quot;前端&quot; &quot;Agent&quot; &quot;简历&quot;&lt;/code&gt;；&lt;code&gt;site:nowcoder.com &quot;AI Agent&quot; &quot;前端&quot; &quot;面试&quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;新增面经：0 条；新增简历/岗位材料：0 条。&lt;/li&gt;
&lt;li&gt;数据来源：本次无新增原帖。&lt;/li&gt;
&lt;li&gt;本次没有新的高相关材料。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;2026-07-16-1308--firecrawl-牛客前端-agent-同步&quot;&gt;2026-07-16 13:08 | Firecrawl 牛客前端 Agent 同步&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;本次检索词：&lt;code&gt;site:nowcoder.com 前端 &quot;AI&quot; &quot;一面&quot;&lt;/code&gt;；&lt;code&gt;site:nowcoder.com 前端 &quot;大模型&quot; &quot;二面&quot;&lt;/code&gt;；&lt;code&gt;site:nowcoder.com 前端 &quot;MCP&quot; 面试&lt;/code&gt;；&lt;code&gt;site:nowcoder.com 前端 &quot;工作流&quot; 面试&lt;/code&gt;；&lt;code&gt;site:nowcoder.com &quot;智能体平台&quot; 前端&lt;/code&gt;；&lt;code&gt;site:nowcoder.com &quot;大模型应用&quot; 前端 招聘&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;新增面经：9 条；新增简历/岗位材料：1 条。&lt;/li&gt;
&lt;li&gt;数据来源：&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/bb9e8c5b9fd5442aa0483b7af4a3d5e9%EF%BC%9Bhttps://www.nowcoder.com/feed/main/detail/0f17e1b2e9214f778e7889e434f74ed9%EF%BC%9Bhttps://www.nowcoder.com/feed/main/detail/80693d262a7b439f87b85f6e8cd209d9%EF%BC%9Bhttps://www.nowcoder.com/feed/main/detail/cbefd28f5deb40efb773da3a67c10089%EF%BC%9Bhttps://www.nowcoder.com/feed/main/detail/0377a25b259144819db05ff6e84cf602%EF%BC%9Bhttps://www.nowcoder.com/feed/main/detail/a38f79a2f03c4e2faccff2d7a052ac2d%EF%BC%9Bhttps://www.nowcoder.com/discuss/868996108591120384%EF%BC%9Bhttps://www.nowcoder.com/discuss/868998856070000640%EF%BC%9Bhttps://www.nowcoder.com/discuss/873899049244508160%EF%BC%9Bhttps://www.nowcoder.com/feed/main/detail/0d226871ed4d4ca4a0adbd338678797c%E3%80%82&quot;&gt;https://www.nowcoder.com/feed/main/detail/bb9e8c5b9fd5442aa0483b7af4a3d5e9；https://www.nowcoder.com/feed/main/detail/0f17e1b2e9214f778e7889e434f74ed9；https://www.nowcoder.com/feed/main/detail/80693d262a7b439f87b85f6e8cd209d9；https://www.nowcoder.com/feed/main/detail/cbefd28f5deb40efb773da3a67c10089；https://www.nowcoder.com/feed/main/detail/0377a25b259144819db05ff6e84cf602；https://www.nowcoder.com/feed/main/detail/a38f79a2f03c4e2faccff2d7a052ac2d；https://www.nowcoder.com/discuss/868996108591120384；https://www.nowcoder.com/discuss/868998856070000640；https://www.nowcoder.com/discuss/873899049244508160；https://www.nowcoder.com/feed/main/detail/0d226871ed4d4ca4a0adbd338678797c。&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;面经-2&quot;&gt;面经&lt;/h3&gt;
&lt;h4 id=&quot;快手前端-ai-应用开发一面&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/bb9e8c5b9fd5442aa0483b7af4a3d5e9&quot;&gt;快手前端 AI 应用开发一面&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;原帖问题与答案：以下问题原帖均未提供答案。
&lt;ol&gt;
&lt;li&gt;事件循环中微任务和宏任务的执行顺序是什么？&lt;/li&gt;
&lt;li&gt;AI 流式输出中的 SSE 和 WebSocket 有什么区别？&lt;/li&gt;
&lt;li&gt;如何实现带并发控制的 Promise 控制器？&lt;/li&gt;
&lt;li&gt;TypeScript 泛型及 extends 关键字有什么作用？&lt;/li&gt;
&lt;li&gt;CSS 如何实现类似 ChatGPT 对话框的自动滚动到底部效果？&lt;/li&gt;
&lt;li&gt;如何判断包含大、中、小括号的字符串是否合法？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可复习问题：SSE 与 WebSocket 如何选型；Promise 并发控制如何实现；聊天列表自动滚动如何处理。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;快手暑期-ai-前端一面&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/0f17e1b2e9214f778e7889e434f74ed9&quot;&gt;快手暑期 AI 前端一面&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;原帖问题与答案：以下问题原帖均未提供答案。
&lt;ol&gt;
&lt;li&gt;请做自我介绍。&lt;/li&gt;
&lt;li&gt;实习的核心需求是什么？&lt;/li&gt;
&lt;li&gt;实习项目有哪些难点？&lt;/li&gt;
&lt;li&gt;自研项目的进展和产品方案是什么？&lt;/li&gt;
&lt;li&gt;是否开发过 Agent？&lt;/li&gt;
&lt;li&gt;当前前后端 HC 是否紧缩？原帖转述面试官称 AI 破坏了原有工作流，但没有进一步证据，标记 uncertain。&lt;/li&gt;
&lt;li&gt;前后端入职后是否都会以 Agent 开发为核心，主要做 Agent 工作流和部署？原帖转述面试官回答“确实”，适用范围不明，标记 uncertain。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可复习问题：如何证明自己开发过 Agent；实习项目与 Agent 工作流、部署需求如何关联。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;美团-ai-coding-前端开发一面&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/80693d262a7b439f87b85f6e8cd209d9&quot;&gt;美团 AI Coding 前端开发一面&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;原帖问题与答案：以下问题原帖均未提供答案。
&lt;ol&gt;
&lt;li&gt;JavaScript 事件循环中宏任务和微任务的执行顺序是什么？&lt;/li&gt;
&lt;li&gt;Flex 如何实现垂直居中且两端对齐？&lt;/li&gt;
&lt;li&gt;SSE 和 WebSocket 有什么区别，为什么 AI 对话多用 SSE？&lt;/li&gt;
&lt;li&gt;如何实现考虑循环引用和 Symbol 的深拷贝？&lt;/li&gt;
&lt;li&gt;TypeScript 泛型是什么，如何提取 Promise 返回类型？&lt;/li&gt;
&lt;li&gt;如何求无重复字符的最长子串长度？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可复习问题：AI 对话为何选择 SSE；深拷贝与 Promise 类型工具如何实现。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;阿里云-ai-应用开发前端一面&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/cbefd28f5deb40efb773da3a67c10089&quot;&gt;阿里云 AI 应用开发前端一面&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;原帖问题与答案：以下问题原帖均未提供答案。
&lt;ol&gt;
&lt;li&gt;SSE 与 WebSocket 有什么区别，AI 对话为什么通常选择 SSE？&lt;/li&gt;
&lt;li&gt;LLM 返回 Markdown 流时，如何处理代码块或公式截断造成的渲染闪烁？&lt;/li&gt;
&lt;li&gt;如何用 Fetch API 的 ReadableStream 实现简单的流式数据解析器？&lt;/li&gt;
&lt;li&gt;Promise.all、Promise.allSettled 和 Promise.race 有什么区别，在 AI 场景中如何应用？&lt;/li&gt;
&lt;li&gt;对话界面如何自动滚动到底部，同时允许用户向上查看历史消息？&lt;/li&gt;
&lt;li&gt;Record、Partial、Pick 等高级类型在 AI 接口响应定义中有什么作用？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可复习问题：流式 Markdown 如何稳定解析；ReadableStream 如何跨 chunk 缓冲；自动滚动如何区分程序滚动与用户滚动。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;得物-ai-应用开发前端一面&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/0377a25b259144819db05ff6e84cf602&quot;&gt;得物 AI 应用开发前端一面&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;原帖问题与答案：以下问题原帖均未提供答案。
&lt;ol&gt;
&lt;li&gt;AI 流式输出中的 Markdown 标签被截断时，前端如何渲染？&lt;/li&gt;
&lt;li&gt;什么是 RAG，前端可以参与哪些环节？&lt;/li&gt;
&lt;li&gt;如何通过 Prompt Engineering 减少前端请求的 token 消耗？&lt;/li&gt;
&lt;li&gt;AI 聊天消息很多时，如何保证滚动平滑？&lt;/li&gt;
&lt;li&gt;如何防范 Prompt Injection？&lt;/li&gt;
&lt;li&gt;AI 项目的性能监控有哪些特殊指标？&lt;/li&gt;
&lt;li&gt;通用 AI Chat 组件应设计哪些 Props 和 Slots？&lt;/li&gt;
&lt;li&gt;AI 接口网络抖动时，前端重试机制如何设计？&lt;/li&gt;
&lt;li&gt;向量数据库如何用于前端，前端是否需要处理向量化？&lt;/li&gt;
&lt;li&gt;如何实现支持拖拽上传、预览并可被 AI 解析的附件功能？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可复习问题：AI Chat 组件契约如何设计；流式 Markdown、长列表、重试、附件与安全如何组成完整交互链路。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;minimax-前端-ai-开发实习一面&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/a38f79a2f03c4e2faccff2d7a052ac2d&quot;&gt;MiniMax 前端 AI 开发实习一面&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;原帖问题与答案：以下问题原帖均未提供答案。
&lt;ol&gt;
&lt;li&gt;SSE 与 WebSocket 有什么区别，AI 对话为什么多采用 SSE？&lt;/li&gt;
&lt;li&gt;AI 聊天列表的长文本渲染卡顿如何处理？&lt;/li&gt;
&lt;li&gt;如何用 Fetch 处理 ReadableStream，模拟 AI 流式输出？&lt;/li&gt;
&lt;li&gt;自动滚动到底部如何处理用户手动向上滚动的冲突？&lt;/li&gt;
&lt;li&gt;Promise.all 和 Promise.allSettled 有什么区别，调用多个模型接口时如何选择？&lt;/li&gt;
&lt;li&gt;CSS 如何实现类似 ChatGPT 的打字机光标闪烁效果？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可复习问题：长文本流式渲染如何控制更新频率；多模型并发的失败语义如何选择；滚动锚定如何实现。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;字节剪映暑期实习-ai-前端一面&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/discuss/868996108591120384&quot;&gt;字节剪映暑期实习 AI 前端一面&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;原帖问题与答案：以下问题原帖均未提供答案。
&lt;ol&gt;
&lt;li&gt;AI Agent 系统的背景、职责和落地成果是什么？&lt;/li&gt;
&lt;li&gt;主从 Agent 如何分工？&lt;/li&gt;
&lt;li&gt;从 Agent 数量如何确定，如何避免重复探索？&lt;/li&gt;
&lt;li&gt;MCP 和 Tool Calling 有什么区别？&lt;/li&gt;
&lt;li&gt;Skill 和固定 Workflow 有什么区别，如何选型？&lt;/li&gt;
&lt;li&gt;如何复用 Agent 经验并优化 Memory？&lt;/li&gt;
&lt;li&gt;Next.js 电商项目的核心工作、难点和方案是什么？&lt;/li&gt;
&lt;li&gt;CSR、SSR、SSG 的区别、优缺点和适用场景是什么？&lt;/li&gt;
&lt;li&gt;SSR 和 CSR 哪个维护成本更高，为什么？&lt;/li&gt;
&lt;li&gt;TLS 1.2 与 TLS 1.3 的握手有什么区别？&lt;/li&gt;
&lt;li&gt;HTTPS 如何防止中间人攻击？&lt;/li&gt;
&lt;li&gt;超卖问题的根因和解决方案是什么？&lt;/li&gt;
&lt;li&gt;智能商品查询助手的架构、问题和优化手段是什么？&lt;/li&gt;
&lt;li&gt;Rerank 的作用是什么？&lt;/li&gt;
&lt;li&gt;为什么商品推荐使用 RAG，而不是直接使用大模型？&lt;/li&gt;
&lt;li&gt;如何寻找两个无限输入流共同出现的元素？&lt;/li&gt;
&lt;li&gt;个人项目和团队项目有什么区别，协作中遇到过什么痛点？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可复习问题：主从 Agent 如何控制并行与重复探索；MCP、Tool Calling、Skill、Workflow 如何划分；RAG 推荐为什么需要 Rerank。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;字节剪映暑期实习-ai-前端二面&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/discuss/868998856070000640&quot;&gt;字节剪映暑期实习 AI 前端二面&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;原帖问题与答案：以下问题原帖均未提供答案。
&lt;ol&gt;
&lt;li&gt;实习项目的背景、职责和成果是什么？&lt;/li&gt;
&lt;li&gt;系统优化如何定位根因、制定方案并验证效果？&lt;/li&gt;
&lt;li&gt;Memory 复用机制的初衷、实现、存储和管理方案是什么？&lt;/li&gt;
&lt;li&gt;为什么选择主从多 Agent 架构，和其他架构相比有哪些取舍？&lt;/li&gt;
&lt;li&gt;当前技术瓶颈和后续迭代方向是什么？&lt;/li&gt;
&lt;li&gt;ReAct、Self-Discovery、Plan-and-Execute 的原理与适用场景是什么？&lt;/li&gt;
&lt;li&gt;电商 RAG 智能导购的功能、链路和效果是什么？&lt;/li&gt;
&lt;li&gt;RAG 召回准确率如何逐步优化？&lt;/li&gt;
&lt;li&gt;如何测量召回率？&lt;/li&gt;
&lt;li&gt;为什么只用商品标题向量化，而不使用全字段？&lt;/li&gt;
&lt;li&gt;RAG 项目还有哪些优化方向？&lt;/li&gt;
&lt;li&gt;Agent 项目最大的系统难点是什么，如何解决？&lt;/li&gt;
&lt;li&gt;Agent 模块耦合严重、调试成本高时，如何解耦？&lt;/li&gt;
&lt;li&gt;是否有大模型微调实践？&lt;/li&gt;
&lt;li&gt;大模型微调的核心难点是什么？&lt;/li&gt;
&lt;li&gt;Prompt 工程和模型微调如何权衡？&lt;/li&gt;
&lt;li&gt;AI 对前端工程师有什么影响？&lt;/li&gt;
&lt;li&gt;如何理解 AI Native 前端工程师？&lt;/li&gt;
&lt;li&gt;为什么应聘剪映，求职动机是什么？&lt;/li&gt;
&lt;li&gt;对剪映产品和前端团队有哪些了解？&lt;/li&gt;
&lt;li&gt;如何用 JavaScript 实现最大并发数为 2 的异步 Scheduler？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可复习问题：多 Agent 架构如何选型与解耦；Memory 如何存储和复用；RAG 召回率如何测量；Prompt 与微调如何选择。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;2026-年前端面试中的-ai-工作流问题&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/discuss/873899049244508160&quot;&gt;2026 年前端面试中的 AI 工作流问题&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;原帖问题与答案：
&lt;ol&gt;
&lt;li&gt;日常 AI 工作流是什么？原帖将流程分为上下文准备、需求分析、代码生成、自动验证、上线优化五阶段；涉及 Rule、MCP、Skills、任务拆分、测试、CI、Code Review、监控和知识库更新。&lt;/li&gt;
&lt;li&gt;如何保证 AI 生成代码的质量？原帖回答包括开发前的规范与架构约束，开发中的上下文和 Skill，提交时的静态检查、测试与人工 Review，以及运行时监控反馈。&lt;/li&gt;
&lt;li&gt;使用哪些 AI 工具，各自优势是什么？原帖按 Cursor、Claude/GPT-4 和 ChatGPT 分别对应日常编码、复杂方案分析和快速学习查询；其中具体使用频率只是作者个人情况。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可复习问题：如何把 AI 编码工作流固化为可审计流程；Rule、MCP、Skill、测试、CI 和监控如何形成质量闭环。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;简历岗位材料-3&quot;&gt;简历/岗位材料&lt;/h3&gt;
&lt;h4 id=&quot;前端-ai-岗位需要达到的能力强度&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/0d226871ed4d4ca4a0adbd338678797c&quot;&gt;前端 AI 岗位需要达到的能力强度&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;信号：
&lt;ol&gt;
&lt;li&gt;原帖列出的前端基础包括 JavaScript/TypeScript、React 或 Vue、工程化、Node.js，以及 AI 流式输出所需的 SSE/WebSocket。&lt;/li&gt;
&lt;li&gt;AI 应用能力包括模型 API、流式输出、多轮对话、Prompt、RAG、Agent 工具调用、多模态处理和生成式 UI。&lt;/li&gt;
&lt;li&gt;进阶方向包括 Transformers.js、WebGPU、模型优化和隐私计算；原帖将部分能力称为“必备”或“大厂刚需”，但没有岗位样本支撑，标记 uncertain。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可追问方向：模型流式事件如何映射到前端状态；RAG 与 Agent 工具调用如何接入 UI；WebGPU 端侧推理如何处理性能、模型体积和隐私。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;2026-07-17-1208--firecrawl-牛客前端-agent-同步&quot;&gt;2026-07-17 12:08 | Firecrawl 牛客前端 Agent 同步&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;本次检索词：&lt;code&gt;site:nowcoder.com 前端 &quot;AI&quot; &quot;一面&quot;&lt;/code&gt;；&lt;code&gt;site:nowcoder.com 前端 &quot;大模型&quot; &quot;二面&quot;&lt;/code&gt;；&lt;code&gt;site:nowcoder.com 前端 &quot;MCP&quot; 面试&lt;/code&gt;；&lt;code&gt;site:nowcoder.com 前端 &quot;工作流&quot; 面试&lt;/code&gt;；&lt;code&gt;site:nowcoder.com &quot;智能体平台&quot; 前端&lt;/code&gt;；&lt;code&gt;site:nowcoder.com &quot;大模型应用&quot; 前端 招聘&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;新增面经：4 条；新增简历/岗位材料：1 条。&lt;/li&gt;
&lt;li&gt;数据来源：&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/8f02ab1b4ca9428bbc9340c21116a1ab%EF%BC%9Bhttps://www.nowcoder.com/feed/main/detail/6bdd0e226e2f4f06a17d21399d0e610c%EF%BC%9Bhttps://www.nowcoder.com/discuss/801188664293277696%EF%BC%9Bhttps://www.nowcoder.com/discuss/889546972099584000%EF%BC%9Bhttps://www.nowcoder.com/feed/main/detail/64bfe39a748343b8b4dbf63eac676e5f%E3%80%82&quot;&gt;https://www.nowcoder.com/feed/main/detail/8f02ab1b4ca9428bbc9340c21116a1ab；https://www.nowcoder.com/feed/main/detail/6bdd0e226e2f4f06a17d21399d0e610c；https://www.nowcoder.com/discuss/801188664293277696；https://www.nowcoder.com/discuss/889546972099584000；https://www.nowcoder.com/feed/main/detail/64bfe39a748343b8b4dbf63eac676e5f。&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;面经-3&quot;&gt;面经&lt;/h3&gt;
&lt;h4 id=&quot;字节前端实习二面面经&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/8f02ab1b4ca9428bbc9340c21116a1ab&quot;&gt;字节前端实习二面面经&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;原帖问题与答案：以下相关问题原帖均未提供答案。
&lt;ol&gt;
&lt;li&gt;AI Agent 怎么使用，平时如何在自己的项目里落地 AI 实践？&lt;/li&gt;
&lt;li&gt;AI 使用过程中有哪些令人难受的地方，或者希望大模型改进什么？&lt;/li&gt;
&lt;li&gt;是否尝试过 Workflow 这种固定的大模型工具？&lt;/li&gt;
&lt;li&gt;是否使用过 Skill 来沉淀自己的方法论？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可复习问题：
&lt;ol&gt;
&lt;li&gt;如何用真实项目说明 AI Agent 的落地方式？&lt;/li&gt;
&lt;li&gt;Workflow 与 Skill 分别如何固化 AI 开发流程和方法论？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;360-前端二面&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/6bdd0e226e2f4f06a17d21399d0e610c&quot;&gt;360 前端二面&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;原帖问题与答案：以下相关问题原帖均未提供答案。
&lt;ol&gt;
&lt;li&gt;流式对话的实现原理是什么？&lt;/li&gt;
&lt;li&gt;在 AI 项目中如何实现用户权限管理？&lt;/li&gt;
&lt;li&gt;操作权限如何实现？&lt;/li&gt;
&lt;li&gt;多模态 AI 工具调用对工作和生活有什么影响？&lt;/li&gt;
&lt;li&gt;如何看待 AI 代替前端？&lt;/li&gt;
&lt;li&gt;知识库文件解析预览如何做性能优化？&lt;/li&gt;
&lt;li&gt;RAGFlow 和 Dify 有什么区别？&lt;/li&gt;
&lt;li&gt;大模型 Function Calling 的函数如何调用？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可复习问题：
&lt;ol&gt;
&lt;li&gt;AI 项目的用户权限、操作权限与工具调用权限如何分层？&lt;/li&gt;
&lt;li&gt;流式对话、知识库预览和 Function Calling 如何组成前端交互链路？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;腾讯前端二面&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/discuss/801188664293277696&quot;&gt;腾讯前端二面&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;原帖问题与答案：
&lt;ol&gt;
&lt;li&gt;大模型流式输出是什么原理？原帖括注答案为 SSE，未进一步展开。&lt;/li&gt;
&lt;li&gt;SSE 和 WebSocket 有什么区别，应用层是什么协议，基于 UDP 还是 TCP？原帖未提供答案。&lt;/li&gt;
&lt;li&gt;为什么 WebSocket 不用 UDP，为什么 HTTP/3 可以用 UDP？原帖未提供答案。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可复习问题：
&lt;ol&gt;
&lt;li&gt;大模型流式输出为什么可以使用 SSE？&lt;/li&gt;
&lt;li&gt;SSE、WebSocket 与 HTTP/3 的应用层和传输层关系是什么？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;27-届暑期前端高频面试题汇总&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/discuss/889546972099584000&quot;&gt;27 届暑期前端高频面试题汇总&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;原帖问题与答案：以下为原帖明确列出的前端 AI/Agent 相关问题，原帖均未提供答案。
&lt;ol&gt;
&lt;li&gt;为什么 ChatGPT 使用 SSE 而不是 WebSocket，流式输出为什么不用其他方式？&lt;/li&gt;
&lt;li&gt;SSE 流式 Markdown 语法不完整时如何处理？&lt;/li&gt;
&lt;li&gt;SSE 断线重连、ping 心跳、AbortController 边界情况和降级兜底如何设计？&lt;/li&gt;
&lt;li&gt;AI 生成代码和项目规范冲突时如何约束，大项目 token 爆炸如何处理？&lt;/li&gt;
&lt;li&gt;团队是否使用 Rules 或 Skills 沉淀，解决什么问题？&lt;/li&gt;
&lt;li&gt;AI 对话上下文过长导致语义偏移时，如何做上下文摘要压缩？&lt;/li&gt;
&lt;li&gt;Markdown 如何安全渲染并防止 XSS？&lt;/li&gt;
&lt;li&gt;AI 模块在 Monorepo 中应该放在哪里？&lt;/li&gt;
&lt;li&gt;AST 静态分析如何生成文档供 AI 理解上下文？&lt;/li&gt;
&lt;li&gt;RAG 如何计算 chunk 相似度，效果不好如何优化，AI 胡言乱语如何处理？&lt;/li&gt;
&lt;li&gt;HyDE 是什么，用户模糊意图如何改写，为什么这与 RAG 不冲突？&lt;/li&gt;
&lt;li&gt;嵌入模型、切分策略、重叠步长与会话长记忆如何设计？&lt;/li&gt;
&lt;li&gt;ReAct 与 Workflow 的核心差异是什么？&lt;/li&gt;
&lt;li&gt;MCP 与 A2A 有什么区别，MCP 协议内部是什么样的？&lt;/li&gt;
&lt;li&gt;MCP 与 Skills 有什么区别，模型如何知道存在某个工具，Agent 有哪些编排范式？&lt;/li&gt;
&lt;li&gt;使用过哪些 AI 工具，AI 生成代码占比多少，哪些代码适合由 AI 生成？&lt;/li&gt;
&lt;li&gt;Vibe Coding 的一般流程是什么，中途出错如何改正，如何转向 Spec Coding？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可复习问题：
&lt;ol&gt;
&lt;li&gt;SSE、流式 Markdown、重连和安全渲染如何构成稳定的 AI 对话前端？&lt;/li&gt;
&lt;li&gt;Rules、Skills、MCP、A2A、ReAct 与 Workflow 如何划分职责？&lt;/li&gt;
&lt;li&gt;RAG、上下文压缩和 AST 文档如何改善模型输入质量？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;简历岗位材料-4&quot;&gt;简历/岗位材料&lt;/h3&gt;
&lt;h4 id=&quot;巨量星图大模型应用前端-agent-招聘&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/64bfe39a748343b8b4dbf63eac676e5f&quot;&gt;巨量星图大模型应用前端 Agent 招聘&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;信号：
&lt;ol&gt;
&lt;li&gt;原帖明确招聘前端工程师（Agent 方向），支持应届生和实习生投递。&lt;/li&gt;
&lt;li&gt;前端工作场景包括智能脚本生成、创意策划、内容推荐的交互与可视化。&lt;/li&gt;
&lt;li&gt;团队方向同时覆盖大模型、多模态应用与内容营销 Agent 系统，但原帖未进一步给出前端技术栈或任职要求。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可追问方向：智能脚本生成、创意策划和内容推荐场景的前端交互与可视化如何设计；更具体的技术实现无法从原帖证明，标记 uncertain。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;2026-07-18-1205--firecrawl-牛客前端-agent-同步&quot;&gt;2026-07-18 12:05 | Firecrawl 牛客前端 Agent 同步&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;本次检索词：&lt;code&gt;site:nowcoder.com 前端 &quot;AI&quot; &quot;一面&quot;&lt;/code&gt;；&lt;code&gt;site:nowcoder.com 前端 &quot;大模型&quot; &quot;二面&quot;&lt;/code&gt;；&lt;code&gt;site:nowcoder.com 前端 &quot;MCP&quot; 面试&lt;/code&gt;；&lt;code&gt;site:nowcoder.com 前端 &quot;工作流&quot; 面试&lt;/code&gt;；&lt;code&gt;site:nowcoder.com &quot;智能体平台&quot; 前端&lt;/code&gt;；&lt;code&gt;site:nowcoder.com &quot;大模型应用&quot; 前端 招聘&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;新增面经：2 条；新增简历/岗位材料：0 条。&lt;/li&gt;
&lt;li&gt;数据来源：&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/719c5519554c4d1885baf5f31ce4ae00%EF%BC%9Bhttps://www.nowcoder.com/feed/main/detail/a1a64c32b2034659a369003b79edf5d7%E3%80%82&quot;&gt;https://www.nowcoder.com/feed/main/detail/719c5519554c4d1885baf5f31ce4ae00；https://www.nowcoder.com/feed/main/detail/a1a64c32b2034659a369003b79edf5d7。&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;面经-4&quot;&gt;面经&lt;/h3&gt;
&lt;h4 id=&quot;磐松前端一面&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/719c5519554c4d1885baf5f31ce4ae00&quot;&gt;磐松前端一面&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;原帖问题与答案：以下相关问题原帖均未提供答案。
&lt;ol&gt;
&lt;li&gt;项目和市面上已有的 DeepSeek 问答平台有什么区别？&lt;/li&gt;
&lt;li&gt;Agent 具体是怎么封装的？&lt;/li&gt;
&lt;li&gt;AI 回答返回的数据以什么形式展示到前端页面，为什么不用 WebSocket？&lt;/li&gt;
&lt;li&gt;弱网、断连或响应数据缺失时有什么兜底策略；回答中途停止后，下次如何完整渲染该消息？&lt;/li&gt;
&lt;li&gt;AI 回答的历史记录如何处理，历史数据能存多少条，是否有限制？&lt;/li&gt;
&lt;li&gt;聊天对话页面如何优化大量历史数据，是否了解或使用过虚拟列表？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可复习问题：
&lt;ol&gt;
&lt;li&gt;项目和市面上已有的 DeepSeek 问答平台有什么区别？&lt;/li&gt;
&lt;li&gt;Agent 具体是怎么封装的？&lt;/li&gt;
&lt;li&gt;AI 回答返回的数据以什么形式展示到前端页面，为什么不用 WebSocket？&lt;/li&gt;
&lt;li&gt;弱网、断连或响应数据缺失时有什么兜底策略；回答中途停止后，下次如何完整渲染该消息？&lt;/li&gt;
&lt;li&gt;AI 回答的历史记录如何处理，历史数据能存多少条，是否有限制？&lt;/li&gt;
&lt;li&gt;聊天对话页面如何优化大量历史数据，是否了解或使用过虚拟列表？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;腾讯前端实习面经&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/a1a64c32b2034659a369003b79edf5d7&quot;&gt;腾讯前端实习面经&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;原帖问题与答案：以下相关问题原帖均未提供答案。
&lt;ol&gt;
&lt;li&gt;平时开发和学习是否使用 AI，开发项目时使用哪些 AI 工具？&lt;/li&gt;
&lt;li&gt;Cursor Agent 辅助开发有哪些坑？&lt;/li&gt;
&lt;li&gt;AI 编程有哪些最佳实践或工作流，Skill、MCP 如何帮助开发？&lt;/li&gt;
&lt;li&gt;除开发外，哪些编程节点或流程可以用 AI 提效？&lt;/li&gt;
&lt;li&gt;如何 Review 或测试 AI 产出以避免幻觉？&lt;/li&gt;
&lt;li&gt;如何把多 Agent、Team 模式或 Agent 质检接入开发流程，同时提高效率和代码质量？&lt;/li&gt;
&lt;li&gt;如何关注快速迭代的 AI 知识、理论和实践，近期 Git 上有哪些热门 AI 编程项目？&lt;/li&gt;
&lt;li&gt;是否搭建过 OpenClaw？&lt;/li&gt;
&lt;li&gt;实现流式传输时为什么选择 RxJS 而不是原生 EventSource，RxJS 的核心价值是什么？&lt;/li&gt;
&lt;li&gt;SSE 和 WebSocket 有什么区别？&lt;/li&gt;
&lt;li&gt;流式输出在前端如何渲染，是逐字追加 DOM 还是缓冲后批量更新，如何处理频繁 DOM 更新的性能问题？&lt;/li&gt;
&lt;li&gt;文件上传解析中前端负责哪些部分？&lt;/li&gt;
&lt;li&gt;AI 辅助编码和独立编码分别应如何看待？&lt;/li&gt;
&lt;li&gt;Skill 和 MCP 有什么区别，是否开发过 Skill？&lt;/li&gt;
&lt;li&gt;OpenClaw 如何实现用户需求？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可复习问题：
&lt;ol&gt;
&lt;li&gt;平时开发和学习是否使用 AI，开发项目时使用哪些 AI 工具？&lt;/li&gt;
&lt;li&gt;Cursor Agent 辅助开发有哪些坑？&lt;/li&gt;
&lt;li&gt;AI 编程有哪些最佳实践或工作流，Skill、MCP 如何帮助开发？&lt;/li&gt;
&lt;li&gt;除开发外，哪些编程节点或流程可以用 AI 提效？&lt;/li&gt;
&lt;li&gt;如何 Review 或测试 AI 产出以避免幻觉？&lt;/li&gt;
&lt;li&gt;如何把多 Agent、Team 模式或 Agent 质检接入开发流程，同时提高效率和代码质量？&lt;/li&gt;
&lt;li&gt;如何关注快速迭代的 AI 知识、理论和实践，近期 Git 上有哪些热门 AI 编程项目？&lt;/li&gt;
&lt;li&gt;是否搭建过 OpenClaw？&lt;/li&gt;
&lt;li&gt;实现流式传输时为什么选择 RxJS 而不是原生 EventSource，RxJS 的核心价值是什么？&lt;/li&gt;
&lt;li&gt;SSE 和 WebSocket 有什么区别？&lt;/li&gt;
&lt;li&gt;流式输出在前端如何渲染，是逐字追加 DOM 还是缓冲后批量更新，如何处理频繁 DOM 更新的性能问题？&lt;/li&gt;
&lt;li&gt;文件上传解析中前端负责哪些部分？&lt;/li&gt;
&lt;li&gt;AI 辅助编码和独立编码分别应如何看待？&lt;/li&gt;
&lt;li&gt;Skill 和 MCP 有什么区别，是否开发过 Skill？&lt;/li&gt;
&lt;li&gt;OpenClaw 如何实现用户需求？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;2026-07-19-1203--firecrawl-牛客前端-agent-同步&quot;&gt;2026-07-19 12:03 | Firecrawl 牛客前端 Agent 同步&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;本次检索词：&lt;code&gt;site:nowcoder.com 前端 &quot;AI&quot; &quot;一面&quot;&lt;/code&gt;；&lt;code&gt;site:nowcoder.com 前端 &quot;大模型&quot; &quot;二面&quot;&lt;/code&gt;；&lt;code&gt;site:nowcoder.com 前端 &quot;MCP&quot; 面试&lt;/code&gt;；&lt;code&gt;site:nowcoder.com 前端 &quot;工作流&quot; 面试&lt;/code&gt;；&lt;code&gt;site:nowcoder.com &quot;智能体平台&quot; 前端&lt;/code&gt;；&lt;code&gt;site:nowcoder.com &quot;大模型应用&quot; 前端 招聘&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;新增面经：0 条；新增简历/岗位材料：0 条。&lt;/li&gt;
&lt;li&gt;数据来源：本次无新增原帖。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;本次没有新的高相关材料。&lt;/p&gt;
&lt;h2 id=&quot;2026-07-20-1207--firecrawl-牛客前端-agent-同步&quot;&gt;2026-07-20 12:07 | Firecrawl 牛客前端 Agent 同步&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;本次检索词：&lt;code&gt;site:nowcoder.com 前端 &quot;AI&quot; &quot;一面&quot;&lt;/code&gt;；&lt;code&gt;site:nowcoder.com 前端 &quot;大模型&quot; &quot;二面&quot;&lt;/code&gt;；&lt;code&gt;site:nowcoder.com 前端 &quot;MCP&quot; 面试&lt;/code&gt;；&lt;code&gt;site:nowcoder.com 前端 &quot;工作流&quot; 面试&lt;/code&gt;；&lt;code&gt;site:nowcoder.com &quot;智能体平台&quot; 前端&lt;/code&gt;；&lt;code&gt;site:nowcoder.com &quot;大模型应用&quot; 前端 招聘&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;新增面经：2 条；新增简历/岗位材料：1 条。&lt;/li&gt;
&lt;li&gt;数据来源：&lt;a href=&quot;https://www.nowcoder.com/discuss/868928829648031744%EF%BC%9Bhttps://www.nowcoder.com/feed/main/detail/c9840d6bc86749ca95897e2bfd3b5116%EF%BC%9Bhttps://www.nowcoder.com/discuss/859392487968759808%E3%80%82&quot;&gt;https://www.nowcoder.com/discuss/868928829648031744；https://www.nowcoder.com/feed/main/detail/c9840d6bc86749ca95897e2bfd3b5116；https://www.nowcoder.com/discuss/859392487968759808。&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;面经-5&quot;&gt;面经&lt;/h3&gt;
&lt;h4 id=&quot;影刀-ai-前端一面惨不忍睹&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/discuss/868928829648031744&quot;&gt;影刀 AI 前端一面，惨不忍睹&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;原帖问题与答案：以下相关问题原帖均未提供答案。
&lt;ol&gt;
&lt;li&gt;为什么会有给 AI 使用的 sandbox，它解决什么问题，是否用过？&lt;/li&gt;
&lt;li&gt;LLM Playground 如何实现？&lt;/li&gt;
&lt;li&gt;SSE 和 Socket 有什么区别，为什么流式输出使用 SSE 而不是 Socket？&lt;/li&gt;
&lt;li&gt;模型流式输出时刷新页面或切换会话，如何保证返回后对话继续；SSE 断开后如何恢复？&lt;/li&gt;
&lt;li&gt;用户点击停止时如何设计中止；前端取消 Fetch 后，后端 SSE 如何停止？&lt;/li&gt;
&lt;li&gt;提供给 LLM 的 Tool 是否由前端实现，Web Search 如何调用？&lt;/li&gt;
&lt;li&gt;是否参与过 Agent 开发，是否了解 LLM 的运行过程？&lt;/li&gt;
&lt;li&gt;用户输出与模型输入是什么关系，多模态消息和纯文本消息有什么区别？&lt;/li&gt;
&lt;li&gt;为什么使用 SWR，为什么需要请求缓存？&lt;/li&gt;
&lt;li&gt;项目如何实现国际化？&lt;/li&gt;
&lt;li&gt;全球论坛中，如何让海外用户看到中文帖子的英文版本？&lt;/li&gt;
&lt;li&gt;后端应在什么时机翻译？&lt;/li&gt;
&lt;li&gt;相同文本是否需要重复翻译，如何优化；实时论坛中请求缓存是否仍有必要？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可复习问题：
&lt;ol&gt;
&lt;li&gt;为什么会有给 AI 使用的 sandbox，它解决什么问题，是否用过？&lt;/li&gt;
&lt;li&gt;SSE 流中断后如何恢复会话，并协调前后端真正停止生成？&lt;/li&gt;
&lt;li&gt;提供给 LLM 的 Tool 是否由前端实现，Web Search 如何调用？&lt;/li&gt;
&lt;li&gt;是否参与过 Agent 开发，是否了解 LLM 的运行过程？&lt;/li&gt;
&lt;li&gt;多模态消息和纯文本消息有什么区别？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;dify-前端实习一二面&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/c9840d6bc86749ca95897e2bfd3b5116&quot;&gt;Dify 前端实习一二面&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;原帖问题与答案：以下相关问题原帖均未提供答案。
&lt;ol&gt;
&lt;li&gt;平时在工作中如何使用 AI，具体用于哪些方面？&lt;/li&gt;
&lt;li&gt;是否使用过 Claude Code？&lt;/li&gt;
&lt;li&gt;是否使用过 Dify？&lt;/li&gt;
&lt;li&gt;对当前 AI 的看法是什么？&lt;/li&gt;
&lt;li&gt;是否了解 Dify？&lt;/li&gt;
&lt;li&gt;什么是 Agent？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可复习问题：
&lt;ol&gt;
&lt;li&gt;平时在工作中如何使用 AI，具体用于哪些方面？&lt;/li&gt;
&lt;li&gt;是否使用过 Claude Code？&lt;/li&gt;
&lt;li&gt;是否使用过 Dify？&lt;/li&gt;
&lt;li&gt;对当前 AI 的看法是什么？&lt;/li&gt;
&lt;li&gt;什么是 Agent？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;简历岗位材料-5&quot;&gt;简历/岗位材料&lt;/h3&gt;
&lt;h4 id=&quot;大厂前端岗位-jd总结前端-ai-学习路线&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/discuss/859392487968759808&quot;&gt;大厂前端岗位 JD：总结前端 AI 学习路线&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;信号：
&lt;ol&gt;
&lt;li&gt;原帖汇总的前端 AI 场景包括 AI IDE、Agent 平台、多模态创作、AI 全栈和可视化 AI 交互；具体 JD 内容主要以图片呈现，无法从抓取文本逐项核验，标记 uncertain。&lt;/li&gt;
&lt;li&gt;原帖明确列出的 Agent 平台前端职责包括多 Agent 协同界面、可视化编排工具，以及 Agent 交互、RAG 检索过程展示和多轮对话管理。&lt;/li&gt;
&lt;li&gt;原帖列出的相关工程能力包括模型 API 接入、SSE/WebSocket 流式输出、Token 消耗优化、WebGL/WebGPU/WebRTC、实时通信、性能优化与安全合规。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可追问方向：Agent 交互界面如何展示规划和工具调用；RAG 检索过程如何可视化；多轮对话状态如何管理；SSE/WebSocket 如何选型；Token、推理延迟和前端性能如何协同优化。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;2026-07-21-1207--firecrawl-牛客前端-agent-同步&quot;&gt;2026-07-21 12:07 | Firecrawl 牛客前端 Agent 同步&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;本次检索词：&lt;code&gt;site:nowcoder.com 前端 &quot;AI&quot; &quot;一面&quot;&lt;/code&gt;；&lt;code&gt;site:nowcoder.com 前端 &quot;大模型&quot; &quot;二面&quot;&lt;/code&gt;；&lt;code&gt;site:nowcoder.com 前端 &quot;MCP&quot; 面试&lt;/code&gt;；&lt;code&gt;site:nowcoder.com 前端 &quot;工作流&quot; 面试&lt;/code&gt;；&lt;code&gt;site:nowcoder.com &quot;智能体平台&quot; 前端&lt;/code&gt;；&lt;code&gt;site:nowcoder.com &quot;大模型应用&quot; 前端 招聘&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;新增面经：2 条；新增简历/岗位材料：0 条。&lt;/li&gt;
&lt;li&gt;数据来源：&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/9a7e06328014454aababb71d441b1f65%EF%BC%9Bhttps://www.nowcoder.com/feed/main/detail/e17421f1011649018c99aad1427ad902%E3%80%82&quot;&gt;https://www.nowcoder.com/feed/main/detail/9a7e06328014454aababb71d441b1f65；https://www.nowcoder.com/feed/main/detail/e17421f1011649018c99aad1427ad902。&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;面经-6&quot;&gt;面经&lt;/h3&gt;
&lt;h4 id=&quot;前端小厂面经&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/9a7e06328014454aababb71d441b1f65&quot;&gt;前端小厂面经&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;原帖问题与答案：以下相关问题原帖均未提供答案。
&lt;ol&gt;
&lt;li&gt;项目是智能体吗？&lt;/li&gt;
&lt;li&gt;是否了解过 AI 工作流？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可复习问题：
&lt;ol&gt;
&lt;li&gt;项目是智能体吗？&lt;/li&gt;
&lt;li&gt;是否了解过 AI 工作流？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;前端-ai-项目面试官高频拷打问题&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/e17421f1011649018c99aad1427ad902&quot;&gt;前端 AI 项目：面试官高频拷打问题&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;原帖问题与答案：以下相关问题原帖均未提供答案。
&lt;ol&gt;
&lt;li&gt;项目业务价值是什么，为什么要做 AI 赋能前端场景？&lt;/li&gt;
&lt;li&gt;大模型接口怎么选，云端模型和开源模型有什么区别，选型依据是什么？&lt;/li&gt;
&lt;li&gt;框架和渲染方案为什么这样选，针对 AI 流式场景做了哪些适配？&lt;/li&gt;
&lt;li&gt;大模型流式返回如何实现，SSE、Fetch Streaming、WebSocket 有什么区别，如何落地选择？&lt;/li&gt;
&lt;li&gt;分片数据如何解析和逐字渲染，如何解决乱码、断行和拼接异常？&lt;/li&gt;
&lt;li&gt;如何实现请求中断、重复请求拦截，AbortController 如何使用？&lt;/li&gt;
&lt;li&gt;多轮会话上下文如何拼接传递，存在哪些 Token 开销？&lt;/li&gt;
&lt;li&gt;长对话卡顿如何优化，如何做上下文压缩和历史消息裁剪？&lt;/li&gt;
&lt;li&gt;对话记忆采用本地还是服务端存储，各自优缺点是什么？&lt;/li&gt;
&lt;li&gt;Prompt 提示词工程做了哪些优化，如何提升回答准确度？&lt;/li&gt;
&lt;li&gt;Markdown、代码块、公式等复杂内容如何渲染？&lt;/li&gt;
&lt;li&gt;函数调用、MCP 协议和 AI 工具联动时，前端如何配合？&lt;/li&gt;
&lt;li&gt;长文本渲染和海量聊天记录导致页面卡顿时如何解决？&lt;/li&gt;
&lt;li&gt;骨架屏、加载状态、断网重连和异常降级方案如何设计？&lt;/li&gt;
&lt;li&gt;AI 高频请求场景如何使用防抖、限流和接口缓存？&lt;/li&gt;
&lt;li&gt;项目开发的最大难点是什么，如何排查流式接口异常？&lt;/li&gt;
&lt;li&gt;敏感词过滤、内容安全和输入边界校验如何处理？&lt;/li&gt;
&lt;li&gt;是否了解前端本地 AI、WebLLM 和 RAG 的前端落地思路？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可复习问题：
&lt;ol&gt;
&lt;li&gt;AI 流式响应、增量解析、中断和异常恢复如何组成稳定的前端链路？&lt;/li&gt;
&lt;li&gt;多轮上下文、记忆存储和长对话性能如何协同设计？&lt;/li&gt;
&lt;li&gt;MCP、函数调用和 AI 工具联动时，前端承担哪些职责？&lt;/li&gt;
&lt;li&gt;前端本地 AI、WebLLM 和 RAG 分别适合哪些落地场景？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;2026-07-21-1239--firecrawl-牛客前端-agent-同步&quot;&gt;2026-07-21 12:39 | Firecrawl 牛客前端 Agent 同步&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;本次检索词：&lt;code&gt;site:nowcoder.com 前端 &quot;AI&quot; &quot;一面&quot;&lt;/code&gt;；&lt;code&gt;site:nowcoder.com 前端 &quot;大模型&quot; &quot;二面&quot;&lt;/code&gt;；&lt;code&gt;site:nowcoder.com 前端 &quot;MCP&quot; 面试&lt;/code&gt;；&lt;code&gt;site:nowcoder.com 前端 &quot;工作流&quot; 面试&lt;/code&gt;；&lt;code&gt;site:nowcoder.com &quot;智能体平台&quot; 前端&lt;/code&gt;；&lt;code&gt;site:nowcoder.com &quot;大模型应用&quot; 前端 招聘&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;新增面经：4 条；新增简历/岗位材料：1 条。&lt;/li&gt;
&lt;li&gt;数据来源：&lt;a href=&quot;https://www.nowcoder.com/discuss/863430474180333568%EF%BC%9Bhttps://www.nowcoder.com/discuss/864153617182355456%EF%BC%9Bhttps://www.nowcoder.com/discuss/864449317648490496%EF%BC%9Bhttps://www.nowcoder.com/feed/main/detail/129eaa1c20444651ac3b932e200d3da4%EF%BC%9Bhttps://www.nowcoder.com/discuss/882681718157672448%E3%80%82&quot;&gt;https://www.nowcoder.com/discuss/863430474180333568；https://www.nowcoder.com/discuss/864153617182355456；https://www.nowcoder.com/discuss/864449317648490496；https://www.nowcoder.com/feed/main/detail/129eaa1c20444651ac3b932e200d3da4；https://www.nowcoder.com/discuss/882681718157672448。&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;面经-7&quot;&gt;面经&lt;/h3&gt;
&lt;h4 id=&quot;聊一聊最近碰到的一些-agent-面试题一&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/discuss/863430474180333568&quot;&gt;聊一聊最近碰到的一些 Agent 面试题（一）&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;原帖问题与答案：
&lt;ol&gt;
&lt;li&gt;ACP 的设计思路和解决的问题是什么；ACP 与 MCP 是否冲突；为什么选择 REST 而不是 gRPC 或 WebSocket？原帖回答：ACP 用框架无关的 REST/HTTP 连接 Agent，以 Agent Card、Task、Message、Artifact 描述发现、任务生命周期、过程消息和产物，支持同步及异步/SSE；MCP 连接 Agent 与工具，两者解决不同层面的问题；选择 REST 是以生态可达性换取极端性能。&lt;/li&gt;
&lt;li&gt;MCP 与 Agent Skills 的设计差异是什么，分别适合什么场景；Skills 无进程隔离有哪些风险；二者未来是否会合并？原帖回答：MCP 通过独立 Server、JSON-RPC 和凭证隔离连接外部能力，Skills 以 SKILL.md 向 Agent 注入行为规则；外部系统和合规场景偏 MCP，行为规范和本地工作流偏 Skills；Skills 共享 Agent 权限，因此只应加载可信来源；原帖判断二者更可能互补而非合并。&lt;/li&gt;
&lt;li&gt;Agent Memory 如何设计，短期、长期、情景记忆分别解决什么问题；如何防止记忆污染；如何改善不相关召回？原帖回答：短期记忆承载当前上下文，长期记忆保存跨会话知识，情景记忆保存完整任务经历；写入需设置成功门槛、独立质量评估、冲突审核和置信度衰减；召回可结合混合检索、元数据过滤、重排和使用反馈。&lt;/li&gt;
&lt;li&gt;RAG 架构及从原型到生产的优化点是什么；RAG 与微调如何选择和结合；如何评估 RAG；多轮对话有哪些特殊挑战？原帖回答：基础链路是索引、检索、生成，生产优化覆盖语义切块、混合检索、查询改写、Reranker、元数据过滤和上下文组装；RAG 适合动态/私有知识，微调适合行为和风格，二者可结合；评估需拆分检索与生成指标；多轮场景还需处理问题改写、对话指代和上下文膨胀。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可复习问题：ACP、MCP、Skills 如何分层；Agent Memory 的写入与召回如何形成质量闭环；RAG 如何从检索原型演进到可评估的生产系统。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;28-届实习拷打一场面试的-23-个-agent-问题&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/discuss/864153617182355456&quot;&gt;28 届实习拷打：一场面试的 23 个 Agent 问题&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;原帖问题与答案：原帖围绕“工具调用失败怎么办”串联 23 个问题。第 10 题只给出提示词及入参/出参设计的简略回答，第 19 题提到用 Agent 可观测平台溯源；总体回答框架是先用模型选型、工具描述和入参校验减少失败，再用可观测性区分意图、参数与工具故障，最后做重试、备用工具和最终兜底。其余问题原帖未提供完整答案。
&lt;ol&gt;
&lt;li&gt;什么是 Agent，它由哪些部分组成？&lt;/li&gt;
&lt;li&gt;为什么需要引入工具，单纯大模型为什么不够？&lt;/li&gt;
&lt;li&gt;工具给大模型扩展了哪些能力？&lt;/li&gt;
&lt;li&gt;什么是 Function Call？&lt;/li&gt;
&lt;li&gt;什么是 MCP，它由哪些部分组成？&lt;/li&gt;
&lt;li&gt;Function Call、MCP 和工具有什么区别？&lt;/li&gt;
&lt;li&gt;Skill 与 Function Call、MCP 有什么区别？&lt;/li&gt;
&lt;li&gt;Skill 有哪些特性？&lt;/li&gt;
&lt;li&gt;MCP 和 Skill 哪个占用的上下文更大？&lt;/li&gt;
&lt;li&gt;如何写好一个工具？&lt;/li&gt;
&lt;li&gt;提示词工程的方法论是什么？&lt;/li&gt;
&lt;li&gt;如何理解上下文工程？&lt;/li&gt;
&lt;li&gt;上下文工程与提示词工程有什么区别？&lt;/li&gt;
&lt;li&gt;如何避免不同用户的上下文互相污染？&lt;/li&gt;
&lt;li&gt;如何保存、隔离、选择和压缩上下文？&lt;/li&gt;
&lt;li&gt;如何持久化上下文，OpenClaw 是怎么做的？&lt;/li&gt;
&lt;li&gt;平时使用哪些模型或 AI 工具，Agent 系统为什么选择当前模型而不是其他模型？&lt;/li&gt;
&lt;li&gt;如何做工具入参校验，有哪些现成手段？&lt;/li&gt;
&lt;li&gt;如何判断工具调用失败源于意图识别错误、入参错误还是工具掉线？&lt;/li&gt;
&lt;li&gt;知道哪些 Agent 系统可观测平台？&lt;/li&gt;
&lt;li&gt;LangSmith 和 Langfuse 有什么区别，如何选择？&lt;/li&gt;
&lt;li&gt;工具重试仍失败时怎么办？&lt;/li&gt;
&lt;li&gt;备用工具也失败时怎么办？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可复习问题：工具调用失败如何按“预防、观测溯源、重试、降级、人工兜底”设计；上下文隔离、持久化和压缩如何落到多用户 Agent 系统。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;聊一聊最近碰到的一些-agent-面试题五&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/discuss/864449317648490496&quot;&gt;聊一聊最近碰到的一些 Agent 面试题（五）&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;原帖问题与答案：
&lt;ol&gt;
&lt;li&gt;如何开发高质量 Agent Skill，好的 SKILL.md 应包含和避免什么；如何测试 Skill；Skill 触发条件冲突怎么办？原帖回答围绕清晰的触发描述、具体可执行步骤、渐进式加载、少写模型已知常识，并通过正向/负向触发用例和真实任务测试；冲突时应收窄描述、明确优先级或合并重叠 Skill。&lt;/li&gt;
&lt;li&gt;开发 MCP Server 要考虑哪些设计决策和常见坑；工具描述由谁写；一个 Server 放多少工具？原帖回答覆盖工具边界、Schema、错误返回、状态、安全与可观测性；工具描述需要 Server 开发者与 Agent 使用者协作；工具数量没有固定上限，关键是领域内聚并避免把大量无关工具同时暴露给模型。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.cursorrules&lt;/code&gt;、&lt;code&gt;CLAUDE.md&lt;/code&gt;、&lt;code&gt;AGENTS.md&lt;/code&gt; 如何配置才有效；与对话指令冲突时听谁的；团队是否应提交 Git？原帖回答强调规则要具体、可执行、分层且避免冗长冲突；实际优先级取决于宿主的指令层级；团队共享规则应版本化提交，个人偏好不应混入共享文件。&lt;/li&gt;
&lt;li&gt;Agent 输出不符合预期时如何调试，与传统代码调试有什么区别；有哪些快速诊断经验？原帖回答要求记录完整轨迹，逐段检查输入上下文、模型决策、工具参数、工具结果和最终生成；Agent 的非确定性意味着还要固定模型参数、保存重放样本并用评测集比较。&lt;/li&gt;
&lt;li&gt;什么是 Prompt 缓存，它如何影响 Agent 成本与性能；与 RAG 是否冲突？原帖回答：缓存复用稳定前缀的计算结果，可降低长系统提示和工具定义的首 Token 延迟与成本；需把稳定内容放前、动态内容放后；RAG 提供动态知识，缓存复用稳定前缀，两者不冲突。&lt;/li&gt;
&lt;li&gt;Agent 如何做灰度发布和 A/B 测试，与传统软件有何不同；如何确认 Prompt 改进不是巧合？原帖回答强调对 Prompt、模型、工具和参数做版本化及稳定分流，同时观察任务成功率、质量、成本、延迟和安全指标；需要足够样本、统计显著性和离线评测交叉验证。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可复习问题：Skill、MCP Server 和 Rules 文件如何分别形成可维护接口；Agent 的调试、缓存、灰度与实验体系如何工程化。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;大模型应用开发面经5-年经验&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/129eaa1c20444651ac3b932e200d3da4&quot;&gt;大模型应用开发面经（5 年经验）&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;原帖问题与答案：原帖汇总作者近半年多家公司实际面试，以下相关问题均未提供逐题答案。
&lt;ol&gt;
&lt;li&gt;LangChain、AutoGen 和 LiteLLM 分别如何使用？&lt;/li&gt;
&lt;li&gt;为什么手写 Agent 而不使用框架？&lt;/li&gt;
&lt;li&gt;MCP 是什么，与 Function Call 有什么区别，是否实践过？&lt;/li&gt;
&lt;li&gt;是否了解 A2A？&lt;/li&gt;
&lt;li&gt;ReAct 如何实现？&lt;/li&gt;
&lt;li&gt;CoT 为什么有效，有什么缺点？&lt;/li&gt;
&lt;li&gt;Prompt Caching 是什么？&lt;/li&gt;
&lt;li&gt;temperature、top-p、top-k 分别是什么，不同场景如何设置？&lt;/li&gt;
&lt;li&gt;RAG 是���么，最难的部分是什么？&lt;/li&gt;
&lt;li&gt;文档切割策略有哪些，如何避免切断语义？&lt;/li&gt;
&lt;li&gt;什么是多路召回？&lt;/li&gt;
&lt;li&gt;文档如何存储，粒度多大，使用什么数据库？&lt;/li&gt;
&lt;li&gt;为什么使用图数据库？&lt;/li&gt;
&lt;li&gt;是否比较过向量数据库，Qdrant 的性能、数据量和瓶颈如何？&lt;/li&gt;
&lt;li&gt;如何减少大模型幻觉？&lt;/li&gt;
&lt;li&gt;微调与 RAG 各有什么优缺点？&lt;/li&gt;
&lt;li&gt;如何量化检索效果和回答效果？&lt;/li&gt;
&lt;li&gt;如何做任务拆分，为什么拆，效果如何提升？&lt;/li&gt;
&lt;li&gt;Text-to-SQL 如何实现并提高准确率？&lt;/li&gt;
&lt;li&gt;为什么以及如何润色 Query？&lt;/li&gt;
&lt;li&gt;Code Generation 如何实现并保证准确性？&lt;/li&gt;
&lt;li&gt;如果重新设计系统会怎么做 Replan？&lt;/li&gt;
&lt;li&gt;Workflow 效果如何量化？&lt;/li&gt;
&lt;li&gt;介绍自己的 Agent 项目。&lt;/li&gt;
&lt;li&gt;长短期记忆如何实现、存储和使用，粒度如何选择？&lt;/li&gt;
&lt;li&gt;Function Call 如何实现？&lt;/li&gt;
&lt;li&gt;Agent 项目最大的难题是什么，如何提升效果并降低延迟？&lt;/li&gt;
&lt;li&gt;端到端延迟如何优化？&lt;/li&gt;
&lt;li&gt;Single-Agent 与 Multi-Agent 有哪些设计方案？&lt;/li&gt;
&lt;li&gt;反思机制如何实现，为什么需要它？&lt;/li&gt;
&lt;li&gt;如何看待当前 LLM 应用的趋势和方向？&lt;/li&gt;
&lt;li&gt;为什么使用 WebRTC，它与 WebSocket 有什么区别？&lt;/li&gt;
&lt;li&gt;如何保证 Agent 服务高可用和稳健？&lt;/li&gt;
&lt;li&gt;LLM 服务并发过高时如何处理？&lt;/li&gt;
&lt;li&gt;如何评估项目的实际落地效果？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可复习问题：Agent 框架与协议如何选型；RAG、Workflow、Memory 与 Reflection 如何量化效果；Agent 服务如何优化延迟、并发与高可用。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;简历岗位材料-6&quot;&gt;简历/岗位材料&lt;/h3&gt;
&lt;h4 id=&quot;企业级-ai-智能体项目-super-agent&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/discuss/882681718157672448&quot;&gt;企业级 AI 智能体项目 Super Agent&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;信号：
&lt;ol&gt;
&lt;li&gt;原帖项目使用 Vue 3、TypeScript、Vite 构建前端，后端采用 Java 17、Spring Boot 3、Spring AI/Spring AI Alibaba，并组合 MySQL、PGVector、Elasticsearch、Neo4j、Redis、MinIO 和 Kafka。&lt;/li&gt;
&lt;li&gt;项目把用户输入处理为五步前置编排、三层执行器路由、三级知识路由和双通道检索，并明确实现歧义澄清、问题改写、Parent-Child 块聚合、RRF、Rerank、证据预算与无证据短路。&lt;/li&gt;
&lt;li&gt;Agent 工程点包括 ReAct 循环、Checkpoint、MCP 动态工具发现、安全沙箱、调用次数上限、工具重试与兜底、三种会话记忆、集群级会话锁及全链路可观测。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可追问方向：前端如何呈现三层执行器、检索证据和工具调用轨迹；Vue 3 客户端如何管理流式对话、Checkpoint 与会话恢复；调用预算、重试、会话锁和无证据短路如何共同避免死循环、重复处理与幻觉。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;2026-07-22-1208--firecrawl-牛客前端-agent-同步&quot;&gt;2026-07-22 12:08 | Firecrawl 牛客前端 Agent 同步&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;本次检索词：&lt;code&gt;site:nowcoder.com 前端 &quot;AI&quot; &quot;一面&quot;&lt;/code&gt;；&lt;code&gt;site:nowcoder.com 前端 &quot;大模型&quot; &quot;二面&quot;&lt;/code&gt;；&lt;code&gt;site:nowcoder.com 前端 &quot;MCP&quot; 面试&lt;/code&gt;；&lt;code&gt;site:nowcoder.com 前端 &quot;工作流&quot; 面试&lt;/code&gt;；&lt;code&gt;site:nowcoder.com &quot;智能体平台&quot; 前端&lt;/code&gt;；&lt;code&gt;site:nowcoder.com &quot;大模型应用&quot; 前端 招聘&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;新增面经：0 条；新增简历/岗位材料：0 条。&lt;/li&gt;
&lt;li&gt;数据来源：本次无新增原帖。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;本次没有新的高相关材料。&lt;/p&gt;
&lt;h2 id=&quot;2026-07-24-1209--firecrawl-牛客前端-agent-同步&quot;&gt;2026-07-24 12:09 | Firecrawl 牛客前端 Agent 同步&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;本次检索词：&lt;code&gt;site:nowcoder.com 前端 &quot;AI&quot; &quot;一面&quot;&lt;/code&gt;；&lt;code&gt;site:nowcoder.com 前端 &quot;大模型&quot; &quot;二面&quot;&lt;/code&gt;；&lt;code&gt;site:nowcoder.com 前端 &quot;MCP&quot; 面试&lt;/code&gt;；&lt;code&gt;site:nowcoder.com 前端 &quot;工作流&quot; 面试&lt;/code&gt;；&lt;code&gt;site:nowcoder.com &quot;智能体平台&quot; 前端&lt;/code&gt;；&lt;code&gt;site:nowcoder.com &quot;大模型应用&quot; 前端 招聘&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;新增面经：2 条；新增简历/岗位材料：0 条。&lt;/li&gt;
&lt;li&gt;数据来源：&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/b98c9db8c09b4120b38aeb3cb65f178c%EF%BC%9Bhttps://www.nowcoder.com/feed/main/detail/844b4fb4257345608054e55b378c2a34%E3%80%82&quot;&gt;https://www.nowcoder.com/feed/main/detail/b98c9db8c09b4120b38aeb3cb65f178c；https://www.nowcoder.com/feed/main/detail/844b4fb4257345608054e55b378c2a34。&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;面经-8&quot;&gt;面经&lt;/h3&gt;
&lt;h4 id=&quot;前端面试5-个高频-ai-问题与前端向回答&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/b98c9db8c09b4120b38aeb3cb65f178c&quot;&gt;前端面试：5 个高频 AI 问题与前端向回答&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;原帖问题与答案：
&lt;ol&gt;
&lt;li&gt;AI 大模型会取代前端吗，前端的核心价值是什么？原帖回答：AI 会重构工作方式，但交互体验、业务理解、性能优化、工程架构、跨端兼容、安全和用户体验仍由前端把控；前端会转向与 AI 协作并聚焦复杂决策。&lt;/li&gt;
&lt;li&gt;前端如何接入大模型，常用方案有哪些？原帖回答：可由后端封装模型接口、前端负责流式渲染与对话交互；也可使用 WebLLM、Transformers.js 在浏览器运行轻量模型，或封装 AI 搜索、智能提示等通用组件；前端还要处理 SSE/WebSocket、上下文、加载态和异常兜底。&lt;/li&gt;
&lt;li&gt;项目中如何用 AI 提升前端开发效率？原帖回答：用于生成基础页面、表单、表格、动画代码，辅助编写正则、工具函数、Hooks 和接口类型，支持代码审查、Bug 定位与性能优化，并把重复工作交给 AI、由开发者把控复杂逻辑和架构。&lt;/li&gt;
&lt;li&gt;前端如何实现 AI 流式对话的打字机效果？原帖回答：使用 SSE 或 Fetch 流式读取后端分块内容，通过 ReadableStream 接收并渲染 chunk，配合防抖、中断、重发、异常重试和虚拟列表处理体验及长对话性能。&lt;/li&gt;
&lt;li&gt;AI 给前端带来了哪些新产品形态？原帖回答：智能表单、AI 设计稿转代码、智能客服或对话助手、语音交互与可视化界面、AI 低代码生成模块，以及按用户行为调整主题、布局和内容的个性化 UI。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可复习问题：
&lt;ol&gt;
&lt;li&gt;AI 大模型会取代前端吗，前端的核心价值是什么？&lt;/li&gt;
&lt;li&gt;前端如何接入大模型，常用方案有哪些？&lt;/li&gt;
&lt;li&gt;项目中如何用 AI 提升前端开发效率？&lt;/li&gt;
&lt;li&gt;前端如何实现 AI 流式对话的打字机效果？&lt;/li&gt;
&lt;li&gt;AI 给前端带来了哪些新产品形态？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;蚂蚁大安全前端一二三面面经&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/844b4fb4257345608054e55b378c2a34&quot;&gt;蚂蚁大安全前端一二三面面经&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;原帖问题与答案：以下相关问题原帖均未提供答案。
&lt;ol&gt;
&lt;li&gt;实习项目中的大模型部分是什么？&lt;/li&gt;
&lt;li&gt;有哪些大模型相关科研或学习经历，做过哪些 AI 和前端结合实践？&lt;/li&gt;
&lt;li&gt;是否做过大模型硬件推理加速，是否训练过模型？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可复习问题：
&lt;ol&gt;
&lt;li&gt;实习项目中的大模型部分是什么？&lt;/li&gt;
&lt;li&gt;有哪些大模型相关科研或学习经历，做过哪些 AI 和前端结合实践？&lt;/li&gt;
&lt;li&gt;是否做过大模型硬件推理加速，是否训练过模型？&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;2026-08-05--牛客秋招提前批同步人工检索&quot;&gt;2026-08-05 | 牛客秋招提前批同步（人工检索）&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;本次检索背景：2026-08-05，正值 2027 届秋招提前批窗口（拼多多 7.6 开、百度 8 月初笔试、快手快Star/联想/米哈游/OPPO 2027 已开）。&lt;/li&gt;
&lt;li&gt;新增面经：10 条；新增简历/岗位材料：7 条。全部带来源链接。&lt;/li&gt;
&lt;li&gt;同步方式说明：与之前 Firecrawl 定时同步不同，本次为人工 web_search + 页面抓取，面经正文以抓取到的完整题目为准。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;面经2026-年-7-8-月最新&quot;&gt;面经（2026 年 7-8 月最新）&lt;/h3&gt;
&lt;h4 id=&quot;吉比特前端实习面经-202679前端工程师精选面经合集内&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/experience/644&quot;&gt;吉比特前端实习面经 2026.7.9&lt;/a&gt;（前端工程师精选面经合集内）&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;原帖问题与答案：以下问题原帖均未提供答案。
&lt;ol&gt;
&lt;li&gt;之前实习/学习中印象深刻的经历&lt;/li&gt;
&lt;li&gt;vue2 和 vue3 响应式的具体区别与原理&lt;/li&gt;
&lt;li&gt;从输入 URL 到浏览器渲染的完整过程&lt;/li&gt;
&lt;li&gt;重绘和重排、以及分别发生在渲染哪个阶段&lt;/li&gt;
&lt;li&gt;避免重绘重排的优化手段&lt;/li&gt;
&lt;li&gt;AI 在工作中怎么运用、如何打造 AI Harness 工程&lt;/li&gt;
&lt;li&gt;Agent 的组成是哪些&lt;/li&gt;
&lt;li&gt;MCP 和 Skill 的区别&lt;/li&gt;
&lt;li&gt;MCP 由哪几部分组成、怎么开发&lt;/li&gt;
&lt;li&gt;场景题：金融网页需要快速更新（不及时更新损失巨大），作为前端怎么做（作者坦言没答好）&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可复习问题：MCP 组成与开发、Agent 组成、AI Harness 工程化叙事。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;快手主站-2026-秋招前端二面发布于-2025-0926-届秋招参考&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/discuss/792499680130174976&quot;&gt;快手主站 2026 秋招前端二面&lt;/a&gt;（发布于 2025-09，26 届秋招参考）&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;原帖问题与答案：以下问题原帖均未提供答案。
&lt;ol&gt;
&lt;li&gt;事件循环相关代码输出分析&lt;/li&gt;
&lt;li&gt;如何判断元素是否在视口&lt;/li&gt;
&lt;li&gt;浏览器 DevTools 中 Performance 面板有什么用&lt;/li&gt;
&lt;li&gt;如何提升首屏加载速度&lt;/li&gt;
&lt;li&gt;Vue 的 nextTick 有什么用&lt;/li&gt;
&lt;li&gt;如何实现缓存&lt;/li&gt;
&lt;li&gt;项目相关&lt;/li&gt;
&lt;li&gt;从零设计一个弹窗组件考虑什么、自定义样式怎么做&lt;/li&gt;
&lt;li&gt;项目中为什么同时用 Vite + Webpack&lt;/li&gt;
&lt;li&gt;函数式/面向对象/过程式编程的区别&lt;/li&gt;
&lt;li&gt;手撕：拍平数组并去重排序、括号匹配&lt;/li&gt;
&lt;li&gt;如何学习新技术栈、印象深刻的学习经历&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可复习问题：组件设计题、构建工具并存的原因、手撕数组与括号匹配。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;菜鸟-26-秋招前端二面纯场景题发布于-2025-11&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/476d32eb03e44d94a38a4452af56b3c2&quot;&gt;菜鸟 26 秋招前端二面（纯场景题）&lt;/a&gt;（发布于 2025-11）&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;原帖问题与答案：以下问题原帖均未提供答案。
&lt;ol&gt;
&lt;li&gt;复杂 B 端「创建物流订单」页面的组件架构与状态管理设计&lt;/li&gt;
&lt;li&gt;拖拽排序、动态增删表单项的实现思路&lt;/li&gt;
&lt;li&gt;「天眼」物流大屏：ECharts/AntV G6/L7 选型 + 海量数据渲染性能&lt;/li&gt;
&lt;li&gt;H5 包裹实时轨迹（地图+时间轴）设计、与高德地图交互&lt;/li&gt;
&lt;li&gt;驿站站长工作台 PC 端首页加载慢的排查优化（考虑 B 端特点）&lt;/li&gt;
&lt;li&gt;高实时性数据更新方案：轮询/WebSocket/SSE 优劣分析&lt;/li&gt;
&lt;li&gt;对菜鸟业务的了解、前端核心技术挑战&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可复习问题：B 端组件架构、可视化大屏选型与性能、实时数据通道选型。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;字节前端风控一面含作者复盘发布于-2026-03&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/03b7222809834f93a95cba1874d47e7d&quot;&gt;字节前端风控一面（含作者复盘）&lt;/a&gt;（发布于 2026-03）&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;原帖问题与答案：以下问题原帖均未提供答案，作者附带答题复盘。
&lt;ol&gt;
&lt;li&gt;盒模型参数、box-sizing&lt;/li&gt;
&lt;li&gt;多列布局用什么渲染方式（grid vs table）&lt;/li&gt;
&lt;li&gt;Tailwind 与传统 CSS 最大区别、tailwind 缺点&lt;/li&gt;
&lt;li&gt;Vue2/Vue3 最大差异（defineProperty/Proxy）&lt;/li&gt;
&lt;li&gt;浏览器缓存工作方式（Cache-Control/ETag、强缓存 vs 协商缓存、304）&lt;/li&gt;
&lt;li&gt;跨域、CORS、同源策略（协议/域名/端口、ACAO/ACAC、Cookie 携带）&lt;/li&gt;
&lt;li&gt;CSRF&lt;/li&gt;
&lt;li&gt;Cookie vs JWT（作者复盘：JWT 是 base64 明文+签名，不是密文）&lt;/li&gt;
&lt;li&gt;EventLoop 宏任务/微任务/rAF + 代码输出题（顺序 1432）&lt;/li&gt;
&lt;li&gt;html 中 async/defer 的含义&lt;/li&gt;
&lt;li&gt;Vite 开发环境为什么快（ESBuild、按需编译）&lt;/li&gt;
&lt;li&gt;Tree Shaking 机制与一票否决情况（CJS 动态导入、全局副作用）&lt;/li&gt;
&lt;li&gt;手撕：多层嵌套数组展平&lt;/li&gt;
&lt;li&gt;base 地、实习时长、到岗时间；反问环节仓促，最终挂了&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;可复习问题：缓存控制头细节、JWT 明文签名机制、Tree Shaking 失效场景。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;前端大厂高频面试真题最常见版发布于-2026-03&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/ce0e2b279eb248b29a23acf73b5096f8&quot;&gt;前端大厂高频面试真题（最常见版）&lt;/a&gt;（发布于 2026-03）&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;原帖按六大类汇总，均未提供答案：JS 基础（闭包/this/原型链/Promise/宏微任务/防抖节流）、浏览器网络（URL 全过程/渲染/HTTP 握手/缓存/跨域）、Vue 响应式与 React Hooks+Fiber、工程化（Webpack/代码分割/tree shaking/LCP/FCP/首屏/移动端适配）、手写（Promise/防抖节流/深拷贝/call-apply-bind/去重 flat）、场景题（定位卡顿白屏/虚拟列表/弹窗组件/监控错误捕获）。&lt;/li&gt;
&lt;li&gt;可复习问题：无新增考点，适合做自检清单。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;拼多多-2027-届校招笔试真题解析开发算法数据分析前端全方向2026-08-03-发布网申至-823-截止&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/discuss/913779912165580800&quot;&gt;拼多多 2027 届校招笔试真题+解析（开发/算法/数据分析/前端全方向）&lt;/a&gt;（2026-08-03 发布，网申至 8.23 截止）&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;原帖为 2027 届笔试真题复盘贴，覆盖前端方向；正文题目以图片呈现，无法从文本逐项核验，标记 uncertain。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;百度-2027-届校招笔试真题解析2026-08-05-当天发布算法后端方向&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/discuss/914426550739533824&quot;&gt;百度 2027 届校招笔试真题+解析&lt;/a&gt;（2026-08-05 当天发布，算法+后端方向）&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;原帖为笔试复盘贴，题目以图片呈现，标记 uncertain。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;agent-开发岗最新学习技术总结全站热榜第-3&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/discuss/914102390276513792&quot;&gt;Agent 开发岗最新学习技术总结&lt;/a&gt;（全站热榜第 3）&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;信号：核心刚需为 Python+FastAPI 搭 Agent 后端、RAG（混合召回/重排/Agentic-RAG/GraphRAG）、LangChain+LangGraph；侧面反映 27 届 AI 岗位能力要求。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;腾讯-workbuddy-实习内幕全站热榜第-10&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/discuss/914112068389769216&quot;&gt;腾讯 WorkBuddy 实习内幕&lt;/a&gt;（全站热榜第 10）&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;信号：腾讯 WorkBuddy 实习的面经、薪资、转正避坑点合集。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;aicoding-真的是万能解法吗2026-07-30&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/discuss/912381116789624832&quot;&gt;AiCoding 真的是万能解法吗？&lt;/a&gt;（2026-07-30）&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;信号：AI 生成代码”看起来对、跑起来不对”的踩坑讨论（业务上下文缺失、字段约束未知、系统上下文不感知），对「面试中如何评价 AI 辅助开发」类必问题有参考价值。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;简历岗位材料2026-年最新&quot;&gt;简历/岗位材料（2026 年最新）&lt;/h3&gt;
&lt;h4 id=&quot;2026-校招新变局如何搞定-ai-筛简历&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/discuss/867127642368065536&quot;&gt;2026 校招新变局：如何搞定 AI 筛简历&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;信号：AI 筛简历（NLP 语义理解/结构化提取）已替代 70% 以上基础人筛；语义理解能区分「优化了接口速度」与「API 延迟从 500ms 降至 50ms」；技术栈需形成闭环（写 RAG 就要有向量库/Embedding/LangChain 配套）；真实性校验成为筛选维度。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;简历模板分享按岗位划分直接套用&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/5b8d2c8430a84cf48263eaf05aace2be&quot;&gt;简历模板分享·按岗位划分直接套用&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;信号：前端版含技术栈写法 + 项目亮点提炼方式；回复「模板」获取。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;长得再好看简历写得烂也是达咩面试官看简历习惯&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/discuss/865910349608906752&quot;&gt;长得再好看，简历写得烂也是达咩（面试官看简历习惯）&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;信号：白底简洁、校招一页（社招最多两页）、不写无关证件/兴趣、实习经历匹配度优先、总分形式自我评价放第二 part。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;2026-大厂校招避坑全攻略&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/discuss/852133440504725504&quot;&gt;2026 大厂校招避坑全攻略&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;信号：招聘节奏提前（7 月提前批）、弱化学历重实战（项目/实习权重超 50%）、投递「精」比「多」重要 10 倍、AI 岗位成主角（文中具体占比为作者个人观察，标记 uncertain）。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;27-届简历求锐评--27-届前端简历求评价&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/d72d79e08f674f10bebedee0caad5156&quot;&gt;27 届简历求锐评&lt;/a&gt; / &lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/a1f777d004434770b52c5baec5ed0de0&quot;&gt;27 届前端简历求评价&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;信号：牛客简历板块当前活跃讨论，可参考别人的被批点与改��。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;2026-年大厂前端面试手写题库已开源23k-star&quot;&gt;&lt;a href=&quot;https://www.nowcoder.com/discuss/862778032979746816&quot;&gt;2026 年大厂前端面试手写题库已开源（2.3k star）&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;信号：JavaScript HOT 100（Promise 系列、flat、call/apply/bind、深拷贝、发布订阅等），中大厂突击用。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;2026-08-05--ai-流式专题sse-解析四层管线参考答案interview-drill-沉淀&quot;&gt;2026-08-05 | AI 流式专题：SSE 解析四层管线（参考答案，interview-drill 沉淀）&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;适用：SSE vs WebSocket、fetch+ReadableStream 自实现解析类问题。百度/快手/美团/阿里云 Agent 面经高频追问点。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;速记&quot;&gt;速记&lt;/h3&gt;
&lt;p&gt;SSE 基于 HTTP 单向推送，EventSource 原生自动重连 + Last-Event-ID 续传，但只能 GET 且不能自定义 header；业界用 fetch + ReadableStream 自解析以支持 POST 与鉴权。解析器按「字节→文本→行→事件」四层管线设计，每层只处理自己那层的不完整状态。&lt;/p&gt;
&lt;h3 id=&quot;四层管线&quot;&gt;四层管线&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;字节→文本&lt;/strong&gt;：TextDecoder 必须传 &lt;code&gt;{ stream: true }&lt;/code&gt;（内部缓存未完成多字节序列，如 &lt;code&gt;你&lt;/code&gt; 的 &lt;code&gt;E4 BD&lt;/code&gt; / &lt;code&gt;A0&lt;/code&gt; 分到两个 chunk 时），否则半个字符变 &lt;code&gt;�&lt;/code&gt; 永久损坏；结束后 &lt;code&gt;decoder.decode()&lt;/code&gt; flush 尾部。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;文本→行&lt;/strong&gt;：&lt;code&gt;buf += decode(u8, {stream:true})&lt;/code&gt; 后 &lt;code&gt;split(&apos; &apos;)&lt;/code&gt;，&lt;strong&gt;最后一段永远留回缓冲&lt;/strong&gt;（可能是半行）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;行→事件&lt;/strong&gt;：状态机维护 field/value，&lt;strong&gt;空行 &lt;code&gt;line===&apos;&apos;&lt;/code&gt; 即事件结束&lt;/strong&gt;，组装派发后重置；兼容 &lt;code&gt;\r &lt;/code&gt;（Windows 服务端，否则事件永不结束）；&lt;code&gt;data:&lt;/code&gt; 多行以 &lt;code&gt; &lt;/code&gt; 拼接；&lt;code&gt;:&lt;/code&gt; 开头为注释行忽略；&lt;code&gt;id:&lt;/code&gt; 更新 lastEventId。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;断线续传&lt;/strong&gt;：lastEventId 是&lt;strong&gt;应用层事件游标，不是 TCP seq 字节偏移&lt;/strong&gt;；EventSource 原生自动携带 Last-Event-ID 重连，fetch 自实现要&lt;strong&gt;手动&lt;/strong&gt;在重试请求头加 &lt;code&gt;Last-Event-ID&lt;/code&gt;，且 lastEventId 必须放解析器作用域（循环外）持久化。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;易错点清单&quot;&gt;易错点清单&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;th&gt;后果&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;decode 忘传 stream:true&lt;/td&gt;&lt;td&gt;半个 UTF-8 字符→&lt;code&gt;�&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;split 后末段不留缓冲&lt;/td&gt;&lt;td&gt;丢行/丢事件&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;不处理 `\r&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&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;4&lt;/td&gt;&lt;td&gt;多 data 行不用&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;拼接&lt;/td&gt;&lt;td&gt;多行 JSON 压扁，parse 失败&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;lastEventId 不持久化&lt;/td&gt;&lt;td&gt;断线后续传失效&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;不检查 res.ok / res.body 为空&lt;/td&gt;&lt;td&gt;4xx 也进流式循环，静默吞错&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;参考实现骨架&quot;&gt;参考实现骨架&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;js&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; decoder&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; TextDecoder&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;utf-8&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; buf &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, field &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, value &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, lastEventId &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; reader&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; res.body.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;getReader&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;while&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  const&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;done&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;value&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;u8&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; reader.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;read&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (done) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;break&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  buf &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; decoder.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;decode&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(u8, { stream: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; lines&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; buf.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;split&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  buf &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; lines.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;pop&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; raw&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; lines) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; line&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; raw.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;replace&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;\r&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (line &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;===&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) { &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (field) { &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;onEvent&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({id: lastEventId, event: field, data: value}); field&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;; value&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;; } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;continue&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (line.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;startsWith&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;:&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;continue&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; i&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; line.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;indexOf&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;:&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; f&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;===&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; line &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; line.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;slice&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, i);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; v&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;===&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ?&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; :&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; line.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;slice&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(i&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;replace&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;^&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (f &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;===&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;data&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) value &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; value &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; value &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; v &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; v;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    else&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (f &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;===&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;id&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) lastEventId &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; v;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    else&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; field &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; f;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;关联&quot;&gt;关联&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;与 [[流式 UI 的数据完成态与播放完成态分离]] 同一思想：解析层处理「不完整状态」，渲染层处理「完成态才升级」。&lt;/li&gt;
&lt;li&gt;关联面经：快手 AI Agent 二面（打字机/流式）、百度一面（SSE 重连/断点续传）、阿里云一面（ReadableStream 跨 chunk 缓冲）。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;流式-markdown-截断渲染参考答案interview-drill-沉淀&quot;&gt;流式 Markdown 截断渲染（参考答案，interview-drill 沉淀）&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;适用：阿里云/得物/MiniMax/快手面经高频题「流式代码块/公式截断如何避免闪烁」。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;结构宣言模板&lt;/strong&gt;：“我会从四个维度处理：渲染分层、升级时机、频率控制、安全。“（开放题先给框架再展开）&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;① 流式期间渲染什么（分层渲染：缓冲区 + 增量解析）&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;原理：Markdown 解析器假设输入完整；未闭合代码块、未配对公式符、未结束链接语法都会误判 → 界面跳变。&lt;/li&gt;
&lt;li&gt;已闭合块：增量解析（remark/markdown-it 流式）正常渲染，输出 AST 增量；未闭合尾部：pending 标记进缓冲区，走轻量层（纯文本 / 简化 pre），不高亮不解析；公式未配对不触发 KaTeX 显示原文。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;② 升级渲染时机（sealed 触发 + 块级 dirty）&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;数据流结束（source sealed）或某块刚闭合时触发升级：应用高亮、公式、链接、表格。&lt;/li&gt;
&lt;li&gt;块级 dirty 标记 + 稳定 key（消息 id + 块序号）：只重渲变化块，避免整条消息重建 DOM 与滚动跳动。&lt;/li&gt;
&lt;li&gt;高亮/公式升级时初始化，先清理旧实例防重复初始化。对应 [[流式 UI 的数据完成态与播放完成态分离]]。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;③ 频率控制（合并提交）&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;不逐 token 触发框架渲染：文本缓冲 + requestAnimationFrame / 16-50ms 合并一次提交。&lt;/li&gt;
&lt;li&gt;memo / 稳定 props 防止无关块重渲染；打字机走轻量 textContent，重量渲染低频；超长文档叠加虚拟列表。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;④ 安全（AI 输出全程视为不可信输入）&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;流式尾部按纯文本（textContent），不用 dangerouslySetInnerHTML；完成态白名单清洗：react-markdown + remark-gfm + 过滤 javascript: 协议、禁 script/自定义标签。&lt;/li&gt;
&lt;li&gt;未闭合代码块 pending 不高亮，避免 highlight.js 对不完整代码抛错或输出错乱。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;边界与易错点&lt;/strong&gt;：升级渲染与打字机动画的节奏分离（完成态才硬切）；高亮重复初始化；超长文档滚动锚定。&lt;/p&gt;
&lt;hr&gt;
&lt;h1 id=&quot;agent-前端--ai-前端-面经专题202608-搜集&quot;&gt;Agent 前端 / AI 前端 面经专题（2026.08 搜集）&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;搜集时间：2026-08-07 | 来源：牛客网面试经验中心 + 掘金/思否/卡码笔记等外部搜索
关联：[[AI-Design-Workflow与Design-System一面题库]]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;米哈游-agent-开发提前批一面20260801&quot;&gt;米哈游 Agent 开发提前批一面（2026.08.01）&lt;/h2&gt;
&lt;p&gt;来源：&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/7b13b3c9e42745819ad822397a115812&quot;&gt;牛客&lt;/a&gt;
岗位方向：Agent 开发 | 浏览 3276 | 偏 workflow agent + RAG&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;平时怎么使用 AI coding？&lt;/li&gt;
&lt;li&gt;如何保证 AI coding 生成代码的质量？&lt;/li&gt;
&lt;li&gt;AI 幻觉产生的原因是什么？&lt;/li&gt;
&lt;li&gt;DeepSeek、OpenAI 这类模型 API 有哪些接口？&lt;/li&gt;
&lt;li&gt;如何解决模型回答的事实性和忠实度问题？&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Skill 和 MCP 有什么区别？&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Skill 有哪些特性？&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;个人 agent 项目深挖（围绕 Agent 的实际流程展开）&lt;/li&gt;
&lt;li&gt;手写题（二选一）：
&lt;ul&gt;
&lt;li&gt;A：Python 实现一个装饰器，用于打印 log&lt;/li&gt;
&lt;li&gt;B：ACM 模式：输入若干组（售价、售出、买入），输出售价最低的前4个，且售出和买入都不为 0&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;总结：项目深挖占比高，Agent 实际流程是核心考点。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;字节剪映-agent-一面20260803&quot;&gt;字节剪映 Agent 一面（2026.08.03）&lt;/h2&gt;
&lt;p&gt;来源：&lt;a href=&quot;https://www.nowcoder.com/discuss/913899716599873536&quot;&gt;牛客&lt;/a&gt;
岗位方向：Agent 开发（剪映）| 浏览 6.2W 创作者 | 前40min 项目拷打 + 后20min 手撕&lt;/p&gt;
&lt;h3 id=&quot;项目深挖极硬核代码级追问&quot;&gt;项目深挖（极硬核，代码级追问）&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Workflow 中的原子性在项目里怎么体现？&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;职责单一：每个节点只做一件事&lt;/li&gt;
&lt;li&gt;执行可回滚：Saga 模式，每个节点配补偿操作&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Workflow 是怎么搭建的？开源还是自研？&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;自研 + 开源组件混搭（Airflow 思想 + 业务层自研）&lt;/li&gt;
&lt;li&gt;节点注册机制：统一接口，启动时动态加载&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Workflow 每个节点是怎么控制的？&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;eval 机制：每个节点执行完过一个 eval 判断&lt;/li&gt;
&lt;li&gt;EvalResult: passed/score/reason/next_action(continue/retry/abort/branch)&lt;/li&gt;
&lt;li&gt;重试策略按失败类型：超时→指数退避；输出质量→调 prompt；依赖服务→检查状态&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Eval 的评判标准和结果怎么影响后续？&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;格式校验（pydantic schema）&lt;/li&gt;
&lt;li&gt;质量评分（BERT-base 或 LLM-as-Judge）&lt;/li&gt;
&lt;li&gt;业务规则（视频时长≤60s、标题非空等硬规则）&lt;/li&gt;
&lt;li&gt;eval 结果作为 feature 输入后续节点&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Workflow 和 Agent 的 Loop 各自怎么设计？业务中的 Workflow 怎么往 Loop 上设计？&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Workflow Loop = 确定性循环（循环次数已知）&lt;/li&gt;
&lt;li&gt;Agent Loop = 不确定性循环（ReAct 模式，Agent 自己决定）&lt;/li&gt;
&lt;li&gt;设计思路：Loop 作为 Workflow 的特殊节点（外层 Workflow 兜底可控，内层 Loop 灵活）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;视频上行 Workflow 优化&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;并行化：转码和封面生成无依赖，并行执行&lt;/li&gt;
&lt;li&gt;异步化 + 事件驱动&lt;/li&gt;
&lt;li&gt;节点粒度超时和降级（LLM 审核慢 → 降级到规则引擎，准确率损失≤3%）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;长任务稳定性 / 微服务设计&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Checkpoint 机制：节点执行前后保存状态到 Redis+DB&lt;/li&gt;
&lt;li&gt;挂了从上一个 checkpoint 恢复&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;sse-流式聊天--agent-工作流面经20260805小厂前端&quot;&gt;SSE 流式聊天 + Agent 工作流面经（2026.08.05，小厂前端）&lt;/h2&gt;
&lt;p&gt;来源：&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/54f708d048c44203a78be3e364190e17&quot;&gt;牛客&lt;/a&gt;
浏览 474 | 关键词：SSE、Agent 工作流编辑器、AI 护城河&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;SSE 流式聊天怎么保证大段文本吐出页面不卡顿，组件重渲染怎么优化？&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;为什么用 monorepo（代码复用，拆分子包）&lt;/li&gt;
&lt;li&gt;Fiber 的引入解决了什么&lt;/li&gt;
&lt;li&gt;React 19 新特性 / Vue 了解程度&lt;/li&gt;
&lt;li&gt;Three.js 离屏渲染？切换场景怎么防止内存泄漏？&lt;/li&gt;
&lt;li&gt;用过 vibe coding 工具吗&lt;/li&gt;
&lt;li&gt;CSS 居中 / flex:1 是哪三个属性缩写 / animation transforming&lt;/li&gt;
&lt;li&gt;宏任务与微任务&lt;/li&gt;
&lt;li&gt;Node.js&lt;/li&gt;
&lt;li&gt;（换面试官）用过什么 vibe coding 工具，怎么保证代码符合要求？&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;如果让你设计一个 AI Agent 的工作流可视化编辑器，你觉得应该怎么设计？&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;前端在 AI 领域的护城河&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;流式返回数据频繁，怎么优化内容&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;接到不明确需求怎么做&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;拼多多-pdd-前端提前批一面--二面20260807&quot;&gt;拼多多 pdd 前端提前批一面 + 二面（2026.08.07）&lt;/h2&gt;
&lt;p&gt;来源：一面 &lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/02ba69c3a222483ca32367a508f27fb4&quot;&gt;牛客&lt;/a&gt; | 二面 &lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/5168933a7e31466e92e899cceb3ffaa8&quot;&gt;牛客&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;一面&quot;&gt;一面&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;项目的虚拟滚动怎么做的&lt;/li&gt;
&lt;li&gt;手写一个 fps 函数&lt;/li&gt;
&lt;li&gt;…（更多项目深挖）&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;二面全程拷打项目不问八股&quot;&gt;二面（全程拷打项目，不问八股）&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;收集类名：&lt;code&gt;[&apos;a&apos;,{&apos;b&apos;:true},{&apos;c&apos;:false},[&apos;d&apos;,[&apos;e&apos;]]] ===&gt; &apos;a b d e&apos;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;写一个倒计时组件&lt;/li&gt;
&lt;li&gt;手写 Promise.all&lt;/li&gt;
&lt;li&gt;首屏优化怎么做的&lt;/li&gt;
&lt;li&gt;三级缓存怎么做的&lt;/li&gt;
&lt;li&gt;图片格式&lt;/li&gt;
&lt;li&gt;懒加载怎么做的&lt;/li&gt;
&lt;li&gt;怎么获取真实用户的首屏时间（非实验室数据）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;有没有沉淀 AI 工作流或者 Skill&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;实习时公司用 AI 有没有做什么限制&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;腾讯-teg-前端一面20260805日常实习&quot;&gt;腾讯 TEG 前端一面（2026.08.05，日常实习）&lt;/h2&gt;
&lt;p&gt;来源：&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/42782e938be141eca32cd8e1b87b0a0c&quot;&gt;牛客&lt;/a&gt; | 浏览 912&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;垂直居中 / CSS 布局（flex、grid）&lt;/li&gt;
&lt;li&gt;BFC 是什么&lt;/li&gt;
&lt;li&gt;闭包、防抖、节流&lt;/li&gt;
&lt;li&gt;代码输出题&lt;/li&gt;
&lt;li&gt;更新代码后用户显示旧的，怎么排查？&lt;/li&gt;
&lt;li&gt;缓存类型有哪些？&lt;/li&gt;
&lt;li&gt;跨域问题&lt;/li&gt;
&lt;li&gt;事件循环&lt;/li&gt;
&lt;li&gt;防抖&lt;/li&gt;
&lt;li&gt;TypeScript 和 JavaScript 的关系&lt;/li&gt;
&lt;li&gt;interface 和 type 的区别&lt;/li&gt;
&lt;li&gt;算法：链表排序&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;字节前端一面20260805&quot;&gt;字节前端一面（2026.08.05）&lt;/h2&gt;
&lt;p&gt;来源：&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/8e43d3496c8b4a57a77eb0348504bd0b&quot;&gt;牛客&lt;/a&gt; | 浏览 717&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;npm 理解：type/module/main/版本号差异&lt;/li&gt;
&lt;li&gt;ESM 和 CJS 区别&lt;/li&gt;
&lt;li&gt;Vite 和 Webpack 差异&lt;/li&gt;
&lt;li&gt;设计模式有哪些&lt;/li&gt;
&lt;li&gt;手撕单例模式、发布订阅模式&lt;/li&gt;
&lt;li&gt;布局 flex&lt;/li&gt;
&lt;li&gt;事件循环&lt;/li&gt;
&lt;li&gt;Nginx 跨域怎么解决&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;蔚来汽车前端一面20260805&quot;&gt;蔚来汽车前端一面（2026.08.05）&lt;/h2&gt;
&lt;p&gt;来源：&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/4c0fea1074d94d1bbbcce1a570e855c2&quot;&gt;牛客&lt;/a&gt; | 提到 Agent&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;自我介绍&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;我看你提到了学习后端和 Agent，你未来更倾向于前端、后端还是算法等等岗位？&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;…（后续问题待展开）&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;字节抖音生活服务前端二面20260805日常实习&quot;&gt;字节抖音生活服务前端二面（2026.08.05，日常实习）&lt;/h2&gt;
&lt;p&gt;来源：&lt;a href=&quot;https://www.nowcoder.com/feed/main/detail/d609e5f2ac7c4b7da982dfd6b471d7c7&quot;&gt;牛客&lt;/a&gt;
纯聊天风格：兴趣爱好、怎么学前端、个人优缺点&lt;/p&gt;
&lt;hr&gt;
&lt;h1 id=&quot;外部搜索agent-开发岗面经汇总2026&quot;&gt;外部搜索：Agent 开发岗面经汇总（2026）&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;以下为 web_search 搜集的外部资源，内容为摘要 + 链接。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;字节-agent-开发四面面经卡码笔记&quot;&gt;字节 Agent 开发四面面经（卡码笔记）&lt;/h2&gt;
&lt;p&gt;来源：&lt;a href=&quot;https://notes.kamacoder.com/interview/llm/20260506bytedance.html&quot;&gt;卡码笔记&lt;/a&gt;
21 道大模型面试题，从 Prompt 到 Agent 到 MCP，四面全覆盖。
考点：ReAct、Function Calling、MCP、RAG、SFT/RLHF/DPO、Agent Skill、混合路由优化。&lt;/p&gt;
&lt;h2 id=&quot;字节腾讯阿里-agent-开发岗面试横评&quot;&gt;字节/腾讯/阿里 Agent 开发岗面试横评&lt;/h2&gt;
&lt;p&gt;来源：&lt;a href=&quot;https://www.faxai.cn/archives/6508&quot;&gt;发现AI&lt;/a&gt; | &lt;a href=&quot;https://dormon.net/posts/2026-06-16-douyin-7640808172391248379/&quot;&gt;dormon.net&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;字节技术密度最高&quot;&gt;字节：技术密度最高&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Agentic CPT → SFT → RL 三阶段训练&lt;/li&gt;
&lt;li&gt;工具调用死循环处理（最大迭代 + 循环模式检测 + 异常回流 + 人工降级）&lt;/li&gt;
&lt;li&gt;React 框架细节&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;腾讯工程协议通才&quot;&gt;腾讯：工程协议通才&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Agent 生态理解广度&lt;/li&gt;
&lt;li&gt;协议标准到工程落地&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;阿里架构设计--业务落地&quot;&gt;阿里：架构设计 + 业务落地&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Tools / Workflow / Agent 三者区别&lt;/li&gt;
&lt;li&gt;架构格局 + 落地细节&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;2026-ai-agent-岗面试三-offer-复盘思否&quot;&gt;2026 AI Agent 岗面试三 offer 复盘（思否）&lt;/h2&gt;
&lt;p&gt;来源：&lt;a href=&quot;https://segmentfault.com/a/1190000047697204&quot;&gt;SegmentFault&lt;/a&gt;
三个岗位：某电商 AI Agent 开发 / 某大模型独角兽 Agent 应用高工 / 某云计算厂商智能应用开发专家&lt;/p&gt;
&lt;h3 id=&quot;一面核心考点&quot;&gt;一面核心考点&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Agent 框架选型（为什么选 LangChain 而非其他）&lt;/li&gt;
&lt;li&gt;工具调用机制设计&lt;/li&gt;
&lt;li&gt;错误处理与重试策略&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;二面核心考点&quot;&gt;二面核心考点&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Agent 记忆系统设计&lt;/li&gt;
&lt;li&gt;多 Agent 协作架构&lt;/li&gt;
&lt;li&gt;评估与调试方法论&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;大厂-agent-面试核知识地图掘金&quot;&gt;大厂 Agent 面试核��知识地图（掘金）&lt;/h2&gt;
&lt;p&gt;来源：&lt;a href=&quot;https://juejin.cn/post/7642596411209662502&quot;&gt;掘金&lt;/a&gt;
五维度考点：推理框架 / Agent 工程 / RAG / 工具调用 / 评估调试
核心问题：你的&lt;/p&gt;
&lt;hr&gt;
&lt;h1 id=&quot;agent-前端面经高频题目--参考答案202608-整理&quot;&gt;Agent 前端面经高频题目 + 参考答案（2026.08 整理）&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;基于米哈游/字节剪映/pdd/腾讯/小厂等真实面经提炼，按维度分组&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;q1skill-和-mcp-有什么区别&quot;&gt;Q1：Skill 和 MCP 有什么区别？&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Skill&lt;/strong&gt;：面向 Agent 的能力封装单元。一个 Skill 包含 system prompt + 工具定义 + 输出格式约束 + 执行策略，Agent 根据任务自动路由到对应 Skill。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;自包含、可组合、有边界&lt;/li&gt;
&lt;li&gt;适用场景：Agent 内部能力复用，团队间共享标准化能力包&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;MCP（Model Context Protocol）&lt;/strong&gt;：面向模型与外部工具/数据源的通信协议。定义了模型如何发现、调用、接收外部服务的标准接口。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;协议层、解耦、生态&lt;/li&gt;
&lt;li&gt;适用场景：跨系统工具集成、第三方服务接入&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;核心区别&lt;/strong&gt;：Skill 是「能力的封装」（what to do），MCP 是「能力的通信协议」（how to connect）。一个 Skill 内部可能通过 MCP 调用外部工具，但 Skill 本身还包含 prompt 策略、eval 判断、输出约束等 MCP 不管的东西。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;q2ai-幻觉产生的原因如何解决事实性和忠实度问题&quot;&gt;Q2：AI 幻觉产生的原因？如何解决事实性和忠实度问题？&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;原因&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;训练数据含错误/过时信息，模型学到的是统计模式而非事实&lt;/li&gt;
&lt;li&gt;自回归生成追求语义连贯而非事实准确，前文偏离后会「自洽地编下去」&lt;/li&gt;
&lt;li&gt;知识截断 + 概率采样引入随机性&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;解决方案&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;RAG&lt;/strong&gt;：检索知识库注入 context，基于真实文档回答&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Grounding&lt;/strong&gt;：强制引用来源，输出标注出处&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Eval + 事后校验&lt;/strong&gt;：NLI 蕴含检测，不达标则重试/拒绝&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CoT + 自我反思&lt;/strong&gt;：先推理再回答&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;结构化输出&lt;/strong&gt;：JSON schema 约束，减少自由发挥&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;多轮验证&lt;/strong&gt;：Agent 调搜索工具交叉验证关键事实&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&quot;q3sse-流式聊天怎么保证大段文本不卡顿组件重渲染怎么优化&quot;&gt;Q3：SSE 流式聊天怎么保证大段文本不卡顿？组件重渲染怎么优化？&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;卡顿根因&lt;/strong&gt;：每个 token 触发 setState → React 重渲染 → 频率极高（每秒几十次）→ 主线程阻塞。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;优化方案&lt;/strong&gt;：&lt;/p&gt;


















































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;层级&lt;/th&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;/td&gt;&lt;td&gt;useRef 累积 + rAF batch flush&lt;/td&gt;&lt;td&gt;不是每 token 触发渲染，攒一批再更新&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;渲染层&lt;/td&gt;&lt;td&gt;React.memo / 局部更新&lt;/td&gt;&lt;td&gt;只重渲染最后一条流式消息，历史消息不动&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;渲染层&lt;/td&gt;&lt;td&gt;直接操作 DOM（逃逸 React）&lt;/td&gt;&lt;td&gt;流式阶段直接 textContent 追加，流结束再同步 state&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Markdown&lt;/td&gt;&lt;td&gt;增量解析（incremark 等）&lt;/td&gt;&lt;td&gt;不全文 re-parse，只解析新增部分&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Markdown&lt;/td&gt;&lt;td&gt;延迟渲染复杂块&lt;/td&gt;&lt;td&gt;代码高亮/表格等流结束再渲染，流中只展示纯文本&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;CSS&lt;/td&gt;&lt;td&gt;content-visibility: auto&lt;/td&gt;&lt;td&gt;历史消息跳过渲染计算&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;React 18&lt;/td&gt;&lt;td&gt;startTransition&lt;/td&gt;&lt;td&gt;markdown 重渲染标记为 transition，用户交互优先&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;进阶&lt;/td&gt;&lt;td&gt;Web Worker&lt;/td&gt;&lt;td&gt;markdown 解析放 Worker，主线程只负责 DOM&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;最佳实践&lt;/strong&gt;：ref 累积 + rAF 批量 flush + 最后一条消息单独组件 + 增量 markdown 解析器。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;q4设计一个-ai-agent-工作流可视化编辑器&quot;&gt;Q4：设计一个 AI Agent 工作流可视化编辑器&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;三层架构&lt;/strong&gt;：&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;UI 层：DAG 画布 + 节点面板 + 属性配置 + 调试面板（React Flow / X6）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;模型层：Workflow DSL（节点/边/条件/循环的 JSON 定义）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;执行层：调度引擎 + eval 网关 + checkpoint + 日志&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;关键设计点&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;节点类型&lt;/strong&gt;：LLM 节点、Tool 节点、条件分支、循环（for/Agent Loop）、人工审核节点&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DSL 设计&lt;/strong&gt;：编辑器操作 → JSON/YAML workflow 定义，可导入导出、版本管理&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;实时调试&lt;/strong&gt;：节点状态可视化（pending/running/success/fail）、断点暂停、手动修改 context&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;变量系统&lt;/strong&gt;：节点间 context 传递，可视化数据流向&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;eval 集成&lt;/strong&gt;：每个节点可配置 eval 规则，不通过时红色标记 + 自动重试/分支&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id=&quot;q5前端在-ai-领域的护城河&quot;&gt;Q5：前端在 AI 领域的护城河&lt;/h2&gt;
&lt;p&gt;核心论点：AI 能生成代码，但不能替代「人机交互的设计与工程」。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;复杂交互体验&lt;/strong&gt;：流式渲染/打字机/token 动画/多模态混排——纯前端工程问题&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;性能与体感&lt;/strong&gt;：60fps/首屏秒开/弱网降级——AI 生成代码难以自动处理&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;可视化编排&lt;/strong&gt;：Agent 工作流编辑器/节点画布/拖拽连线——高度定制 UI 交互&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;端侧 AI&lt;/strong&gt;：WebGPU/WASM 跑小模型/浏览器端 embedding——前端是唯一触达用户设备的层&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;产品感知&lt;/strong&gt;：loading 时机/流式 vs 一次性/错误态展示——产品+设计+前端的交叉领域&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&quot;q6workflow-中的原子性怎么体现怎么回滚&quot;&gt;Q6：Workflow 中的原子性怎么体现？怎么回滚？&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;原子性&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;职责单一：每个节点只做一件事&lt;/li&gt;
&lt;li&gt;状态不可分割：要么完全成功，要么完全失败&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;回滚——Saga 模式&lt;/strong&gt;：每个节点注册 &lt;code&gt;execute()&lt;/code&gt; 和 &lt;code&gt;compensate()&lt;/code&gt;，失败时逆序执行补偿操作。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Checkpoint&lt;/strong&gt;：每个节点成功后保存 checkpoint 到 Redis+DB，挂了从最近 checkpoint 恢复。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;q7workflow-loop-vs-agent-loop怎么融合&quot;&gt;Q7：Workflow Loop vs Agent Loop？怎么融合？&lt;/h2&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;Workflow Loop&lt;/th&gt;&lt;th&gt;Agent Loop&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;确定性&lt;/td&gt;&lt;td&gt;确定的（循环次数/条件明确）&lt;/td&gt;&lt;td&gt;不确定的（Agent 自行决定）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;控制者&lt;/td&gt;&lt;td&gt;编排引擎&lt;/td&gt;&lt;td&gt;Agent 自身（ReAct: think→act→observe）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;终止条件&lt;/td&gt;&lt;td&gt;固定条件/计数器&lt;/td&gt;&lt;td&gt;Agent 判断完成 / max_iterations&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;融合&lt;/strong&gt;：Agent Loop 封装为 Workflow 的特殊节点。外层 Workflow 保证可控（超时兜底、日志可观测），内层 Agent Loop 保证灵活性。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;q8工具调用死循环怎么处理&quot;&gt;Q8：工具调用死循环怎么处理？&lt;/h2&gt;
&lt;p&gt;四道防线：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;最大迭代次数&lt;/strong&gt;：硬上限 max_iterations&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;循环模式检测&lt;/strong&gt;：连续 N 次相同 tool + 相同参数 → 强制退出&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;异常回流&lt;/strong&gt;：把状态 + 历史 action 重新交给 Agent，注入提示「你陷入了循环，换一种方式」&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;人工降级&lt;/strong&gt;：异常回流后仍循环 → 暂停通知人工介入&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id=&quot;q9eval-机制怎么设计&quot;&gt;Q9：eval 机制怎么设计？&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;三类评判标准&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;格式校验：Pydantic / JSON Schema（字段是否齐全）&lt;/li&gt;
&lt;li&gt;质量评分：LLM-as-Judge / BERT 打分（score ≥ 阈值）&lt;/li&gt;
&lt;li&gt;业务规则：硬编码（duration ≤ 60s / title not empty）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;结果影响后续&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;passed=True → 继续&lt;/li&gt;
&lt;li&gt;retry → 调整 prompt 后重试（最多 3 次）&lt;/li&gt;
&lt;li&gt;branch → 走备选路径&lt;/li&gt;
&lt;li&gt;abort → 终止 + 告警&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;进阶&lt;/strong&gt;：eval score 作为 feature 注入下游节点 context，后续节点感知「前序质量」并调整策略。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;q10流式返回数据频繁更新的工程优化补充&quot;&gt;Q10：流式返回数据频繁更新的工程优化（补充）&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;双缓冲&lt;/strong&gt;：实时追加 buffer + 已渲染快照，rAF 时 swap&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Web Worker&lt;/strong&gt;：markdown 解析放 Worker&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;content-visibility: auto&lt;/strong&gt;：历史消息跳过渲染&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;React 18 startTransition&lt;/strong&gt;：非紧急渲染让位用户交互&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&quot;q11deepseek--openai-模型-api-有哪些接口&quot;&gt;Q11：DeepSeek / OpenAI 模型 API 有哪些接口？&lt;/h2&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;/chat/completions&lt;/td&gt;&lt;td&gt;对话补全（tools/stream）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;/embeddings&lt;/td&gt;&lt;td&gt;文本向量化&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;/images/generations&lt;/td&gt;&lt;td&gt;图片生成&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;/audio/transcriptions&lt;/td&gt;&lt;td&gt;语音转文字&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;/audio/speech&lt;/td&gt;&lt;td&gt;文字转语音&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;/files&lt;/td&gt;&lt;td&gt;文件管理&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;/fine-tuning/jobs&lt;/td&gt;&lt;td&gt;微调任务&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;/assistants&lt;/td&gt;&lt;td&gt;Assistant API&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;/responses&lt;/td&gt;&lt;td&gt;Responses API（新，支持 tool + 上下文）&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;DeepSeek 特色：兼容 OpenAI 格式 + FIM 补全 + reasoning_content 字段（思维链）。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;q12如何保证-ai-coding-生成代码的质量&quot;&gt;Q12：如何保证 AI Coding 生成代码的质量？&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Prompt 工程&lt;/strong&gt;：明确约束写入 system prompt（语言/框架/风格/测试）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Context 管理&lt;/strong&gt;：只喂相关代码文件，减少噪声&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;生成后校验&lt;/strong&gt;：ESLint/TypeCheck + 生成测试跑一遍 + diff 过 CI&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;人工审核&lt;/strong&gt;：AI 生成 → 人 review → merge&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;限制作用域&lt;/strong&gt;：每次只生成一个函数/组件&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;沉淀 Rule&lt;/strong&gt;：团队编码规范写成 AI 可读的 rule file（cursor rules 等）&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id=&quot;q13有没有沉淀-ai-工作流或者-skillpdd-二面原题&quot;&gt;Q13：有没有沉淀 AI 工作流或者 Skill？（pdd 二面原题）&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;答题思路&lt;/strong&gt;（结合自身经验）：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;把常用 Agent 操作封装为 Skill（如：代码审查 Skill、部署 Skill、文档生成 Skill）&lt;/li&gt;
&lt;li&gt;每个 Skill 有标准接口：system prompt + tool list + output schema + eval 规则&lt;/li&gt;
&lt;li&gt;工作流沉淀：将多 Skill 编排为可复用的 workflow template（如：PR 流程 = lint Skill → review Skill → test Skill → merge）&lt;/li&gt;
&lt;li&gt;版本管理：Skill 有版本号，团队内共享 registry&lt;/li&gt;
&lt;li&gt;效果度量：记录每个 Skill 的成功率/耗时/token 消耗，持续优化&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>Javascript</category><category>Typescript</category><category>Nodejs</category><category>面试</category></item><item><title>计算机网络 谢希仁</title><link>https://feichuans.com/blogs/05-archive/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C-%E8%B0%A2%E5%B8%8C%E4%BB%81/</link><guid isPermaLink="true">https://feichuans.com/blogs/05-archive/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C-%E8%B0%A2%E5%B8%8C%E4%BB%81/</guid><description>互联网的重要基本特点 什么样的网络是计算机网络 Internet 和小写的 internet 的区别 互联网的组成 互联网中核心部分中起特殊作用的是路由器 作用是分组转发 三种交换技术与特点 物理层 物理层的主要作用 : 透明的传输比特流 确定与传输媒体接口有关的特性 计算机网络性能指标 速率 速率指的是本…</description><pubDate>Mon, 15 Sep 2025 08:07:58 GMT</pubDate><content:encoded>&lt;p&gt;互联网的重要基本特点
什么样的网络是计算机网络
Internet 和小写的 internet 的区别
互联网的组成
互联网中核心部分中起特殊作用的是路由器
作用是分组转发
三种交换技术与特点&lt;/p&gt;
&lt;h1 id=&quot;物理层&quot;&gt;物理层&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;物理层的主要作用&lt;/strong&gt;: 透明的传输比特流&lt;/p&gt;
&lt;p&gt;确定与传输媒体接口有关的特性&lt;/p&gt;
&lt;h2 id=&quot;计算机网络性能指标&quot;&gt;计算机网络性能指标&lt;/h2&gt;
&lt;h3 id=&quot;速率&quot;&gt;速率&lt;/h3&gt;
&lt;p&gt;速率指的是本地机器端口能够发送数据的单位时间. 比如说 Mac 的雷电接口, 可以传输 &lt;code&gt;30Gbps&lt;/code&gt; 的数据.
速率的单位是&lt;/p&gt;
&lt;h3 id=&quot;带宽&quot;&gt;带宽&lt;/h3&gt;
&lt;p&gt;带宽通常有两种意义&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;某个信号具有的频宽宽度. 信号的带宽是指信号所包含的各种不同的频率成分所占据的频率范围&lt;/li&gt;
&lt;li&gt;表示网络中某通道传送数据的能力, 即表示&lt;strong&gt;单位时间&lt;/strong&gt;内网络中某信道所能通过的 &lt;strong&gt;最高数据率&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;在计算机网络中指的带宽通常是指第二种, &lt;strong&gt;单位是 &lt;code&gt;bit/s&lt;/code&gt;&lt;/strong&gt; 也就是 “比特每秒”&lt;/p&gt;
&lt;p&gt;数字数据转数字信号称为&lt;strong&gt;编码&lt;/strong&gt;
数字数据转为模拟信号称为&lt;strong&gt;调制&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;常用的编码方法&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;曼彻斯特编码计算方式: 标记 &lt;code&gt;位中心&lt;/code&gt; 的向上/向下曲线. 上 0 下 1&lt;/li&gt;
&lt;li&gt;差分曼彻斯特编码计算方式: 标记 &lt;code&gt;位开始边界&lt;/code&gt; 的跳变, 有跳变表示 0, 无跳变表示 1.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;基本的带通调制方法&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;将各种数字基带信号转换成适于信道传输的数子频带信号的过程称为调整 (modulation)&lt;/li&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;常用的信道复用技术&quot;&gt;常用的信道复用技术&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;频分复用 (FDM): 所有用户在同样的时间占据不同的带宽资源&lt;/li&gt;
&lt;li&gt;时分复用（TDM): 所有用户在不同时间占据同样的频带宽度（分时不分频）&lt;/li&gt;
&lt;li&gt;统计时分复用 (Statistic TDM): 改进的时分复用, 能&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id=&quot;网络层&quot;&gt;网络层&lt;/h1&gt;
&lt;h2 id=&quot;46-互联网的路由选择协议&quot;&gt;4.6 互联网的路由选择协议&lt;/h2&gt;
&lt;h3 id=&quot;461-有关路由选择的几个概念&quot;&gt;4.6.1 有关路由选择的几个概念&lt;/h3&gt;
&lt;h4 id=&quot;1-理想的路由算法&quot;&gt;1. 理想的路由算法&lt;/h4&gt;
&lt;p&gt;路由选择协议的核心就是路由算法&lt;/p&gt;
&lt;p&gt;理想的路由选择算法的特点:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;算法必须是正确和完整的。正确: 沿着各路由表所指引的路由, 分组一定能够达到目的网络和目的主机。&lt;/li&gt;
&lt;li&gt;算法在计算上简单。&lt;/li&gt;
&lt;li&gt;算法能够自适应通信量和网络拓扑的变化。即自适应性, 在网络中的通信量发生变化时, 算法能够自适应的改变路由以实现各链路的负载均衡。&lt;/li&gt;
&lt;li&gt;算法应具有稳定性。在网络通信量和网络拓扑逐渐稳定的情况下, 路由算法应收敛于一个可接受的解, 而不应使得路由不停地变化。&lt;/li&gt;
&lt;li&gt;算法应该是公平的。即平等的处理每个分组 (除去少数优先级)&lt;/li&gt;
&lt;li&gt;算法应该是最佳的。应当能够找出最好的路由, 使分组平均时延最小, 网络吞吐量最大。但相对于网络的可靠性来说, 往往应该舍去一定的性能而保持稳定。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;从路由算法能否自适应来划分, 只有两大类。即 &lt;strong&gt;静态路由选择策略&lt;/strong&gt; 与 &lt;strong&gt;动态路由选择策略&lt;/strong&gt;。静态路由选择也叫 &lt;strong&gt;非自适应路由选择&lt;/strong&gt;、动态路由选择也叫 &lt;strong&gt;自适应路由选择&lt;/strong&gt;。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;静态路由选择（对于简单的小网络, 完全可以采用静态路由, 用人工配置每一条）
&lt;ol&gt;
&lt;li&gt;优点: 简单和开销小&lt;/li&gt;
&lt;li&gt;缺点: 不能及时适应网络的变化。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;动态路由选择（适用于复杂的大网络）
&lt;ol&gt;
&lt;li&gt;优点: 能够较好的适应网络状态的变化&lt;/li&gt;
&lt;li&gt;缺点: 配置较为复杂, 开销较大&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&quot;2-分层次的路由选择协议&quot;&gt;2. 分层次的路由选择协议&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;互联网(Internet)&lt;/strong&gt; 采用的路由选择协议主要是自适应的、分布式路由选择协议。由于以下两个原因, 互联网采用分层次的路由选择协议:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;互联网的规模非常大。如果让所有的路由器知道所有的网络应该怎样到达, 则路由表将非常大。而路由之间交换信息的带宽就会让互联网的通信链路饱和。&lt;/li&gt;
&lt;li&gt;许多单位不希望外界了解自己单位网络的布局袭击和本部门采用的路由选择协议。但同时希望连接到互联网上&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;为此, 可以把整个互联网划分为许多较小的自治系统 (autonomous system), 一般记为 AS&lt;/p&gt;
&lt;p&gt;AS 是在单一技术管理下的许多网络、IP 地址以及路由器, 而这些路由器使用一种自治系统内部的路由选择协议。&lt;strong&gt;每一个 AS 对其他 AS 表现出的是一个单一和一致的路由选择协议策略&lt;/strong&gt;。这样, 互联网就把路由选择协议分为两大类, 即:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;内部网关协议 IGP&lt;/strong&gt;(Interior gateway protocol), 即在一个自治系统内部使用的路由选择协议, 这与互联网中的&lt;strong&gt;其他自治系统选择什么路由选择协议无关&lt;/strong&gt;, 目前这类路由选择协议使用的最多是是 &lt;strong&gt;RIP&lt;/strong&gt; 和 &lt;strong&gt;OSRF&lt;/strong&gt;协议（IS-IS 也有）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;外部网关协议 EGP&lt;/strong&gt;(External Gateway Protocol), 若源主机和目的主机处在不同的 AS 中, 那么在不同自治系统 AS 之间的路由选择就需要使用外部网关协议 EGP, 目前使用最多的外部网关协议是 BGP 4 的版本。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;两个自治系统之间的路由选择也叫做 &lt;strong&gt;域间路由选择(interdomain routing)&lt;/strong&gt;, 而在自治系统内部的路由选择叫做 &lt;strong&gt;域内路由选择(intradomain routing)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.feichuans.com/file/1762245339696_20251104163526.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;462-内部网关协议-rip&quot;&gt;4.6.2 内部网关协议 RIP&lt;/h3&gt;
&lt;h4 id=&quot;1-rip-协议的工作原理&quot;&gt;1. RIP 协议的工作原理&lt;/h4&gt;
&lt;p&gt;RIP（Routing Information Protocol） 是内部网关协议 (IGP) 中最先得到广泛应用的协议, 中文译名是
&lt;strong&gt;路由信息协议&lt;/strong&gt;。RIP 是一种分布式的 &lt;strong&gt;基于距离向量的路由选择协议&lt;/strong&gt;, 最大的优点是简单。&lt;/p&gt;
&lt;p&gt;RIP 协议要求网络中的每一个路由器都要维护从 &lt;strong&gt;它自己&lt;/strong&gt; 到其他每一个目的网络的距离记录（&lt;strong&gt;距离向量&lt;/strong&gt;）。定义如下:&lt;/p&gt;
&lt;p&gt;从一路由器到直接连接的网络的距离为 1. 从一主机非直接连接的网络的距离定义为所经过的路由器数 &lt;code&gt;+1&lt;/code&gt; 。 &lt;code&gt;+1&lt;/code&gt; 是因为达到目的网络后就进行直接交付。而到直接连接的网络的距离已经定义为 1.&lt;/p&gt;
&lt;p&gt;距离称为“跳数”（hop count）, 每经过一个网络, 跳数就 &lt;code&gt;+1&lt;/code&gt;, &lt;strong&gt;显然, 一个分组经过的网络数越少, 那么这条路由就越好&lt;/strong&gt;, 即越短越好。
RIP 允许一条路径最多只能包含 &lt;code&gt;15&lt;/code&gt; 个网络, 因此, 当距离等于
&lt;code&gt;16&lt;/code&gt; 时即相当于不可达。可见 RIP 只适用于小型互联网。&lt;/p&gt;
&lt;p&gt;RIP 不能在两个网络之间同时使用多条路由。RIP 选择一条具有最少网络数的路由（即最短路由）, 哪怕还存在另一条高速（低时延）但网络数较多的路由&lt;/p&gt;
&lt;p&gt;RIP 协议与下一节的 OSPF 协议, 都是&lt;strong&gt;分布式路由协议&lt;/strong&gt;。
他们的共同特点就是每一个路由器都要不断地和其他一些路由器交换路由信息。&lt;/p&gt;
&lt;p&gt;我们一定要弄清以下三个要点:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;和哪些路由器交换交换信息?&lt;/li&gt;
&lt;li&gt;交换什么信息?&lt;/li&gt;
&lt;li&gt;在什么时候交换信息&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;RIP 协议的特点是:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;仅和相邻路由器交换信息&lt;/strong&gt;。如果两个路由器之间通信不经过另一个路由器, 那么这两个路由器就是相邻的。RIP 协议不与不相邻的路由器交换信息。&lt;/li&gt;
&lt;li&gt;路由器交换的信息是&lt;strong&gt;本路由器当前所知道的全部信息, 即自己现在的路由表&lt;/strong&gt;。也就是说, 交换的信息是:“我到本自治系统中所有网络的（最短）距离, 以及到每个网络应经过的下一跳路由器”。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;按固定的时间间隔&lt;/strong&gt;交换路由信息, 例如, 每隔三十秒。然后路由器根据收到的路由信息更新路由表。当网络拓普发送变化时, 路由器也及时向相邻路由器通告变化后的路由信息。网络中的主机虽然也运行 RIP, 但只被动的接受路由器发来的路由信息。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;在路由器刚刚开始工作时, 路由表是空的。然后路由器就检查各个端口, 得到直接相连的几个网络的距离（1）. 接着, 每个路由器也只和&lt;strong&gt;数目有限&lt;/strong&gt;（较少）的相邻路由器交换并更新路由信息。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://s2.loli.net/2025/11/04/k6ux19wERMT3gmr.png&quot; alt=&quot;image.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;看起来协议 RIP 有些奇怪，因为“我的路由表中的信息要依赖于你的，面你的信息又依赖于我的。”然而事实证明，通过这样的方式一一“我告诉别人些信息，而别人又告诉我一些信息。我再把我知道的更新后的信息告诉别人，别人也这样把更新后的信息再告诉我”，最后在自治系统中所有的节点都得到了正确的路由选择信息。在一般悄况下，协议 RTP 可以收敛，并且过程也较快。&lt;strong&gt;“收敛”就是在自治系统中所有的节点都得到正确的路由选择信息的过程&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;路由表中最主要的信息就是: 本路由器到某个网络的最短距离, 以及应经过的下一条的地址。路由表更新的原则就是找出每个目的网络的&lt;strong&gt;最短距离&lt;/strong&gt;。这种更新算法又称为 &lt;strong&gt;距离向量算法&lt;/strong&gt;。下面是 RIP 使用的距离向量算法定义:&lt;/p&gt;
&lt;h4 id=&quot;2-距离向量算法&quot;&gt;2. 距离向量算法&lt;/h4&gt;
&lt;p&gt;对 &lt;strong&gt;每一个相邻路由器发送过来的&lt;/strong&gt; RIP 报文, 执行以下步骤&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;将地址为 &lt;code&gt;X&lt;/code&gt; 的相邻路由器发来的 RIP 报文, 修改此报文中的&lt;strong&gt;所有项目&lt;/strong&gt;: &lt;code&gt;把 &apos;下一跳&apos;字段中的地址都改为 X,并把所有距离字段+1 &lt;/code&gt;。每个项目都有三个关键数据, 即: 目的网络 Net, 距离 &lt;code&gt;d&lt;/code&gt;, 下一跳路由器 &lt;code&gt;X&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;对修改后的 RIP 报文中的每一个项目, 进行
&lt;ol&gt;
&lt;li&gt;若原来的路由表中没有目的网络 &lt;code&gt;Net&lt;/code&gt;, 则把该项目添加到路由表中&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot; id=&quot;user-content-fnref-1&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;若在, 则查看本路由器中下一跳路由器的地址。
&lt;ol&gt;
&lt;li&gt;若下一跳路由器地址是 &lt;code&gt;X&lt;/code&gt; ,则把收到的项目替换原路由表中的项目&lt;sup&gt;&lt;a href=&quot;#user-content-fn-2&quot; id=&quot;user-content-fnref-2&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;若不是（即 &lt;code&gt;到目的网络 Net,但下一跳路由器不是 X&lt;/code&gt;）,
&lt;ol&gt;
&lt;li&gt;若该项目的距离 &lt;code&gt;d&lt;/code&gt; 小于路由表中的距离, 则进行更新。&lt;sup&gt;&lt;a href=&quot;#user-content-fn-3&quot; id=&quot;user-content-fnref-3&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;否则什么都不做&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;若 3 分钟还没有收到相邻路由器的更新路由表, 则把此相邻路由器标记为不可达路由, 即把距离设置为 16&lt;/li&gt;
&lt;li&gt;返回。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://img.feichuans.com/file/1762302395378_20251105082619.png&quot; alt=&quot;image.png|725&quot;&gt;RIP 协议让一个自治系统中的所有路由器和自己相邻的路由器定期交换信息, 并不断更新路由表。使得 &lt;strong&gt;每一个路由器到每一个目的网络的路由都是最短的&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.feichuans.com/file/1762302949143_20251105083534.png&quot; alt=&quot;image.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;RIP 报文由首部和路由部分组成。在路由部分要填入 &lt;strong&gt;自治系统号 ASN&lt;/strong&gt;(Autonomous System Number), 这是使 RIP 有可能收到本自治系统外的路由选择信息。还要指出目的网络地址（包括子网掩码）、下一跳路由器地址以及到此网络的距离。一个 RIP 报文最多有 &lt;code&gt;25&lt;/code&gt; 个路由, 如超过, 必须再用一个 RIP 报文来传送。&lt;/p&gt;
&lt;h4 id=&quot;3-坏消息传播的慢&quot;&gt;3. 坏消息传播的慢&lt;/h4&gt;
&lt;p&gt;RIP 存在的一个问题是当网络出现故障时, 要经过较长的时间才能将此信息传送到&lt;strong&gt;所有的路由器&lt;/strong&gt;。你来我往, 直到 16&lt;/p&gt;
&lt;h3 id=&quot;463-内网网关协议-ospf&quot;&gt;4.6.3 内网网关协议 OSPF&lt;/h3&gt;
&lt;h4 id=&quot;1-ospf-协议的基本特点&quot;&gt;1. OSPF 协议的基本特点&lt;/h4&gt;
&lt;p&gt;OSPF (Open Shortest Path First), &lt;strong&gt;开放最短路径优先&lt;/strong&gt;, 它是为了克服 RIP 的缺点而在 1989 年提出来的。OSPF 的原理很简单, 但实现较为复杂。
Open 表示 OSPF 不受某一厂家限制, 而是公开发表的。“最短路径优先”是因为使用 &lt;code&gt;Dijkstra&lt;/code&gt; 提出的&lt;strong&gt;最短路径算法 SPF&lt;/strong&gt;。现在使用的 OSPF 协议是第二个版本&lt;/p&gt;
&lt;p&gt;OSPF 最主要的特征就是使用了 &lt;strong&gt;链路状态协议&lt;/strong&gt;（link state protocol）,
OSPF 的特点是:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;向本自治系统中的所有路由器发送信息&lt;/strong&gt;。这里使用的是 &lt;strong&gt;泛洪法&lt;/strong&gt; （向所有相邻的路由器发送信息, 收到消息的相邻路由器又给自己的相邻路由器发送此信息（但不发给刚刚发来信息的路由器））（一传十, 十传百）。这样整个区域内所有路由器都得到了这个信息的副本。&lt;/li&gt;
&lt;li&gt;发送的信息是与本路由器 &lt;strong&gt;相邻的所有路由器的链路状态&lt;/strong&gt;, 但是这只是路由器所知道的 &lt;strong&gt;部分信息&lt;/strong&gt;。所谓的 “链路状态” 就是说明本路由器都和那些路由器相邻, 以及该链路的 “&lt;strong&gt;度量&lt;/strong&gt;”（metric）。 OSPF 将这个度量用来表示费用、距离、时延、带宽, 等等。这些都由网络管理人员来决定, 因此较为灵活。有时为了方便就称这个度量为 “&lt;strong&gt;代价&lt;/strong&gt;”。应当注意, 对于 RIP 协议, 发送的信息是 “到所有网络的距离和下一跳路由器”。&lt;/li&gt;
&lt;li&gt;当链路状态发送变化或每隔一段时间（如 30 分钟）, 路由器向所有路由器用 &lt;code&gt;泛洪法&lt;/code&gt; 发送链路状态信息。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;由于各路由器之间频繁的交换链路状态信息, 因此所有的路由器最终都能建立一个&lt;strong&gt;链路状态数据库&lt;/strong&gt;（link-state database）, 这个数据库实际上就是 &lt;strong&gt;全网的拓扑结构图&lt;/strong&gt;（有点像数据结构中图的二维数组表示法）。这个拓扑结构图在全网范围内是&lt;strong&gt;一致的&lt;/strong&gt;(这也称为 &lt;strong&gt;链路状态数据库的同步&lt;/strong&gt;)。因此, 每一个路由器都知道全网共有多少个路由器, 以及哪些路由器是相连的, 其代价是多少, 等等。每个路由器使用链路状态数据库中的数据, 构造出自己的路由表（比如 Dijkstra 的最短路径算法）。相反的, RIP 协议虽然知道所有的网络的距离以及下一条路由器, 但却 &lt;strong&gt;不知道全网的拓扑结构&lt;/strong&gt;（只有到了下一个路由器, 才能知道怎么走）。&lt;/p&gt;
&lt;p&gt;OSPF 的链路状态数据库能够较快地进行更新。OSPF 的更新过程收敛得块是其中药有点&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;泛洪法&lt;/strong&gt;：保证链路状态广告在全网几乎同步地传播，是 OSPF 快速更新的核心。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;触发式增量更新&lt;/strong&gt;：仅在链路变化时立刻泛洪最新 LSA，避免周期性的全量刷新。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;序列号/寿命/校验&lt;/strong&gt;：确保只保留最新、正确的信息，防止冗余与冲突。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;分层（Area）&lt;/strong&gt;：限制泛洪范围，进一步提升更新效率。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;可靠的传输与抑制机制&lt;/strong&gt;：防止广播风暴，同时保证每台路由器都能收到最新 LSA。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;为了使 OSPF 能够用于规模很大的网络, OSPF 将一个自治系统再划分为若干个更小的范围, 叫做 &lt;strong&gt;区域（area）&lt;/strong&gt;。每一个区域都有一个 32 位的区域标识符（点分十进制）。一个区域的路由器最好不要超过 200 个
&lt;img src=&quot;https://s2.loli.net/2025/11/05/Ky9b8wGouFjszpe.png&quot; alt=&quot;image.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;划分区域的好处:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;泛洪法交换链路状态信息的范围局限于每一个区域, 减少通信量&lt;/li&gt;
&lt;li&gt;对区域进行封装, 每一个区域内部的路由器都只知道本区域的完整网络拓扑, 而不必知道其他区域的网络拓扑情况, 而交由其中一个连接另一个区域的路由器来处理。&lt;/li&gt;
&lt;li&gt;OSPF 采用 &lt;strong&gt;层次结构的区域划分&lt;/strong&gt;, 在上层的区域叫做 &lt;strong&gt;主干区域（backbone area）&lt;/strong&gt;。主干区域的标识符规定为 &lt;code&gt;0.0.0.0&lt;/code&gt;。主干区域的作用是用来连通下层的区域。&lt;/li&gt;
&lt;li&gt;从其他区域来的信息都由 &lt;strong&gt;区域边界路由器（area border router）&lt;/strong&gt; 进行概括。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;在上图中, 路由器 &lt;code&gt;R3,4,7&lt;/code&gt; 都是区域边界路由器, 显然, 每一个区域都应当至少有一个 &lt;code&gt;区域边界路由器&lt;/code&gt;。
在主干区域的路由器叫做 &lt;strong&gt;主干路由器(backbone router)&lt;/strong&gt;, 如 &lt;code&gt;R3,4,5,6,7&lt;/code&gt;. 一个主干路由器可以同时是区域边界路由器, 如 &lt;code&gt;R3,4,7&lt;/code&gt;。在主干区域内还要有一个路由器专门和&lt;strong&gt;本自治系统外&lt;/strong&gt;的其他自治洗头交换路由信息。这样路由器叫做 &lt;strong&gt;自治系统边界路由器&lt;/strong&gt;, 如 &lt;code&gt;R6&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;除了以上几个基本特点以外, OSPF 还具有下列的一些特点:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;OSPF 允许管理员给每条路由指派不同的代价。例如, 高带宽的卫星链路可以设置为较低的代价, 但对于时延敏感的业务就可以设置为非常高的代价。因此, &lt;strong&gt;OSPF 对于不同类型的业务可计算出不同的路由&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;若同一个目的网络有多条相同代价的路径, 那么可以将通信量分配给这几条路由。这叫做多路径间的负载均衡 (load balancing)
&lt;img src=&quot;https://s2.loli.net/2025/11/05/MRy7OoDUYJEsp6i.png&quot; alt=&quot;image.png|575&quot;&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&quot;2-ospf-的五种分组类型&quot;&gt;2. OSPF 的五种分组类型&lt;/h4&gt;
&lt;p&gt;OSPF 共有以下五种分组类型:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;问候 (hello) 分组, 用来发现和维持邻站的可达性。&lt;/li&gt;
&lt;li&gt;数据库描述（Database Description）分组, 向邻站给出自己的&lt;strong&gt;链路状态数据库&lt;/strong&gt;中的所有链路状态项目的摘要信息。&lt;/li&gt;
&lt;li&gt;链路状态请求（Link State Request）分组, 向对方请求发送某些链路状态项目的详细信息。（得到上一步的摘要后）&lt;/li&gt;
&lt;li&gt;链路状态更新（Link State Update）分组, 用泛洪法对全网更新链路状态。这种分组是最复杂的, 也是 OSPF 协议最核心的部分。&lt;/li&gt;
&lt;li&gt;链路状态确认（Link State Acknowledgedgment）分组, 用来对链路更新分组的确认。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://s2.loli.net/2025/11/05/czLfTIs8kvnwrbl.png&quot; alt=&quot;image.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;省略一些… 太多了 （我靠）&lt;/p&gt;
&lt;section data-footnotes=&quot;&quot; class=&quot;footnotes&quot;&gt;&lt;h2 class=&quot;sr-only&quot; id=&quot;footnote-label&quot;&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li id=&quot;user-content-fn-1&quot;&gt;
&lt;p&gt;表明这是一个新的目的网络 &lt;a href=&quot;#user-content-fnref-1&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-2&quot;&gt;
&lt;p&gt;用新的路由信息替换掉旧的路由信息 &lt;a href=&quot;#user-content-fnref-2&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 2&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-3&quot;&gt;
&lt;p&gt;若新的路由距离大于原来的, 则会花费更多时间, 所以只更新更短的 &lt;a href=&quot;#user-content-fnref-3&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 3&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content:encoded><category>计算机网络</category></item><item><title>Linux学习</title><link>https://feichuans.com/blogs/05-archive/linux%E5%AD%A6%E4%B9%A0/</link><guid isPermaLink="true">https://feichuans.com/blogs/05-archive/linux%E5%AD%A6%E4%B9%A0/</guid><description>短命令可组合 长命令不可组合 [当前用户名@主机名 当前路径]$ $ 普通用户 root 用户 在 Shell 中 . 代表当前目录, 在操作当前目录下的文件时非常好用 cp i(强制覆盖) /etc/NetworkManager/conf . 移动至当前目录 chmod or option : [u(us…</description><pubDate>Mon, 08 Sep 2025 07:36:55 GMT</pubDate><content:encoded>&lt;p&gt;&lt;code&gt;-&lt;/code&gt; 短命令可组合
&lt;code&gt;--&lt;/code&gt; 长命令不可组合&lt;/p&gt;
&lt;p&gt;&lt;code&gt;[当前用户名@主机名 当前路径]$&lt;/code&gt;
&lt;code&gt;$&lt;/code&gt; 普通用户
&lt;code&gt;#&lt;/code&gt; root 用户&lt;/p&gt;
&lt;p&gt;在 Shell 中 &lt;code&gt;.&lt;/code&gt; 代表当前目录, 在操作当前目录下的文件时非常好用&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;cp -i(强制覆盖) /etc/NetworkManager/conf . &lt;/code&gt; 移动至当前目录&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;chmod &amp;#x3C;number&gt; or &amp;#x3C;option&gt;&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;option&lt;/code&gt;: &lt;code&gt;[u(user) || g(group) || o(other) || a(all)]+(rwx)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;number&lt;/code&gt;: 八进制下的 rwx 权限 (111 = 7 110 = 6) 每一位代表每个组&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>Linux</category></item><item><title>Strapi踩坑指南</title><link>https://feichuans.com/blogs/05-archive/strapi%E8%B8%A9%E5%9D%91%E6%8C%87%E5%8D%97/</link><guid isPermaLink="true">https://feichuans.com/blogs/05-archive/strapi%E8%B8%A9%E5%9D%91%E6%8C%87%E5%8D%97/</guid><description>最近接了一个单子 前端已经写好 但是需要一个简单 CMS 来管理数据,最终选择了 Strapi 主要是看中了他 Headless CMS + RestFul API+开源的优势. 接下来简单说一下我遇到坑与难点 populate 深层数据 比方说我们有这样一个结构 那么自动生成的链接就是 GET /api/…</description><pubDate>Mon, 14 Jul 2025 10:03:48 GMT</pubDate><content:encoded>&lt;p&gt;最近接了一个单子 前端已经写好 但是需要一个简单 CMS 来管理数据,最终选择了 Strapi 主要是看中了他 Headless CMS + RestFul API+开源的优势.
接下来简单说一下我遇到坑与难点&lt;/p&gt;
&lt;h2 id=&quot;populate-深层数据&quot;&gt;populate 深层数据&lt;/h2&gt;
&lt;p&gt;比方说我们有这样一个结构&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ts&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;interface&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Person&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;	name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;	age&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;number&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;	components&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Components&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;可以理解为对象&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;那么自动生成的链接就是 &lt;code&gt;GET /api/person/documentId 和 /api/persons&lt;/code&gt;
在默认情况下返回的数据是&lt;strong&gt;不带&lt;code&gt;components&lt;/code&gt;的&lt;/strong&gt;,也就是下面这样&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// /api/persons&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;name,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;age,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在官方文档中提供了一个简单办法,那就是 &lt;code&gt;/api/persons?populte=*&lt;/code&gt;
这样的话就可以获取到所有第二层的数据(就是说非基本数据,官方以层级来解释). 但是这个方法有两个缺点，第一个 URL 不干净了(悲),第二个就是
&lt;strong&gt;只能获取到第二层的数据&lt;/strong&gt; 无法处理多层嵌套的情况 比方说，
Strapi 目前提供了 三种&lt;code&gt;Content-Type&lt;/code&gt;分别是 &lt;code&gt;集合类型(Collection Types)&lt;/code&gt;,&lt;code&gt;单个类型(Single Types)&lt;/code&gt;和&lt;code&gt;组件(Conponents)&lt;/code&gt;.
而基本类型中又有引用(稍后提到)和 Component 组件 这两种类型可以在当前的类型中引用或嵌入一个对应类型的对象,日常开发中可能嵌套多层.
虽然官方也提供了基于上述方法&lt;code&gt;populate&lt;/code&gt;的扩展 比如&lt;code&gt;/api/persons?populate[A][populate][underAObjectName]&lt;/code&gt; 但是还是太麻烦了.好在官方是支持自定义处理方法的,&lt;/p&gt;
&lt;h3 id=&quot;what-is-custom-handle-method&quot;&gt;What is custom handle method?&lt;/h3&gt;
&lt;p&gt;在&lt;code&gt;/src/api/类型名/controllers/&lt;/code&gt; 目录下有这样的工厂代码&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ts&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { factories } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;@strapi/strapi&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;export&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; default&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; factories.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;createCoreController&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;api::overview.overview&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, {});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果我们想自定义返回的结构与层级,又不想改 url,可以直接在第二个参数里写入对应路由的方法,例如&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;ts&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { factories } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;@strapi/strapi&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;export&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; default&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; factories.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;createCoreController&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;api::overview.overview&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  async&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; create&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;ctx&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;next&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; data &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; strapi.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;documents&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;api::overview.overview&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;create&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      populate: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;        //这个是引用类型的数据&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        records: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;          populate: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;            // 等同于 {populate:*}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            image_url: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;          },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  async&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; find&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;ctx&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;next&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  async&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; findOne&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;ctx&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;next&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;by the way, 媒体库中的图片在返回的时候也是只返回&lt;code&gt;documentId&lt;/code&gt;,要想直接获得 url 需要加一个 populate&lt;/p&gt;
&lt;h2 id=&quot;自定义路由&quot;&gt;自定义路由&lt;/h2&gt;
&lt;p&gt;这个比较简单.
只需要在 &lt;code&gt;/api/[自定义名字]/controllers&lt;/code&gt; 和 &lt;code&gt;/api/[自定义名字]/router&lt;/code&gt;写入对应的&lt;/p&gt;</content:encoded><category>Nodejs</category></item></channel></rss>