<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>愧怍</title>
        <link>https://kuizuo.cn/</link>
        <description>愧怍的小站 Blog</description>
        <lastBuildDate>Fri, 20 Jan 2023 00:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>zh</language>
        <copyright>Copyright © 2023 愧怍 Built with Docusaurus.&lt;p&gt;&lt;a href="http://beian.miit.gov.cn/" class="footer_lin"&gt;闽ICP备2020017848号-2&lt;/a&gt;&lt;/p&gt;</copyright>
        <item>
            <title><![CDATA[Deno不只是个Javascript运行时]]></title>
            <link>https://kuizuo.cn/deno-is-not-only-a-javascript-runtime</link>
            <guid>deno-is-not-only-a-javascript-runtime</guid>
            <pubDate>Fri, 20 Jan 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Deno 是一个安全的 JavaScript 和 TypeScript 运行时，作者是 Ryan Dahl（也是 Node.js 的原作者）。Deno 的诞生之初是为了解决 2009 年首次设计 Node.js 时的一些疏忽。我认为这种改造动机很有道理，因为我相信每个程序员都希望有机会能重写他们已有 10 年历史的代码。]]></description>
            <content:encoded><![CDATA[<img loading="lazy" src="https://deno.land/logo.svg" width="150" height="150" class="img_ev3q"><p>Deno 是一个安全的 JavaScript 和 TypeScript 运行时，作者是 Ryan Dahl（也是 Node.js 的原作者）。Deno 的诞生之初是为了<a href="https://link.juejin.cn?target=https://www.youtube.com/watch?v=M3BM9TB-8yA" target="_blank" rel="noopener noreferrer">解决 2009 年首次设计 Node.js 时的一些疏忽</a>。我认为这种改造动机很有道理，因为<strong>我相信每个程序员都希望有机会能重写他们已有 10 年历史的代码。</strong></p><p>deno 刚出的时候就听闻了，传言 deno 是下一代 node.js。不过如今看来，还革不了 node.js 的命。如果要说两者字面上的区别，Deno 的来源是 Node 的字母重新组合（Node = no + de），表示"拆除 Node.js"（de = destroy, no = Node.js）。</p><p>趁着假期学了一段时间的 deno（指<a href="https://deno.land/manual@v1.29.3/introduction" target="_blank" rel="noopener noreferrer" title="文档">文档</a>刷了一遍），想分享本人作为 node 开发者在学习 deno 时认为的一些亮点，以及个人对 deno 与 node 见解。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="开发环境">开发环境<a class="hash-link" href="#开发环境" title="标题的直接链接">​</a></h3><p><a href="https://deno.land/manual@v1.29.2/getting_started/installation" target="_blank" rel="noopener noreferrer" title="Installation | Manual | Deno">Installation | Manual | Deno</a></p><p>默认情况下 deno 会根据不同的系统，选择相应的安装目录，以及依赖目录，你可以<a href="https://deno.land/manual@v1.29.3/getting_started/setup_your_environment#environment-variables" target="_blank" rel="noopener noreferrer" title="配置环境变量">配置环境变量</a>来改变 deno 的默认行为。</p><p>这里我选用 vscode 进行开发，安装<a href="https://marketplace.visualstudio.com/items?itemName=denoland.vscode-deno" target="_blank" rel="noopener noreferrer" title="deno官方插件">deno 官方插件</a>。此时创建一个项目工程文件夹，打开 vscode，并创建 <code>.vscode/settings.json</code> 内容如下</p><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">.vscode/settings.json</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"deno.enable"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"deno.lint"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"editor.formatOnSave"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"[typescript]"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token property">"editor.defaultFormatter"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"denoland.vscode-deno"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>在 vscode 中默认会将 ts 代码认为是 node 运行时环境，因此需要在项目工程下手动配置并启用 deno，让 vscode 以 deno 运行时环境来语法解析 ts 代码。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="deno-的一些亮点">deno 的一些亮点💡<a class="hash-link" href="#deno-的一些亮点" title="标题的直接链接">​</a></h2><p>因为 deno 与 node 一样，都是 javascript 运行时（deno 合理来说是 typescript 运行时）。所以在 javascript 的部分就没什么好说的了，主要对比 deno 相比与 node 的优势，或说我个人觉得一些使用亮点。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="官方所介绍的亮点">官方所介绍的亮点<a class="hash-link" href="#官方所介绍的亮点" title="标题的直接链接">​</a></h3><p>以下是官方所介绍的<a href="https://deno.land/manual@v1.29.3/introduction#feature-highlights" target="_blank" rel="noopener noreferrer" title="亮点">亮点</a>，我对其做了翻译</p><ul><li><p>提供<a href="https://deno.land/manual@v1.29.3/runtime/web_platform_apis" target="_blank" rel="noopener noreferrer" title="web平台功能">web 平台功能</a>，采用网络平台标准。例如，使用 ES 模块、Web worker 和支持 <code>fetch()</code>。</p></li><li><p>默认安全。除非显式启用，否则无法访问文件、网络或环境。</p></li><li><p>支持开箱即用的 <a href="https://deno.land/manual@v1.29.3/advanced/typescript" target="_blank" rel="noopener noreferrer" title="TypeScript">TypeScript</a>。</p></li><li><p>提供单个可执行文件 （<code>deno</code>）。</p></li><li><p>为编辑器提供内置的开发工具，如代码格式化程序 （<a href="https://deno.land/manual@v1.29.3/tools/formatter" target="_blank" rel="noopener noreferrer" title="deno fmt">deno fmt</a>）、linter （<a href="https://deno.land/manual@v1.29.3/tools/linter" target="_blank" rel="noopener noreferrer" title="deno lint">deno lint</a>）、测试运行程序（<a href="https://deno.land/manual@v1.29.3/basics/testing" target="_blank" rel="noopener noreferrer" title="deno test">deno test</a>）和<a href="https://deno.land/manual@v1.29.3/getting_started/setup_your_environment.md#using-an-editoride" target="_blank" rel="noopener noreferrer" title="语言服务器">语言服务器</a>。</p></li><li><p>拥有<a href="https://deno.land/std@0.172.0" target="_blank" rel="noopener noreferrer" title="一组经过审查（审核）的标准模块">一组经过审查（审核）的标准模块</a>，保证与 Deno 一起使用。</p></li><li><p>可以将脚本<a href="https://deno.land/manual@v1.29.3/tools/bundler" target="_blank" rel="noopener noreferrer" title="捆绑">捆绑</a>到单个 JavaScript 文件或<a href="https://deno.land/manual@v1.29.3/tools/compiler" target="_blank" rel="noopener noreferrer" title="可执行文件">可执行文件</a>中。</p></li><li><p>支持使用现有的 npm 模块</p></li></ul><p>以下会针对部分亮点，进行个人的见解。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="自带实用工具">自带实用工具<a class="hash-link" href="#自带实用工具" title="标题的直接链接">​</a></h3><p>deno 则是自带代码格式化（<code>deno fmt</code>）、代码风格（<code>deno lint</code>）、代码测试（<code>deno test</code>）、依赖检查器（<code>deno info</code>）等等的功能。而这些在 node 中，你需要通过第三方的库，如 eslint，jest 才能实现。</p><p>你可以在项目工程中添加配置文件 <a href="https://deno.land/manual@v1.29.2/getting_started/configuration_file" target="_blank" rel="noopener noreferrer" title="deno.json">deno.json</a>来定制化代码风格（rust 中也有类似的功能），但在 node 中必须要借助第三方的库，或是 IDE 才能实现。</p><p>不过也能理解，在当时的编程环境背景下，javascript 还主要作为前端的脚本语言使用，又怎能让 node 来做相关规范呢？（这句话可能有点不妥）</p><p><strong>这点我认为对开发者是否选用你这门语言的一个加分项</strong>，并且这些功能也应该作为编程语言所自带的，有官方的背书（保证），对代码风格才更有所保障。</p><p>这里有份 <a href="https://deno.land/manual@v1.29.4/references/cheatsheet#nodejs---deno-cheatsheet" target="_blank" rel="noopener noreferrer" title="官方小抄">官方小抄</a> 可以知道通过<code>deno xxx</code>等命令能够做到 node 原本需要通过第三方库才能实现的功能。</p><table><thead><tr><th>Node.js</th><th>Deno</th></tr></thead><tbody><tr><td><code>node file.js</code></td><td><code>deno run file.js</code></td></tr><tr><td><code>ts-node file.ts</code></td><td><code>deno run file.ts</code></td></tr><tr><td><code>npm i -g</code></td><td><code>deno install</code></td></tr><tr><td><code>npm i</code> / <code>npm install</code></td><td><em>n/a</em></td></tr><tr><td><code>npm run</code></td><td><code>deno task</code></td></tr><tr><td><code>eslint</code></td><td><code>deno lint</code></td></tr><tr><td><code>prettier</code></td><td><code>deno fmt</code></td></tr><tr><td><code>rollup</code> / <code>webpack</code> / etc</td><td><code>deno bundle</code></td></tr><tr><td><code>package.json</code></td><td><code>deno.json</code> / <code>deno.jsonc</code> / <code>import_map.json</code></td></tr><tr><td><code>tsc</code></td><td><code>deno check</code></td></tr><tr><td><code>typedoc</code></td><td><code>deno doc</code></td></tr><tr><td><code>jest</code> / <code>ava</code> / <code>mocha</code> / <code>tap</code> / etc</td><td><code>deno test</code></td></tr><tr><td><code>nodemon</code></td><td><code>deno run/lint/test --watch</code></td></tr><tr><td><code>nexe</code> / <code>pkg</code></td><td><code>deno compile</code></td></tr><tr><td><code>npm explain</code></td><td><code>deno info</code></td></tr><tr><td><code>nvm</code> / <code>n</code> / <code>fnm</code></td><td><code>deno upgrade</code></td></tr><tr><td><code>tsserver</code></td><td><code>deno lsp</code></td></tr><tr><td><code>nyc</code> / <code>c8</code> / <code>istanbul</code></td><td><code>deno coverage</code></td></tr><tr><td><code>benchmarks</code></td><td><code>deno bench</code></td></tr></tbody></table><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="远程导入"><a href="https://deno.land/manual@v1.29.3/basics/modules#remote-import" target="_blank" rel="noopener noreferrer" title="远程导入">远程导入</a><a class="hash-link" href="#远程导入" title="标题的直接链接">​</a></h3><p>与 node 不同，使用 node 通常需要从 npm 官方包来下载并导，有 npm 这样的包管理器来统一管理这些包（package），我们通常称这种为中心化，而 deno 与 go 的做法很像，你可以将你的封装好的代码定义成一个包，并将其放在任何网络可访问的地方，比如 github，或是私有地址，然后通过网络读取文件的方式来导入，这种称为去中心化。</p><div class="theme-admonition theme-admonition-tip alert alert--success admonition_LlT9"><div class="admonitionHeading_tbUL"><span class="admonitionIcon_kALy"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>提示</div><div class="admonitionContent_S0QG"><p>node 也不一定要用 npm 来下载模块，也可以本地模块或者私有模块。</p></div></div><p>关于中心化与去中心化管理，各有优缺，这里不做细致讨论。</p><p>以下是 deno 官方远程导入的代码示例：</p><p><strong>Command: deno run ./remote.ts</strong></p><div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">remote.ts</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">add</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> multiply</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'https://x.nest.land/ramda@0.27.0/source/index.js'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">totalCost</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">outbound</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(0, 112, 193)">number</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> inbound</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(0, 112, 193)">number</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> tax</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(0, 112, 193)">number</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(0, 112, 193)">number</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">multiply</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token function" style="color:rgb(0, 0, 255)">add</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">outbound</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> inbound</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> tax</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token builtin" style="color:rgb(0, 112, 193)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token function" style="color:rgb(0, 0, 255)">totalCost</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">19</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">31</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1.2</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token builtin" style="color:rgb(0, 112, 193)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token function" style="color:rgb(0, 0, 255)">totalCost</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">45</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">27</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1.15</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">/**</span><br></span><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)"> * Output</span><br></span><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)"> *</span><br></span><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)"> * 60</span><br></span><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)"> * 82.8</span><br></span><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)"> */</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>而这里的 <code>https://x.nest.land/ramda@0.27.0/source/index.js</code> 可以替换成任何 ES module 特性（import/export）的模块。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="http-的方式运行代码">http 的方式运行代码<a class="hash-link" href="#http-的方式运行代码" title="标题的直接链接">​</a></h3><p>既然都能通过 http（cdn）远程导入模块，那远程运行文件自然也不成大问题。有时候像快捷体验一下别人的代码，或是想要在浏览器中运行一下代码，这时候就可以通过 http 的方式来运行代码。</p><p>这里我准备了一段代码，并部署到我的站点上，你可以通过如下命令得到该代码的执行结果（如果你有安装 deno 的话），放心这段代码并无危害，就是一段简单的 console.log 输出。</p><div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">deno run https://deno.kuizuo.cn/main.ts</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>在第一次使用时下载并缓存代码，你可以通过</p><div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">deno info http://deno.kuizuo.cn/main.ts</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>来查看文件信息，如下</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_deb0_lGYRA.png" class="img_ev3q"></p><p>deno info 还可以查看 deno 的相关配置，默认缓存都设置在 C 盘，你也可以设置<strong>DENO_DIR</strong> 环境变量来更改 deno 目录，可以到 <a href="https://deno.land/manual@v1.29.3/getting_started/setup_your_environment#environment-variables" target="_blank" rel="noopener noreferrer" title="Set Up Your Environment">Set Up Your Environment</a> 查看 deno 相关环境变量。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="依赖管理">依赖管理<a class="hash-link" href="#依赖管理" title="标题的直接链接">​</a></h3><p>经常使用 node 的开发者应该对 node 的依赖感到无比厌烦，关于这部分强烈建议看 <a href="https://juejin.cn/post/6914508615969669127" target="_blank" rel="noopener noreferrer">node_modules 困境</a>，你就能知道 node 的 node_modules 设计的是有多少问题。看完你也就能知道为啥越来越多的 node 项目都使用 <a href="https://pnpm.io" target="_blank" rel="noopener noreferrer">pnpm</a> 作为包管理。</p><p>虽然 node 有了 pnpm 包管理器这种情况会好一些，但本质在项目目录还是需要 node_modules 文件。也许你用过其他语言的包管理器，你会发现基本都是将所有用到的依赖全局缓存起来，当不同的项目工程需要用到依赖时，直接去全局缓存中找，而不是像 npm 一样，下载到项目工程目录下，存放在 node_modules 里。</p><p>而 deno 也是采用这种这种方式，<code>no npm install</code>，<code>no package.json</code>，<code>no node_modules/</code> ，<a href="https://deno.land/manual@v1.29.3/node/npm_specifiers#using-npm-packages-with-npm-specifiers" target="_blank" rel="noopener noreferrer" title="使用npm包">使用 npm 包</a>可以像下面这样，当你使用 deno run 时便会下载好依赖置全局缓存中。</p><div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">app.ts</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)">// @deno-types="npm:@types/express@^4.17"</span><span class="token plain"></span><br></span><span class="token-line theme-code-block-highlighted-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> express </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'npm:express@^4.17'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> app </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">express</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">app</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">get</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'/'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">req</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">send</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'Hello World'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">app</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">listen</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">3000</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token builtin" style="color:rgb(0, 112, 193)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'listening on http://localhost:3000/'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>deno 刚发布的时候，甚至还不支持 NPM 软件包，这无非是要告诉用户 deno 社区没有轮子，要求用户自己去造一个。不过 deno 团队还是做出了比较正确的选择，支持 npm 软件包，并且还非常友好。</p><p>不过如果你在 deno 中使用了 npm 包，可能会存在一些兼容性问题，万一遇到了，也可以通过添加 <code>--node-modules-dir</code> 标识，在当前运行目录下创建 <code>node_modules</code> 文件夹。详见 <a href="https://deno.land/manual@v1.29.4/node/npm_specifiers#--node-modules-dir-flag" target="_blank" rel="noopener noreferrer" title="--node-modules-dir flag">--node-modules-dir flag</a></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="安全">安全<a class="hash-link" href="#安全" title="标题的直接链接">​</a></h3><p><a href="https://deno.land/manual@v1.29.4/basics/permissions" target="_blank" rel="noopener noreferrer" title="Permissions">Permissions</a></p><p>在 2022 年 npm 出现过一些恶性的库，如 lodash-utils, faker.js, chalk-next。万一你不小心安装了上面，轻则项目无法运行，输出无意义乱码，重则删除本地文件。</p><p>又因为 npm 几乎没有代码审计的机制，任何开发者只需要有一个 npm 的账号就能在上面随意发布他想发布的包。通常来说电脑病毒都是通过随意读取与写入本地文件来达到病毒的目的，但在 deno 中，代码如果尝试写入与读入文件，都需要询问开发者是否允许操作。并且在 linux 系统，你可以指定像 /usr /etc 这样非 root 角色来操作该文件，避免真是病毒文件导致删除不该删除的文件。</p><p>此外像命令执行，网络访问，环境变量这些极易危害电脑的权限，deno 都会检测到，并做出提示告诫开发者是否允许执行。总之你能想到的电脑安全隐患，deno 都为你做好了。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="内置浏览器环境运行时">内置浏览器环境（运行时）<a class="hash-link" href="#内置浏览器环境运行时" title="标题的直接链接">​</a></h3><p>这是我认为 deno 最大的亮点。</p><p>总所周知，浏览器的 js 代码有很大概率是无法直接在 node 中跑起来的，原因就是 node 的全局对象中没有浏览器的对象，如 window，document，甚至连<code>localStorage</code> 都有！</p><p>这说明什么，往常如果你从别的网站扣了一段代码下来，想在 node 运行会发现什么 window is not defined，xxx is not defined。如果想在 node 运行，你必须需要补齐浏览器的环境，此外可以借助 js-dom，happy-dom 等 npm 包。而 window，xxx 这些全局只有浏览器才定义的全局对象在 deno 的运行时同样定义了，可以到<a href="https://deno.land/manual@v1.29.3/runtime/web_platform_apis#using-web-platform-apis" target="_blank" rel="noopener noreferrer" title="这里">这里</a>查看支持的 Web 平台 API。</p><p>虽说与真实浏览器全局对象有些许差异，但这也足够让开发者少做很多工作。比如 Web 逆向者通常要扣取浏览器的 js 代码，并补齐环境使其能够在 node 中运行，而有了 deno 这将变得非常轻松！</p><p><strong>与其说是 javascript/typescript 运行时，我更愿意说是浏览器运行时！</strong></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="web-框架">Web 框架<a class="hash-link" href="#web-框架" title="标题的直接链接">​</a></h3><p>你可以在 <a href="https://deno.land/manual@v1.29.2/getting_started/web_frameworks" target="_blank" rel="noopener noreferrer" title="Web Frameworks">Web Frameworks</a> 中看到 deno 官方所推荐的 Web 框架，其中 <a href="https://deno.land/manual@v1.29.2/getting_started/web_frameworks#fresh" target="_blank" rel="noopener noreferrer" title="Fresh">Fresh</a> 也是最为推荐使用的（后续我也会尝试使用该框架）。</p><p>而在 node 社区中，你会看到像 express，koa，nestjs 等等这种非 Node 官方或大背景的 web 框架（而且还很多），而这时对于初学者而言，就有点不知道该如何做出抉择。</p><p>而像 java 中你完全可以不用担心该学什么，说学 spring 就是在学 java 这可一点都不为过。可能这也是国内 java，尤其是 spring 的开发者尤为诸多的原因。</p><p>吐槽归吐槽，但我想表明的是在有官方的支持下，用户和开发者能够统一使用某个框架，一起维护与使用一个更好的框架。而不是个个 Web 框架的都有各自的优缺点，让使用者去选择，搞得这个框架是另一个框架的轮子一般。</p><p>所以我认为这种支持是很有必要。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="公共托管服务">公共托管服务<a class="hash-link" href="#公共托管服务" title="标题的直接链接">​</a></h3><p><a href="https://dash.deno.com/" target="_blank" rel="noopener noreferrer" title="Project - Deploy (deno.com)">Project - Deploy (deno.com)</a></p><p>deno 像 vercel/netfily 一样提供了一个代码托管服务，可以将你的 deno 应用部署上去。对，目前来看还无法部署前端应用，因为要指明一个入门文件（main.ts）。</p><p>你可以通过 <a href="https://kuizuo.deno.dev/" target="_blank" rel="noopener noreferrer" title="https://kuizuo.deno.dev/">https://kuizuo.deno.dev/</a> 来访问我使用 deno Deploy 所创建的一个在线项目。将会输出一个<code>Hello World!</code> 的页面。</p><p>提供一个免费的线上环境体验，对开发者而言尤为重要，尤其是在将自己的项目成果分享给他人展示时，成就感油然而生。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="node-转-deno-开发的一些帮助">node 转 deno 开发的一些帮助<a class="hash-link" href="#node-转-deno-开发的一些帮助" title="标题的直接链接">​</a></h2><p>deno 相关的亮点我也差不多介绍完了，也许你对 deno 已经有一丝兴趣想尝试一番，以下我整理的对你也许有所帮助。</p><ul><li><p>如果你是一个 Node 用户，考虑切换到 Deno，这里有一个<a href="https://link.juejin.cn/?target=https://deno.land/manual/node/cheatsheet" target="_blank" rel="noopener noreferrer" title="官方小抄">官方小抄</a>来帮助你。</p></li><li><p>如果你不想刷 deno 文档，想快速上手 deno 的话，这里我建议推荐看看 deno 官方所推荐的<a href="https://deno.land/manual@v1.29.4/examples" target="_blank" rel="noopener noreferrer" title="deno代码例子 ">deno 代码例子 </a>，能够非常快速有效了直接了解 deno 标准库以及依赖导入导出。</p></li><li><p>deno 是集成了 node 与 npm 的，也就是说允许直接使用 npm 包与 node 标准库，如果你想用 deno 来写 node，也行，详看<a href="https://deno.land/manual@v1.29.4/node#interoperating-with-nodejs-and-npm" target="_blank" rel="noopener noreferrer" title="Interoperating with Node.js and npm">Interoperating with Node.js and npm</a>。</p></li><li><p>想要在 deno 中连接数据库，可看<a href="https://deno.land/manual@v1.29.4/basics/connecting_to_databases#connecting-to-databases" target="_blank" rel="noopener noreferrer" title="Connecting to Databases">Connecting to Databases</a>。</p></li><li><p>如果想看 deno 如何使用 deno 生态的 Web 框架创建一个 Web 服务，推荐<a href="https://fresh.deno.dev/" target="_blank" rel="noopener noreferrer" title="fresh">fresh</a>框架，并查看该例子<a href="https://github.com/denoland/fresh/tree/main/examples/counter" target="_blank" rel="noopener noreferrer" title="fresh/examples/counter">fresh/examples/counter</a></p></li></ul><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="node-火吗">node 火吗?<a class="hash-link" href="#node-火吗" title="标题的直接链接">​</a></h2><p>关于 deno 就暂且落下笔墨，不妨思考一个问题，node 火吗。</p><p>作为 node 开发者，我肯定会说 node 火，不过更多是对 javascript 来说火。</p><div class="theme-admonition theme-admonition-info alert alert--info admonition_LlT9"><div class="admonitionHeading_tbUL"><span class="admonitionIcon_kALy"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>2022 State of JS</div><div class="admonitionContent_S0QG"><p>2022 也结束了，不妨查看 <a href="https://2022.stateofjs.com" target="_blank" rel="noopener noreferrer" title="2022 State of JS">2022 State of JS</a> 数据报告统计，看看 JavaScript 在 2022 年是如何发展的吧。</p></div></div><p>如今 typescript 大势所趋，说 javascript 就等同于说 typescript，而 javascript 和 node 绑定已成事实，而前端也与 javascript 所绑定，如今的前端工程师要是不会 node，都不好意思说自己是个前端工程师。就现阶段看，没了 nodejs，前端技术得倒退十年（不夸张）。</p><p>如果是在 Web 前端，Node 确实已经火的一塌糊涂了，然而它的诞生并不是为了 Web 前端，而是希望将 javascript 作为服务器端语言发展。只是后来没有想到的是 Node.js 在前端领域却大放异彩，造就了如今大前端的盛世。</p><p>所以在 Web 后端的领域，Node 确实是不温不火，更多的公司都宁可选主流的后端开发语言，而不是优先考虑 Node。不过倒是在 Serverless 领域中，Node 有着一席之地。</p><p>所以我想 deno 的出现，不仅是针对 Node.js 的缺陷，更是针对 Node.js 后端开发的不足。至于说 deno 能否完成原先 node 的使命，只有时间能给我们答案。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="总结">总结<a class="hash-link" href="#总结" title="标题的直接链接">​</a></h2><p>从上述看来，你应该会发现 deno 并不和 node 一样是一个纯运行时环境。因为他不仅仅做了 javascript/typescript 运行时环境，还做了很多开发者好评的功能，一个为 javascript/typescript 提供更好的开发支持的产品。</p><p>但好评并不能直接决定销量，这些功能看似可有可无，没有激起用户从 Node.js 切换过来的杰出之处。就我体验完发现，好像 deno 能做的东西 node 大部分也能做，只是相对繁琐重复一些而已。<strong>但人们更倾向于做一件繁琐重复的事情，而不是做一个新的事情。</strong></p><p>扪心自问，我真的很希望 deno 能火，就开发体验而言，比 node 好用太多了，但好用的东西代表不了用的人就多，这个领域中，生态尤为重要。想要让 node 用户转到 deno 开发还有很长一段路要走。</p><p>再来反问自己，我现在会将 deno 作为 node 替代品吗，我想我和多数 node 开发者一样，都不会将 deno 作为主力语言(因为有很多项目都已经使用node来进行开发与推动)。但作为个人开发者，尤其是 node 开发者，我认为还是非常有必要去尝试一番 deno，亲手目睹"下一代Node"。</p><p>希望本文能对你了解 deno 有所帮助。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="相关推荐文章">相关推荐文章<a class="hash-link" href="#相关推荐文章" title="标题的直接链接">​</a></h2><p><a href="https://juejin.cn/post/7168383367602241550" target="_blank" rel="noopener noreferrer" title="Deno vs. Node.js哪个更好 - 掘金 (juejin.cn)">Deno vs. Node.js 哪个更好 - 掘金 (juejin.cn)</a></p><p><a href="https://juejin.cn/post/6956461134299955213" target="_blank" rel="noopener noreferrer" title="为什么 Deno 没有众望所归？超越 Node.js 还要做些什么？ - 掘金 (juejin.cn)">为什么 Deno 没有众望所归？超越 Node.js 还要做些什么？ - 掘金 (juejin.cn)</a></p><p><a href="https://www.zhihu.com/question/327534747" target="_blank" rel="noopener noreferrer" title="连发明人都抛弃node.js了，还有前途吗？ - 知乎 (zhihu.com)">连发明人都抛弃 node.js 了，还有前途吗？ - 知乎 (zhihu.com)</a></p><p><a href="https://www.zhihu.com/question/517617266" target="_blank" rel="noopener noreferrer" title="已经 2022 年了 Deno 现在怎么样了? - 知乎 (zhihu.com)">已经 2022 年了 Deno 现在怎么样了? - 知乎 (zhihu.com)</a></p>]]></content:encoded>
            <category>deno</category>
            <category>node</category>
            <category>javascript</category>
            <category>typescript</category>
        </item>
        <item>
            <title><![CDATA[Rust实现MD5加密并打包成WebAssembly调用]]></title>
            <link>https://kuizuo.cn/rust-wasm-md5</link>
            <guid>rust-wasm-md5</guid>
            <pubDate>Wed, 04 Jan 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[我初识 WebAssembly 是当初想要分析某个网站的加密算法，最终定位到了一个 .wasm 文件，没错，这个就是 WebAssembly 的构建产物，能够直接运行在浏览器中。在我当时看来这门技术很先进，不过如今看来绝大多数的 web 应用貌似都没使用上，迄今为止我也只在这个网站中看到使用 WebAssembly 的（也许有很多，只是没实质分析过）。]]></description>
            <content:encoded><![CDATA[<img loading="lazy" src="https://img.kuizuo.cn/wasm-ferris.png" width="230" height="150" class="img_ev3q"><p>我初识 WebAssembly 是当初想要分析某个网站的加密算法，最终定位到了一个 <code>.wasm</code> 文件，没错，这个就是 WebAssembly 的构建产物，能够直接运行在浏览器中。在我当时看来这门技术很先进，不过如今看来绝大多数的 web 应用貌似都没使用上，迄今为止我也只在这个网站中看到使用 WebAssembly 的（也许有很多，只是没实质分析过）。</p><p>恰好最近正在接触 Rust，而 Rust 开发 WebAssembly 也非常方便，因此本文算是我对 Rust + WebAssembly 的初探。</p><p>有关 <a href="https://developer.mozilla.org/zh-CN/docs/WebAssembly" target="_blank" rel="noopener noreferrer">WebAssembly </a>不做过多介绍，你可以到 <a href="https://developer.mozilla.org/zh-CN/docs/WebAssembly" target="_blank" rel="noopener noreferrer">MDN</a> 中查看相关介绍。本文重点于 Rust + WebAssembly 实践与相关工具，在 <a href="https://github.com/rustwasm" target="_blank" rel="noopener noreferrer">Rust and WebAssembly (github.com)</a> 或 <a href="https://github.com/rwasm" target="_blank" rel="noopener noreferrer">https://github.com/rwasm</a> 中查看 rustwasm 相关生态。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="使用-wasm-pack-打包-rust-为-wasm-文件">使用 <a href="https://rustwasm.github.io/wasm-pack/installer/" target="_blank" rel="noopener noreferrer">wasm-pack</a> 打包 rust 为 wasm 文件<a class="hash-link" href="#使用-wasm-pack-打包-rust-为-wasm-文件" title="标题的直接链接">​</a></h2><p>下载 wasm-pack，用于将 rust 代码打包成 .wasm 文件</p><div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">cargo install wasm</span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain">pack</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>使用 cargo 有可能无法安装 wasm-pack（笔者就安装不了 openssl-sys），可以到 <a href="https://rustwasm.github.io/wasm-pack/installer/" target="_blank" rel="noopener noreferrer">wasm-pack</a> 官网下载对应的二进制文件进行安装。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="构建-rust-lib">构建 rust lib<a class="hash-link" href="#构建-rust-lib" title="标题的直接链接">​</a></h3><div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain"> cargo new --lib hello-wasm</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>将会创建 rust 库工程，并创建 <code>src/lib.rs</code>。修改为以下内容（先不必在意代码）</p><div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">src/lib.rs</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">extern</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">crate</span><span class="token plain"> </span><span class="token module-declaration namespace">wasm_bindgen</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">use</span><span class="token plain"> </span><span class="token namespace">wasm_bindgen</span><span class="token namespace punctuation" style="color:rgb(4, 81, 165)">::</span><span class="token namespace">prelude</span><span class="token namespace punctuation" style="color:rgb(4, 81, 165)">::</span><span class="token operator" style="color:rgb(0, 0, 0)">*</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token attribute attr-name" style="color:rgb(255, 0, 0)">#[wasm_bindgen]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">extern</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">pub</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:rgb(0, 0, 255)">alert</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">s</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">&amp;</span><span class="token keyword" style="color:rgb(0, 0, 255)">str</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token attribute attr-name" style="color:rgb(255, 0, 0)">#[wasm_bindgen]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">pub</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:rgb(0, 0, 255)">greet</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">&amp;</span><span class="token keyword" style="color:rgb(0, 0, 255)">str</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token function" style="color:rgb(0, 0, 255)">alert</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token operator" style="color:rgb(0, 0, 0)">&amp;</span><span class="token macro property">format!</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">"Hello, {}!"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>接着在 Cargo.toml 文件中添加 wasm-bindgen 依赖，<code>wasm-bindgen</code> 来提供 JavaScript 和 Rust 类型之间的桥梁，允许 JavaScript 使用字符串调用 Rust API，或调用 Rust 函数来捕获 JavaScript 异常。</p><div class="language-toml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">Cargo.toml</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-toml codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token table class-name" style="color:rgb(38, 127, 153)">package</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token key property">name</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"hello-wasm"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token key property">version</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"0.1.0"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token table class-name" style="color:rgb(38, 127, 153)">lib</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token key property">crate-type</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">"cdylib"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token table class-name" style="color:rgb(38, 127, 153)">dependencies</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token key property">wasm-bindgen</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"0.2"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="打包">打包<a class="hash-link" href="#打包" title="标题的直接链接">​</a></h3><div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">wasm</span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain">pack build</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>WebAssembly 构建产物将会输出在 pkg 目录下，如下</p><div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">├─pkg</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">|  ├─.gitignore</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">|  ├─hello_wasm.d.ts</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">|  ├─hello_wasm.js</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">|  ├─hello_wasm_bg.js</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">|  ├─hello_wasm_bg.wasm</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">|  └─hello_wasm_bg.wasm.d.ts</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><div class="theme-admonition theme-admonition-note alert alert--secondary admonition_LlT9"><div class="admonitionHeading_tbUL"><span class="admonitionIcon_kALy"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>备注</div><div class="admonitionContent_S0QG"><p>如果想当 npm 包发布的话，可以添加 —scope 参数，将会在 pkg 下生成 package.json 文件用于发布或当做一个 npm 包来使用，这样也可以在前端工程中直接当做一个模块来导入使用。</p><div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">wasm</span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain">pack build </span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain">scope mynpmusername</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></div></div><p>借助 <a href="https://rustwasm.github.io/wasm-pack/installer/" target="_blank" rel="noopener noreferrer">wasm-pack</a> 可以非常轻松的将 rust 打包成 wasm，同时还提供了 js 相关支持。直接打包成 js 可导入的 npm 包，而不是让用户导入 wasm 文件然后通过浏览器 <code>WebAssembly</code> 对象来加载 WebAssembly 代码，其他语言的 WebAssembly 开发也是如此。</p><p>此外 <a href="https://rustwasm.github.io/" target="_blank" rel="noopener noreferrer">rustwasm</a> 还提供了对应的模板 <a href="https://github.com/rustwasm/wasm-pack-template" target="_blank" rel="noopener noreferrer">rustwasm/wasm-pack-template</a>，可以帮你省去上面的一系列配置操作，专注于你的 wasm 开发。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="运行">运行<a class="hash-link" href="#运行" title="标题的直接链接">​</a></h3><p>由于上面我们已经将其打包成了一个 npm 包，只需要将配置好 package.json 的依赖即可，本地的话可通过下方格式，将 pkg 目录更改为 hello-wasm，并放置在根目录下。</p><div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token string" style="color:rgb(163, 21, 21)">"dependencies"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token string" style="color:rgb(163, 21, 21)">"hello-wasm"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"file:./hello-wasm"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>这时候就可以通过 js 直接导入使用</p><div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> js </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">import</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">"./hello-wasm/hello_wasm.js"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">js</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">then</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">js </span><span class="token operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  js</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">greet</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">"WebAssembly"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>在 vite 生态中有个 <a href="https://github.com/rwasm/vite-plugin-rsw" target="_blank" rel="noopener noreferrer">rwasm/vite-plugin-rsw</a> 插件，能够在 vite 中快速使用 wasm-pack。下文中的一个应用示例也将采用该插件进行开发。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="rust-实现-md5-算法">Rust 实现 MD5 算法<a class="hash-link" href="#rust-实现-md5-算法" title="标题的直接链接">​</a></h2><p>回到一开始的标题，在实现这个功能我一般会想 js 如何实现 MD5 算法，通常来说 MD5 算法是个比较流行的加密算法，通过搜索引擎能够快速帮我找到一份 js 的 MD5 算法。不过我更习惯通过包管理器导入的加密库，如<a href="https://www.npmjs.com/package/crypto-js" target="_blank" rel="noopener noreferrer">crypto-js</a>。</p><p>同理，在 rust 中可以到 <a href="https://crates.io/" target="_blank" rel="noopener noreferrer">crates.io</a> 中也可以找到你想要的库，如 <a href="https://crates.io/crates/digest" target="_blank" rel="noopener noreferrer">digest</a>，不过我这里主要是实现 MD5 算法便使用的是 <a href="https://crates.io/crates/md-5" target="_blank" rel="noopener noreferrer">md-5</a>。以下是我的封装代码。</p><div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">use</span><span class="token plain"> </span><span class="token namespace">md5</span><span class="token namespace punctuation" style="color:rgb(4, 81, 165)">::</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token class-name" style="color:rgb(38, 127, 153)">Digest</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">Md5</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:rgb(0, 0, 255)">md5</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">input</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">&amp;</span><span class="token keyword" style="color:rgb(0, 0, 255)">str</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-&gt;</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">String</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">mut</span><span class="token plain"> hasher </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">Md5</span><span class="token punctuation" style="color:rgb(4, 81, 165)">::</span><span class="token function" style="color:rgb(0, 0, 255)">new</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    hasher</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">update</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">input</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">as_bytes</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> result </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> hasher</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">finalize</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token macro property">format!</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">"{:x}"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> result</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:rgb(0, 0, 255)">main</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> result </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">md5</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">"123456"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token macro property">println!</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">"{}"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> result</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>然后将这一部分的代码替换到一开始的示例中。</p><div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">lib.rs</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">extern</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">crate</span><span class="token plain"> </span><span class="token module-declaration namespace">wasm_bindgen</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">extern</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">crate</span><span class="token plain"> </span><span class="token module-declaration namespace">md5</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">use</span><span class="token plain"> </span><span class="token namespace">wasm_bindgen</span><span class="token namespace punctuation" style="color:rgb(4, 81, 165)">::</span><span class="token namespace">prelude</span><span class="token namespace punctuation" style="color:rgb(4, 81, 165)">::</span><span class="token operator" style="color:rgb(0, 0, 0)">*</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">use</span><span class="token plain"> </span><span class="token namespace">md5</span><span class="token namespace punctuation" style="color:rgb(4, 81, 165)">::</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token class-name" style="color:rgb(38, 127, 153)">Digest</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">Md5</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token attribute attr-name" style="color:rgb(255, 0, 0)">#[wasm_bindgen]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">pub</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:rgb(0, 0, 255)">md5</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">input</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">&amp;</span><span class="token keyword" style="color:rgb(0, 0, 255)">str</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">-&gt;</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">String</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">mut</span><span class="token plain"> hasher </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">Md5</span><span class="token punctuation" style="color:rgb(4, 81, 165)">::</span><span class="token function" style="color:rgb(0, 0, 255)">new</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    hasher</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">update</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">input</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">as_bytes</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> result </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> hasher</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">finalize</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token macro property">format!</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">"{:x}"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> result</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>此时通过 wasm-pack 将上述代码打包成 npm 包形式即可在 js 中调用 rust 提供的 md5 函数，至此就已经完成了本标题的内容了。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="在项目中使用">在项目中使用<a class="hash-link" href="#在项目中使用" title="标题的直接链接">​</a></h2><p>这里我所借用 <a href="https://github.com/rwasm/vite-plugin-rsw" target="_blank" rel="noopener noreferrer">rwasm/vite-plugin-rsw</a> 插件，在 vite 中配合 wasm-pack 进行开发的一个实例。代码部分就不做解读了，有兴趣可自行到翻阅源码：<a href="https://github.com/kuizuo/rust-wasm-md5" target="_blank" rel="noopener noreferrer">kuizuo/rust-wasm-md5</a></p><p>在线地址：<a href="http://rust-wasm-md5.kuizuo.cn/" target="_blank" rel="noopener noreferrer">http://rust-wasm-md5.kuizuo.cn</a> （不保证地址长期可用）</p><p><img loading="lazy" src="https://img.kuizuo.cn/image__XHPNCbC-B.png" class="img_ev3q"></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="思考为何不使用-js-的-md5-而是-wasm-的-md5">思考：为何不使用 js 的 md5 而是 wasm 的 md5<a class="hash-link" href="#思考为何不使用-js-的-md5-而是-wasm-的-md5" title="标题的直接链接">​</a></h2><p>众所周知，你在浏览器中按下 F12 打开 DevTools，并选择源代码面板中就可以看到当前访问的网站的所有代码。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_6019y_U19n.png" class="img_ev3q"></p><p>而对于一些具有熟练度的逆向分析者中，如果不经过任何处理的代码被打包到生产环境中能够快速的定位出某个功能的具体代码位置。</p><p>而通过 wasm 就能很有效的将代码隐藏起来，不让逆向分析者查看，就像下面这样</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_BbA3n6wFws.png" class="img_ev3q"></p><p><img loading="lazy" src="https://img.kuizuo.cn/image_81tgfDE_P7.png" class="img_ev3q"></p><p>这里我并没有将 md5 更改成不易猜测的名字，你也可自行下断点尝试一番，定位代码。当你定位到具体代码后，就会得到上图的二进制代码格式，几乎无法解读其意思。</p><p>不过虽说解读不出 wasm 的原代码（至少目前来说很难反编译成原始代码），但可以通过扣代码的方式来调用 wasm 对外提供的函数（这里为 md5 函数）。</p><p>这里仅是 wasm 的一种实际用例，更多情况下应该还是用 Wasm 来提高 web 应用性能的。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="相关链接">相关链接<a class="hash-link" href="#相关链接" title="标题的直接链接">​</a></h2><p><a href="https://developer.mozilla.org/zh-CN/docs/WebAssembly/Rust_to_wasm" target="_blank" rel="noopener noreferrer">编译 Rust 为 WebAssembly - WebAssembly | MDN (mozilla.org)</a></p><p><a href="https://rustwasm.github.io/" target="_blank" rel="noopener noreferrer">Rust and WebAssembly</a></p><p><a href="https://rustmagazine.github.io/rust_magazine_2021/chapter_2/rust_wasm_frontend.html" target="_blank" rel="noopener noreferrer">前端入门 ｜ Rust 和 WebAssembly - Rust 精选</a></p><p><a href="https://github.com/rwasm/vite-plugin-rsw" target="_blank" rel="noopener noreferrer">rwasm/vite-plugin-rsw: 🦞 wasm-pack plugin for Vite (github.com)</a></p>]]></content:encoded>
            <category>rust</category>
            <category>wasm</category>
        </item>
        <item>
            <title><![CDATA[2022年终总结——从逆向转Web开发]]></title>
            <link>https://kuizuo.cn/2022-year-end-summary</link>
            <guid>2022-year-end-summary</guid>
            <pubDate>Thu, 22 Dec 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[距离上一篇博文有一个月之久了，距离上次编写代码也有一周之久了，由于疫情的全面放开，加上福建省教育厅通知的提前返乡，反而让我感到有些不适。往常这个时间点我忙于期末考试，会把代码的事情放一边，等到彻底放假后，开始闭关潜心学习。然而剩余的半个月变成了线上形式，课还是要上，考试还是要考，虽说身在家乡，但心不在焉的 😂。]]></description>
            <content:encoded><![CDATA[<p>距离上一篇博文有一个月之久了，距离上次编写代码也有一周之久了，由于疫情的全面放开，加上福建省教育厅通知的提前返乡，反而让我感到有些不适。往常这个时间点我忙于期末考试，会把代码的事情放一边，等到彻底放假后，开始闭关潜心学习。然而剩余的半个月变成了线上形式，课还是要上，考试还是要考，虽说身在家乡，但心不在焉的 😂。</p><p>12 月已过半，也是时候该写年终总结了。迄今为止，我已学习了 3 年半的编程。（还好不是两年半），当下的技术不再是当初只会易语言的小伙了。只是当下已没有当初如此强烈的热情与精力了，我称之为老了。</p><p>现在回头回顾学习编程时间，用一个成语对自己做个评价——<strong>差强人意</strong>。在这些时间段，我其实荒废过一段时间，厌倦过，贪玩过，荒废过，从我的 <a href="https://github.com/kuizuo'Github%E7%83%AD%E5%8A%9B%E5%9B%BE'" target="_blank" rel="noopener noreferrer">Github 热力图</a> 中其实就能看得出来。就导致欠下技术的，都需要后续花时间去弥补。</p><p>要让自己保持每天都处于学习状态真的太难了 😩，生活总有源源不断的琐事打扰着你。在忙碌的时候总是感觉时间不够用，哪怕有时一天花费了数十个小时，也总感觉做的事情太少了；哪怕每天计划都规划得好好的，但总是有一半还未完成。生活中大量的碎片化时间，而编程学习最不需要的就是这些碎片化时间。</p><p>回顾整个编程生涯有太多可感慨的，整个旅途几乎是一个人走完的，期间遇到的坎坷就只得依靠搜索引擎来解决，搜索引擎是我再生父母都不为过。没有人给我指引明确的道路，只依靠心中对技术的憧憬不断前行。走过低谷，登过山峰，而如今站稳身子就足矣。</p><p>感叹的话语也就是说到这。今年主要总结我为何从逆向转 Web 开发，并明确我未来所要走的方向，也是本文的主题。<strong>仅作为个人感悟，不作为建议参考。</strong></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="为什么要写年终总结">为什么要写年终总结<a class="hash-link" href="#为什么要写年终总结" title="标题的直接链接">​</a></h2><p>先回答一个问题，为什么要写年终总结？</p><p>我从高中开始，每年都会记录这一年所发生的比较有印象的事情并写下自己的感悟。所以写年终算是个人习惯，并且我希望能够一直坚持下去，写到不能写为止。</p><p>写年终总结是个非常好的自我总结与反思的方式，总结这一年自身的变化，有哪些精彩与满足，有哪些遗憾和不足。同时定制明年的规划，以该目标不断前行，而不是漫无目的地活着，就失去了很多人生的意义。</p><p>同时也算是自我评价与建议，很多时候我们会收到很多别人有关自己的评价与建议，可人总会对他人有莫名的排斥感，就难以虚心听从他人的建议，从而犯错许多（说的是我就对了）。年终总结还有个作用就是弥补自己对某件事情未来可能要发生的情况，要如何做到不犯错，预先有个明确的预防意识。</p><p>即便可能要花数天的周期去回顾与总结，我也很愿意去总结，我常说回顾过去，就是在仰望未来。写年终所做的也就是这个过程。</p><p>写年终总结也算是种分享，分享自己的开发经历，当他人阅读时或许有所启发。</p><p><strong>过去的，就过去了，别将当下的遗憾留到未来，这就是年终的最大意义。</strong></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="为什么是-web-开发而不是逆向">为什么是 Web 开发？而不是逆向<a class="hash-link" href="#为什么是-web-开发而不是逆向" title="标题的直接链接">​</a></h2><p>今年大部分的开发时间都花在 Web 开发上，在此期间也接触到许多技术，并通过博客笔记的方式记录下来。</p><p>我很庆幸我的 Web 开发从一个 Beginner 到 Intermediate，现在回忆整个学习路程，一路学得都很野很随意，从未系统学习过，总是学到一半，就自认为已经掌握了，便开始进行实战项目，可以说很多知识都是在实战探索中了解的。</p><p>虽然很多人都直称我为大佬，但我离 Advanced 还有一大段的路途要走，而这段路途是无比的艰难与漫长。不过好在路不歪，只要肯走终会到达终点 👨‍🦲。</p><p>而带我入门的逆向技术，在今年没有丝毫的长进，说得过分点，就是弃坑了。也正如标题所说，至于缘由，细看下文。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="逆向">逆向<a class="hash-link" href="#逆向" title="标题的直接链接">​</a></h3><p>熟悉我的人应该知道我之前是做爬虫与逆向分析，但是为何今年的技术栈彻底转型到 Web 开发上。</p><p>我常常和别人说起我的技术栈转型（从逆向转到开发），不过比较多的都会比较好奇我为什么不继续深造下去。</p><p>在此我也回顾了我<strong>从逆向转变到 Web 开发</strong>的过程，顺带也回答这个问题。不过在这里先说说我个人对逆向的看法：</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="逆向需要的技术知识面比较广">逆向需要的技术知识面比较广。<a class="hash-link" href="#逆向需要的技术知识面比较广" title="标题的直接链接">​</a></h4><p>就我接触逆向的过程来说，接触了易语言，JavaScript，Python，Java，Php 等等编程语言。</p><p>使用过了一堆的逆向工具，如 Frida、IDA、JEB、jadx 等等（我目前能想到比较有名的）。此外还有一堆知识，包括但不限于以下技术：自动化脚本、TCP/HTTP 协议、抓包、爬虫、加密学、图像识别（验证码、滑块位置）、汇编、反编译、AST 反混淆。</p><p><strong>要我说我在逆向中学到的不是如何使用这些工具或掌握某个技能，而是锻炼出一定的阅读与分析代码能力。</strong>工具与技能总是瞬息万变，但阅读与分析代码能力却是实实在在，一成不变的，也是逆向中最值得学习的。</p><p>有接触过 <a href="https://baike.baidu.com/item/ctf/9548546" target="_blank" rel="noopener noreferrer">CTF</a> 想必再熟悉不过逆向工程的技术面广了。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="越来越多的网站或应用程序不断加强安全防护未来只会越来越难逆向">越来越多的网站或应用程序不断加强安全防护，未来只会越来越难逆向。<a class="hash-link" href="#越来越多的网站或应用程序不断加强安全防护未来只会越来越难逆向" title="标题的直接链接">​</a></h4><p>逆向分析，说白话就是去看别人的代码，进行一些修改手段，达到自己想要的目的。比如修改某个软件的标题或作者信息、将别人的代码“偷”过来用、爬取某些网站或软件的数据。</p><p>但是随着现在越来越多潜在的安全问题，很多框架底层，服务厂商，都会对一些可能有安全问题的代码进行警告或者底层处理。比如使用 ORM 框架能够有效防止 SQL 注入，前端框架中涉及 XSS 攻击也会有相应的错误提示与处理，再如浏览器跨域以及跨站点 cookie 不共享，都是为了用户的安全而去考虑的。这样的例子有太多了。</p><p>简单说说安卓逆向的过程：拿到一个 Apk，发现有加壳（给代码加固让逆向者不易于看到源代码），这时候就需要通过脱壳才能查看到源代码；此时就算脱完了壳，接下来可能将面对经过混淆过的代码，这份代码难以用人眼去阅读，不调试运行，单靠静态分析很难分析出东西，这时候可能就要借助 AST 对代码进行还原；还原完了配合动静分析将代码给扣出来，而在分析的时候可能又有各种检测，比如抓包，反调试以阻碍逆向进度；最后就算逆向工作都做完了，代码也扣下来了，还要尝试运行扣完的代码，这时候极大可能还不一定能运行，然后又要回头看看到底那一步做错了。</p><p>可以说逆向的工作就是不断地调试，不断分析，最终拿到想要的结果。整个过程可以说非常耗时且折磨人，心智如果不够强大，真的容易劝退（我当下耐心也早不如当初了）。但是得到最终的目的，将非常爽，成就感爆棚，相当于一个解了几小时的题，最终被攻克的感觉。</p><p>前阵子在逆向圈中，看到过一张图，大致也把我的逆向学习流程也表达了出来，最终我的逆向学习也确实止步在 Flutter 上。</p><p><img loading="lazy" src="https://img.kuizuo.cn/1cd67d5812e3061e_zy9LIkXWIM.jpg" class="img_ev3q"></p><p>上面所说到的逆向技术中，例如加壳，代码混淆，反调试，风控等等，都是阻碍逆向手段。同样对于爬虫而已，通常会采取反爬措施，包括但不限于封 IP、封账号、JS 参数加密、代码混淆、浏览器指纹、TLS 指纹、验证等。而且防护手段可以说是越来越多，逆向的难度也就越来越大。并且在服务开发那边只需要修改一点东西，逆向可能就需要从头再来一遍。</p><p><strong>未来逆向的难度只增不减，但薪资可不一定保证这趋势。</strong></p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="风险">风险<a class="hash-link" href="#风险" title="标题的直接链接">​</a></h4><p>从上面也不难看出逆向常常与安全挂钩，如果一个网站或软件不是那么好被逆向，那么间接说明安全性是比较高的。可一旦涉及到安全，同时又是互联网，就免不了网络安全与法律相关的风险。</p><p>在大多数逆向的对象（网站，软件）中，多数都是他人的劳动产物，当你未经他人允许的情况下，去爬取他人的数据，或是修改一些版权信息再次发布出来，就属于非法行为。本质和未经他人允许，偷人家的东西性质是一个样的。并且在有防护措施的情况下，绕过网站防护措施获取数据属于违背权利人意愿读取、收集数据，将有较大可能被认定为对计算机信息系统的 “侵入”。</p><p>要知道在逆向的行业中，有很多都是擦边灰产，至少我所在的逆向圈是这样的，抱着【仅供学习为参考，请勿用于非法用途】的想法做逆向工程。路子极易走歪，很少能够正常去走安全岗位的。相信你应该能看到许多类似的案件，如【某某程序员因非法侵入 xx 网站，获刑 x 年】。这不是危言耸听，目前国家对网络安全以及非法数据获取的打击力度，也将决定了这些案件将会越来越多，爬虫逆向也将会越来越邢。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="自身因素">自身因素<a class="hash-link" href="#自身因素" title="标题的直接链接">​</a></h3><p>简单介绍完我认为爬虫和逆向的看法后，再来说说自身因素。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="更想写代码而不是看代码">更想写代码，而不是看代码<a class="hash-link" href="#更想写代码而不是看代码" title="标题的直接链接">​</a></h4><p>我是很享受写代码的过程，一份高质量的代码会让人赏心悦目。我为此特意学习下设计模式、重构技巧以及 TDD 测试。这些在逆向中基本难以涉及，但是这些对开发的体验和代码的健壮性都是非常重要的，也是让我个人觉得技术有所提升的技能点。</p><p>在逆向分析中，大部分时间都不是在写代码而是在看（分析）代码，而反编译出来的代码，很有可能是带有混淆过的代码，而你想要分析这一块代码的作用，只能去一步步调试，将代码啃下来，从而推断运行时某变量的值，或是某个函数的作用。</p><p>虽然说开发岗位中，有很多情况下也是在看代码的日子中度过的，但相比反编译阅读代码而言，至少不至于那么晦涩难懂。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="更想碰新技术而不是旧技术">更想碰新技术，而不是旧技术<a class="hash-link" href="#更想碰新技术而不是旧技术" title="标题的直接链接">​</a></h4><p>其次，在逆向分析中，遇到的网站或软件所用的技术一般都是较为稳定成熟的技术，而这些技术往往不是很新，因此需要去了解很多旧的技术，但这些旧技术仅仅只对逆向分析有用，甚至过段时间很有可能就会遗忘。并且要了解的旧技术还不少，学得将会特别杂。</p><p>而我又是一个喜新厌旧的人，对任何新鲜事物都抱有好奇尝试的态度。我终将认为旧的技术被淘汰是迟早的问题，新技术的出现肯定不是无缘无故的出现，必然是为了解决某些问题而诞生的，如性能，开发体验，安全等等。</p><p>这里有篇我对新技术的看法，推荐阅读一番。<!-- -->[深谈个人对新技术的看法 - 愧怍的小站 (kuizuo.cn)]<!-- -->(<a href="https://kuizuo.cn/talk-new-technologies-opinion'%E6%B7%B1%E8%B0%88%E4%B8%AA%E4%BA%BA%E5%AF%B9%E6%96%B0%E6%8A%80%E6%9C%AF%E7%9A%84%E7%9C%8B%E6%B3%95" target="_blank" rel="noopener noreferrer">https://kuizuo.cn/talk-new-technologies-opinion'深谈个人对新技术的看法</a> - 愧怍的小站 (kuizuo.cn)')</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="更想开源而不是闭源">更想开源，而不是闭源<a class="hash-link" href="#更想开源而不是闭源" title="标题的直接链接">​</a></h4><p>在逆向开发，不，是在灰产开发中，有很多代码是别指望开源出来的，这背后会涉及到商业利益或是版权等问题。一旦代码放出来，将意味着你的代码将有很大的可能被别人利用做坏事，最终甚至祸及到自己。所以大多数情况下，你多半只能将自己的应用发布出去，而不是将源码开源，通常也就带有商业化的性质。</p><p>我想任何开发者肯定是希望自己的代码走的更远，走的正规，而不是被拿来做违背自身意愿的事情。</p><p>开源不仅能为自己提升一些技术知名度，展现自身技术的一面，同时代码被他人使用与认可，这番成就感就足够继续坚持开源下去。因为我有很多技术都是通过开源项目中学到的，所以我能感受到开源带来的魅力，也是对于前人的崇拜，想走开源的原因。</p><p><strong>因为淋过雨，所以很想为别人撑把伞</strong></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="小结">小结<a class="hash-link" href="#小结" title="标题的直接链接">​</a></h3><p>其实在今年出头我还特意复习了一波安卓逆向，为了更深入了解了更底层的知识与工具（当然现在忘得也差不多了），因一些特殊原因我的电子设备不在了，别问，问就是坏了到现在还没修好。就导致我的编程语言环境，逆向工具，虚拟机配置，代码等数据直接灰飞烟灭，也让我停滞了 1 个月的学习。</p><p>我想这才是我从逆向转 Web 开发的最重要的理由了。</p><p>逆向的学习对我开发有很大的帮助。例如开发中的安全问题，我在开发中都会时刻考虑去考虑该问题。如加壳、SQL 注入、代码混淆、接口限流、接口幂等性（Fiddle R 包）等等安全性问题。</p><p>我庆幸我学过逆向，让我学到很多在开发中比较难学到的技能，如调试，阅读源码，而这些也是绝大多数 Web 开发者都欠缺的能力。</p><p>逆向应该就暂以告终，未来会有很长的一段时间，甚至以后不再接触深入专研逆向。</p><p>每当回想，【当时那么难的加密算法都能搞得定，开发一个功能还能有多难】，保持着这种心态，也让我保持着开发。</p><p>也是逆向激起我对编程的兴趣，可以说没有接触逆向开发，我也不太可能会接触到 Web 开发。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="但-web-开发就一定好吗">但 Web 开发就一定好吗？<a class="hash-link" href="#但-web-开发就一定好吗" title="标题的直接链接">​</a></h2><p>上面对逆向的看法仅个人分析而言，但是 Web 开发就一定好吗？我不敢下绝对的肯定，不同人不一定适合相同的技术，<strong>但是我特别看好 Web 技术（尤其是 JavaScript，偏前端向）</strong>，以下是我看好的点。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="应用性广">应用性广<a class="hash-link" href="#应用性广" title="标题的直接链接">​</a></h3><p>目前仍有很多人还停留在 JavaScript 只能编写前端页面的水平，自从 Node.js 问世，目前绝大多数的应用都可以使用 JavaScript 进行编写。</p><p>换句话说，只要你会 JavaScript 就可以编写很多应用了。有个在国外经常被应用的一条和 JavaScript 有关系的著名定律：</p><p><strong>Atwood 定律：任何可以用 JavaScript 编写的应用程序，最终都会用 JavaScript 编写</strong></p><p>Web 前端开发不用多说，目前还得用 JavaScript 来编写。而后端开发通过 Node.js 也有一己之力。近几年特别流行跨平台开发，也就是一份代码，多端运行。</p><p>使用 React Native 或是 Uniapp 这样的前端应用框架，顺带去了解一下相应平台的 API，就能够编写出安卓或 IOS 应用，做过小程序开发肯定知道小程序的技术栈就使用到前端开发的技术栈，如果你会前端开发，就能很轻松的上手小程序开发了。</p><p>并且越来越多的软件都是网页版优先，然后再通过 Electron 这样的跨平台解决方案，实现不同平台间的程序。诸如 Vscode，Typeorm 等等便是其中的佼佼者。</p><p>不过本质上都是在不同应用的平台上套浏览器的壳，然后接入一些该平台的接口，因此普遍应用的体积与内存都相对比较大，与原生相比自然是略逊与原生，不过这点性能上的差异在如今硬件升级如此普遍的物质生活也显得微不足道了。</p><p>但借助浏览器自带的跨平台性，你所编写的应用能够非常轻松的让他人访问，只需要用户有个浏览器，并且通过上述跨平台的解决方案，也能够有效的将你的 web 应用转成其他平台的应用，而不是在耗费时间与精力去编写另一套代码。</p><p>在一些技术文档上，会有 API/SDK 的支持，而绝大多数都支持使用 JavaScript/Node.js，也许该功能本身并不是使用 JavaScript 来编写的，但完全可以通过 JavaScript 来轻松调用该功能。并且如今 JavaScript 生态如此庞大，你不必担心库/包的问题，npm 作为世界上最大的开放源代码的生态系统（包管理器），在这里你几乎找得到你所想要的库/包。</p><p>此外有越来越多的第三方服务平台（通常称 Fass，函数即服务），专门提供数据接口与用户鉴权，如 firebase/supabase 或是国产的云开发产品（如小程序）。前端程序员只需要专注与业务代码，借助第三方开发平台，就能够编写一个高可用的应用。反而也映衬了，Web 开发好像可以没有后端，但必须要有前端的观念。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="工作量将越来越多">工作量将越来越多<a class="hash-link" href="#工作量将越来越多" title="标题的直接链接">​</a></h3><p>这句话的意思可能有点加班那味道，但我所要表明的是可以做的事情多了，意味着你的工作量增加了，同时你的编码价值也就提升了，不过实际价值（工资）的话不一定提升，因为这主要看老板和地区。</p><p>怎么理解呢，我举几个例子。</p><p>现在大部分的 web 应用都采用前后端分离的形式，但在曾经则是由后端通过模板语言渲染成 HTML 直接返回，通过前后端分离的形式，前端只需要专注页面交互的编写，而后端只需要保证接口可靠性。并且前后端分离也有一个特别显著的特点，能非常有效的节省服务器的资源，原本服务器的渲染动作迁移至客户端来做。也许有人会说，那这样 SEO 优化该怎么办，这不就有了 Next.js、Nuxt.js 这样的 SSR（服务端渲染） 框架，而这些工作，也是前端要做的。</p><p>并且越到后面你越能感觉到客户端（前端）远比服务端（后端）做的东西来的多，比如开发阶段的数据 Mock，前端国际化，设计原型等等。之所以会有这种感觉，也许是因为我的大部分开发都是前端，这里你也可以回想当下的工作量与往年相比是多了还是不变。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="技术更新快">技术更新快<a class="hash-link" href="#技术更新快" title="标题的直接链接">​</a></h3><p>前端真的是每隔一段时间，必定会出一些新的技术，也不由让不少前端学习者感叹真的学不动。但伴随着新的技术出现，必然会有新的岗位与机会，这也是我看好前端的一个点。</p><p><strong>不过这种机会在国内不太多见，反而在国外特别普遍。</strong> 多的不说，自行体会。</p><p>忘记从哪看到的一句话：“前端工程师的一大焦虑：永远能（且必须要）看到大量前沿的技术，但自己手上的活儿跟不上，导致眼高手低。”</p><p>不只是前端，做技术这行的，必须要跟着技术发展的角度，并且要时刻关注最新，主流的技术。</p><hr><p>有关 Web 开发的一些想法与感悟就写到这，其实还有蛮多可写的，比如选择 Vue 与 React？为什么是 JavaScript？有太多自我审问的话题了，不过由于当下时间相对紧迫，有机会的话再续写吧。</p><p>综上，也就是我看好 Web 技术的几个点，也回答了我未来的方向。希望这些能够帮助一些不知抉择方向的伙伴。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="在实践中学习">在实践中学习<a class="hash-link" href="#在实践中学习" title="标题的直接链接">​</a></h2><p>回顾整个技术栈，基本都是在项目实践中不断学习。也许是因为逆向的缘故，因为逆向基本上都是靠实战出来的，导致我的学习路线也趋于实践。</p><p>不过在我看来，写项目是最直接能体现出所想学的技术。我在学习一门新技术时，我通常会用项目或者博文的形式来总结我的学习过程。我也乐意花时间在这上面，并将其分享出来。当有其他人也在学习这门技术时，看到该项目或博文，我就认为非常有意义。</p><p><strong>我在学任何一门技术，会使用该技术写点东西；换言之是为了写点东西，而去学点不一样技术。</strong></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="技术心态的变化">技术心态的变化<a class="hash-link" href="#技术心态的变化" title="标题的直接链接">​</a></h2><p>如今来看，确实没那么想写代码，尤其是那种工作量大，重复性强的代码，而编写这些代码，其实与搬砖无任何区别，本质也是重复性与劳动性的任务。</p><p>曾经可能是因为接触得比较少，对于很多软件背后的原理及实现一概不知，所以看到啥就都想写写看，最终很多项目都成为半成品。</p><p>而随着越深入的学习，反而自己所想实现的东西，前人都已经帮我们实现好了。完全可以借用前人的代码，在此基础上学习与使用，而不必从头再来，耗费很多不必要的时间。</p><p>到最后为了实现一开始所想实现的东西，不用再费尽心思，去开源社区搜寻一番，总能找到与自己所要实现的类似的产品，此时只需要会看，会改，总能达到自己最终要实现的东西，有时候自己也称为了别人口中的 CV 工程师。</p><p>也正因如此，写代码的欲望就不再那么强烈。很多自认为无意义的代码或者是以后都不一定用得上的代码就少写了许多。于是乎缺少了很多自我思考与专研的时间，虽说也确实节省了很多不必要的时间，加快最终功能的实现，但这就是自己想要的编程生活吗？或者说这就是绝大多数人的编程生活。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="何来的自驱力">何来的自驱力<a class="hash-link" href="#何来的自驱力" title="标题的直接链接">​</a></h2><p>现在回想，是什么驱使我学习，我心中的答案是无能。</p><p>当你什么都不会时，或者是目前的能力还不足够将某件事情做好，你就会不断地焦虑，犹如热锅上的蚂蚁，想做但又怕做不好。</p><p>我有很多社会技能是欠缺的，比如人际交往，谈话技巧，合作行为等等，并且我本身也不愿去学习这些技能。正因如此，只有不断发挥自身长处，用自己所擅长的领域弥补自己的短板，以提升自我在社会的竞争力，以至于不那么容易被淘汰。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="返校的一年">返校的一年<a class="hash-link" href="#返校的一年" title="标题的直接链接">​</a></h2><p>今年也是我重归学校的一年，倘若，去年没有休学一年的话，如今我可能已经在外实习了，转瞬一年就过去了，如今的我还沉浸在当初休学和别人创业工作的日子。</p><p>也是因为当时休学急迫，后事做得并未完善，学校的一些课程并未申请缓考，最终视为缺考，即挂科。然后此前对大学的课程也是抱着可有可无的心态，也挂了几门课程，如果不是辅导员告知，我还有 34 学分要补（20 学分为严重预警，40 学分为退学或降级处理），我都不曾了解自己在学校挂了这么多科 😂。最离谱的是有个同班同学正好就被降级处理了，不过好在今年上半年并未挂科，加上下半年也重修了一些课程，还不至于离本科毕业证书越走越远。</p><p>回到学校后，就感觉如同坐牢一般，只不过环境相对舒适一番，尤其是在疫情当下更是如此，我这一年出校玩乐的次数好像不超过 10 次。当我仔细回想一下大学的真正意义是什么？貌似就是混个日子，混个证书。我也想不出大学能够有什么实质性的作用，也许是因为我所处的学校不行，换个好一点的大学或许都不是这样了。</p><p>不过今年回学校反而去参加了曾经都不怎么看上的社团（虽然现在也差不了多少），给社团写了些项目，主要也为了给自己重返学校带点个人知名度。但因为学校不是那么有名（臭名可能有），所以这里就不便放上相关信息。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="考研">考研<a class="hash-link" href="#考研" title="标题的直接链接">​</a></h3><p>明年的话我就大三下了，面对我的有条熟知的考研路。说实话，从目前来看，我对考研不抱有太大的希望，我是属于实践派的那种，我坚信没有什么是试不出来。背理论，刷八股，我很反感。</p><p>不知道由于什么原因，总感觉一段时间不写代码，真的就不会写代码。仿佛与自己写的代码成为了陌生人一般（所以写注释的重要性就体现出来了）</p><p>倘若读研的话，必然将会有数个月的时间重心不在代码上，到时候回来编写代码时，又发现自己好像又重新学了一遍似的。加之万一上岸失败的心理落差，会让自我觉得这几个月的努力都白费。而我又恰好是一位结果论者，即只在意结果，不在意过程如何。在别人的眼中，是难以看到你考研备战努力的过程，只会在意你上没上岸。这便是我不想考研因素之一。</p><p>但今年在互联网上所认识伙伴中挺多给我过于高的评价，都认为我作为一个学生，能有这水平是不是在某某牛逼的高校读书。然而并不是，我甚至都不好意思述说自己的高校，感觉是当下的污点。也正因如此反而让我有点过于焦虑，就从身份上，这不得让我萌生读研的一丝丝想法，也不至于死绝考研。</p><p>自我认为离真正的大佬还差很长的一段距离，我只是靠着三分钟热度，加上爱折腾，才维系下去，而那些真正的大佬是肯花费大量时间去编写他们所认为有意义的代码。</p><div class="theme-admonition theme-admonition-info alert alert--info admonition_LlT9"><div class="admonitionHeading_tbUL"><span class="admonitionIcon_kALy"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>信息</div><div class="admonitionContent_S0QG"><p>如果可以的话，在下方的留下你对我的评价与建议。我尽可能的争取在明年这时候完成你心目中我的样子。</p></div></div><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="结语">结语<a class="hash-link" href="#结语" title="标题的直接链接">​</a></h2><p>今年的年终就告一段落，与之前的年终总结相比，篇幅缩减了许多，主要感觉之前写的挺多流水账的，废话挺多的。也有一点是因为时间相对紧迫，其实 12 月我还没放假，都处于线上上课，线上考试的状态，而线上考试的方式我就不得吐槽了，提前打印给定的答题纸，题目以电脑的方式展示，最终将答案手写到答题纸上并通过手机扫描（扫描全能王）成 PDF 的格式提交，当然摄像头必然也是有的。总之麻烦事还是有的，还没到彻底闲下来闭关学习的时候。</p><p>按往常可能还有明年的规划，但我现在认为很多时候都难以依照自身意愿做事，而规划正好自己所设想美好的计划，很容易事与愿违。因为回顾过往的规划，有太多美好的计划，但在实际分析下也将变得不堪一击。不止项目需要可行性分析，人生计划同样需要，一些天马行空幻想，其实就不再有意义去记录了。</p><p><strong>坚持做自己想做的事情，而不是逼自己做不愿做的事情</strong>。这是我编程学习中座右铭，也是给予他人编程学习的建议。</p><p align="right">写于2022年12月22日    By 愧怍</p>]]></content:encoded>
            <category>年终总结</category>
            <category>summary</category>
        </item>
        <item>
            <title><![CDATA[GraphQL 实践与服务搭建]]></title>
            <link>https://kuizuo.cn/graphql-practice</link>
            <guid>graphql-practice</guid>
            <pubDate>Thu, 24 Nov 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[有关 GraphQL 介绍及上手实践，并在 Nest.js 和 Strapi 中搭建 GraphQL 服务]]></description>
            <content:encoded><![CDATA[<p><img loading="lazy" src="https://img.kuizuo.cn/320f3e5a66900d68e93de38154989948.png" class="img_ev3q"></p><blockquote><p>GraphQL 既是一种用于 API 的查询语言也是一个满足你数据查询的运行时。 GraphQL 对你的 API 中的数据提供了一套易于理解的完整描述，使得客户端能够准确地获得它需要的数据，而且没有任何冗余，也让 API 更容易地随着时间推移而演进，还能用于构建强大的开发者工具。</p></blockquote><p>大概率你听说过 GraphQL，知道它是一种与 Rest API 架构属于 API 接口的查询语言。但大概率你也与我一样没有尝试过 GraphQL。</p><p>事实上从 2012 年 Facebook 首次将 GraphQL 应用于移动应用，到 GraphQL 规范于 2015 年实现开源。可如今现状是 GraphQL 不温不火，时不时又有新的文章介绍，不知道的还以为是什么新技术。</p><div class="theme-admonition theme-admonition-tip alert alert--success admonition_LlT9"><div class="admonitionHeading_tbUL"><span class="admonitionIcon_kALy"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>目标</div><div class="admonitionContent_S0QG"><p>本文将上手使用 GraphQL，并用 Nestjs 与 Strapi 这两个 Node 框架搭建 GraphQL 服务。</p></div></div><p>关于 GraphQL 介绍，详见官网 <a href="https://graphql.cn/" target="_blank" rel="noopener noreferrer" title="GraphQL | A query language for your API">GraphQL | A query language for your API</a> 或相关介绍视频 <a href="https://www.bilibili.com/video/BV1fM4y1A7U1/" target="_blank" rel="noopener noreferrer" title="GraphQL 速览：React/Vue 的最佳搭档">GraphQL 速览：React/Vue 的最佳搭档</a></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="graphql-与-restful-api-相比">GraphQL 与 Restful API 相比<a class="hash-link" href="#graphql-与-restful-api-相比" title="标题的直接链接">​</a></h2><p><img loading="lazy" src="https://img.kuizuo.cn/9a7412200a062646b729c8419be28b35.jpeg" class="img_ev3q"></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="restful-api">Restful API<a class="hash-link" href="#restful-api" title="标题的直接链接">​</a></h3><p>Restful 架构的设计范式侧重于分配 HTTP 请求方法（GET、POST、PUT、PA TCH、DELETE）和 URL 端点之间的关系。如下图</p><p><img loading="lazy" src="https://img.kuizuo.cn/17fc41e2de8d829dc2d41e31a0775df3.png" class="img_ev3q"></p><p>但是实际复杂的业务中，单靠 Restful 接口，需要发送多条请求，例如获取博客中某篇博文数据与作者数据</p><div class="language-http codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-http codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">GET /blog/1</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">GET /blog/1/author</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>要么单独另写一个接口，如<code>getBlogAndAuthor</code>，这样直接为调用方“定制”一个接口，请求一条就得到就调用方想要的数据。但是另写一个<code>getBlogAndAuthor</code> 就破坏了 Restful API 接口风格，并且在复杂的业务中，比如说还要获取博文的评论等等，后端就要额外提供一个接口，可以说非常繁琐了。</p><p>有没有这样一个功能，将这些接口做一下聚合，然后<strong>将结果的集合返回给前端</strong>呢？在目前比较流行微服务架构体系下，有一个专门的中间层专门来处理这个事情，这个中间层叫 BFF（Backend For Frontend）。可以参阅 <a href="https://blog.csdn.net/qianduan666a/article/details/107271974" target="_blank" rel="noopener noreferrer" title="BFF——服务于前端的后端">BFF——服务于前端的后端</a></p><p><img loading="lazy" src="https://img.kuizuo.cn/image_Y4u9tNpZwR.png" class="img_ev3q"></p><p>但这些接口一般来说都比较重，里面有很多当前页面并不需要的字段，那还有没有一种请求：<strong>客户端只需要发送一次请求就能获取所需要的字段</strong></p><p>有，也就是接下来要说的 GraphQL</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="graphql">GraphQL<a class="hash-link" href="#graphql" title="标题的直接链接">​</a></h3><p><img loading="lazy" src="https://img.kuizuo.cn/8a141ec5fa73781d66fb2e1b60f9b49d.jpg" class="img_ev3q"></p><p>REST API 构建在请求方法（method）和端点（endpoint）之间的连接上，而 GraphQL API 被设计为只通过一个端点，即 <code>/graphql</code>，始终使用 POST 请求进行查询，其集中的 API 如 http://localhost:3000/graphql，所有的操作都通过这个接口来执行，这会在后面的操作中在展示到。</p><div class="theme-admonition theme-admonition-info alert alert--info admonition_LlT9"><div class="admonitionHeading_tbUL"><span class="admonitionIcon_kALy"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>信息</div><div class="admonitionContent_S0QG"><p>但是想要一条请求就能得到客户端想要的数据字段，那么服务端必然要做比较多的任务😟（想想也是，后端啥都不干，前端就啥都能获取，怎么可能嘛）。</p><p>而服务端要做的就是搭建一个 GraphQL 服务，这在后面也会操作到，也算是本文的重点。</p></div></div><p>接下来便会在客户端中体验下 GraphQL，看看 GraphQL 究竟有多好用。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="在线体验-graphql"><strong>在线体验 GraphQL</strong><a class="hash-link" href="#在线体验-graphql" title="标题的直接链接">​</a></h2><p>可以到 <a href="https://graphql.cn/learn/" target="_blank" rel="noopener noreferrer" title="官网">官网</a> 中简单尝试入门一下，在 <a href="https://studio.apollographql.com/sandbox/explorer" target="_blank" rel="noopener noreferrer" title="Studio (apollographql.com)">Studio</a> 可在线体验 GraphQL，也可以到 <a href="https://swapi-graphql.netlify.app/?query=%7B%0A%20%20person(personID:%201)%20%7B%0A%20%20%20%20name%0A%20%20%7D%0A%7D" target="_blank" rel="noopener noreferrer" title="SWAPI GraphQL API (swapi-graphql.netlify.app)">SWAPI GraphQL API</a> 中体验。</p><p>下面以 <code>apollographql</code> 为例，并查询 People 对象。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="query">query<a class="hash-link" href="#query" title="标题的直接链接">​</a></h3><p>查询所有 People 并且只获取 <code>name</code>、<code>gender</code>、<code>height</code> 字段</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_kvWUNtlUbf.png" class="img_ev3q"></p><p>查询 personID 为 1 的 Person 并且只获取 <code>name</code>，<code>gender</code>，<code>height</code> 字段</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_Msg9xwWFrl.png" class="img_ev3q"></p><p>查询 personID 为 2 的 Person 并且只获取 <code>name</code>，<code>eyeColor</code>、<code>skinColor</code>、<code>hairColor</code> 字段</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_hX0l36Acme.png" class="img_ev3q"></p><p>从上面查询案例中其实就可以发现，我只需要在 person 中写上想要获取的字段，GraphQL 便会返回带有该字段的数据。避免了返回结果中不必要的数据字段。</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    person</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        # 写上想获取的字段 </span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>如果你不想要 person 数据或者想要其他其他的数据，不用像 Restful API 那样请求多条接口，依旧请求<code>/graphql</code>，如</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_Z0b6ya-auG.png" class="img_ev3q"></p><div class="theme-admonition theme-admonition-info alert alert--info admonition_LlT9"><div class="admonitionHeading_tbUL"><span class="admonitionIcon_kALy"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>信息</div><div class="admonitionContent_S0QG"><p><strong>无论你想要什么数据，一次请求便可满足。</strong></p></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="mutation">mutation<a class="hash-link" href="#mutation" title="标题的直接链接">​</a></h3><p>GraphQL 的大部分讨论集中在数据获取（也是它的强项），但是任何完整的数据平台也都需要一个改变服务端数据的方法。即 CRUD。</p><p>GraphQL 提供了 <a href="https://graphql.cn/learn/queries/#mutations" target="_blank" rel="noopener noreferrer" title="变更（Mutations）">变更(Mutations)</a> 用于改变服务端数据，不过 <code>apollographql</code> 在线示例中并没有如 <code>createPeople</code> 字段支持 。这个片段在线体验中就无法体验到，后在后文中展示到。这里你只需要知道 GraphQL 能够执行基本的 CRUD 即可。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="fragmen-和-subscribtion">fragmen 和 subscribtion<a class="hash-link" href="#fragmen-和-subscribtion" title="标题的直接链接">​</a></h3><p>此外还有 <code>fragment </code> 与 <code>subscription</code> 就不做介绍。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="小结">小结<a class="hash-link" href="#小结" title="标题的直接链接">​</a></h3><p>尝试完上面这些操作后，可以非常明显的感受到 GraphQL 的优势与便利，本来是需要请求不同的 url，现在只需要请求 <code>/graphql</code>，对调用方（前端）来说非常友好，香是真的香。</p><p>可目前只是使用了别人配置好的 GraphQL 服务，让前端开发用了特别友好的 API。但是，对于后端开发而言，想要提供 GraphQL 服务可就不那么友善了。因为它不像传统的 restful 请求，需要专门配置 GraphQL 服务，而整个过程是需要花费一定的工作量（定义 Schema，Mutations 等等），前面也提到想要一条请求就能得到客户端想要的数据字段，那服务端必然需要额外的工作量。</p><p>不仅需要在后端中配置 GraphQL 服务，用于接收 GraphQL 查询并验证和执行，此外前端通常需要 GraphQL 客户端，来方便使用 GraphQL 获取数据，目前实用比较多的是<a href="https://www.apollographql.com/platform/" target="_blank" rel="noopener noreferrer" title="Apollo Graph">Apollo Graph</a>，不过本文侧重搭建GraphQL 服务，因此前端暂不演示如何使用 GraphQL。</p><p>你可能听过一句话是，<strong>graphq​l 大部分时间在折磨后端</strong>，并且要求比较严格的数据字段，但是好处都是前端。把工作量基本都丢给了后端，所以在遇到使用这门技术的公司，尤其是后端岗位就需要考虑有没有加班的可能了。</p><p>以下便会开始实际搭建 GraphQL 服务，这里会用 Nest.js 与 Strapi 分别实践演示。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="nestjs">Nest.js<a class="hash-link" href="#nestjs" title="标题的直接链接">​</a></h2><p>官方文档：<a href="https://docs.nestjs.com/graphql/quick-start" target="_blank" rel="noopener noreferrer" title="GraphQL + TypeScript | NestJS">GraphQL + TypeScript | NestJS</a></p><p>模块：<a href="https://github.com/nestjs/graphql" target="_blank" rel="noopener noreferrer" title="nestjs/graphql">nestjs/graphql</a></p><p>仓库本文实例代码仓库： <a href="https://github.com/kuizuo/nest-graphql-demo" target="_blank" rel="noopener noreferrer" title="kuizuo/nest-graphql-demo">kuizuo/nest-graphql-demo</a></p><p><strong>创建项目</strong></p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">nest new nest-graphql-demo</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p><strong>安装依赖</strong></p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token function" style="color:rgb(0, 0, 255)">npm</span><span class="token plain"> i @nestjs/graphql @nestjs/apollo graphql apollo-server-express</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p><strong>修改 app.module.ts</strong></p><div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">app.module.ts</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">Module</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'@nestjs/common'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">GraphQLModule</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'@nestjs/graphql'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">ApolloDriver</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> ApolloDriverConfig</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'@nestjs/apollo'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token decorator at operator" style="color:rgb(0, 0, 0)">@</span><span class="token decorator function" style="color:rgb(0, 0, 255)">Module</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  imports</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    GraphQLModule</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token generic-function function" style="color:rgb(0, 0, 255)">forRoot</span><span class="token generic-function generic class-name operator" style="color:rgb(0, 0, 0)">&lt;</span><span class="token generic-function generic class-name" style="color:rgb(38, 127, 153)">ApolloDriverConfig</span><span class="token generic-function generic class-name operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      driver</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> ApolloDriver</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      autoSchemaFile</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">AppModule</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="resolver">resolver<a class="hash-link" href="#resolver" title="标题的直接链接">​</a></h3><p>设置了<code>autoSchemaFile: true</code> ，nest.js 将会自动搜索整个项目所有以 <code>.resolver.ts</code> 为后缀的文件，将其解析为 <code>schema.gql</code> 比如说创建<code>app.resolver.ts</code></p><div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">app.resolver.ts</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">Resolver</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> Query</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'@nestjs/graphql'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token decorator at operator" style="color:rgb(0, 0, 0)">@</span><span class="token decorator function" style="color:rgb(0, 0, 255)">Resolver</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">AppResolver</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token decorator at operator" style="color:rgb(0, 0, 0)">@</span><span class="token decorator function" style="color:rgb(0, 0, 255)">Query</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> String</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 定义一个查询,并且返回字符类型</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">hello</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'hello world'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>在 <code>graphql</code> 中 <code>resolver</code> 叫解析器，与 <code>service</code> 类似（也需要在 <code>@Module</code> 中通过 <code>providers</code> 导入）。<code>resolver</code>主要包括<code>query</code>(查询数据)、<code>mutation</code>(增、删、改数据)、<code>subscription</code>(订阅，有点类型 <code>socket</code>)，在 <code>graphql</code> 项目中我们用 <code>resolver</code> 替换了之前的控制器。</p><p>这时候打开<a href="http://127.0.0.1:3000/graphql" target="_blank" rel="noopener noreferrer" title="http://127.0.0.1:3000/graphql">http://127.0.0.1:3000/graphql</a>，可以在右侧中看到自动生成的 Schema，这个 Schema 非常关键，决定了你客户端能够请求到什么数据。</p><p>尝试输入 GraphQL 的 query 查询（可以按 Ctrl + i 触发代码建议（Trigger Suggest），与 vscode 同理）</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_a3yl4oVtSU.png" class="img_ev3q"></p><p>此时点击执行，可以得到右侧结果，即<code>app.resolver.ts</code> 中 <code>hello</code> 函数所定义的返回体。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_bK9bvZ3QMm.png" class="img_ev3q"></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="code-first-与-schema-first"><a href="https://docs.nestjs.com/graphql/quick-start#code-first" target="_blank" rel="noopener noreferrer">Code first</a> 与 <a href="https://docs.nestjs.com/graphql/quick-start#schema-first" target="_blank" rel="noopener noreferrer">Schema first</a><a class="hash-link" href="#code-first-与-schema-first" title="标题的直接链接">​</a></h3><p>在 nestjs 中有 <a href="https://docs.nestjs.com/graphql/quick-start#code-first" target="_blank" rel="noopener noreferrer">Code first</a> 与 <a href="https://docs.nestjs.com/graphql/quick-start#schema-first" target="_blank" rel="noopener noreferrer">Schema first</a> 两种方式来生成上面的 Schema，从名字上来看，前者是优先定义代码会自动生成 Schema，而后者是传统方式先定义Schema。</p><p>在上面一开始的例子中是 Code First 方式，通常使用该方式即可，无需关心 Schema 是如何生成的。下文也会以 Code First 方式来编写 GraphQL 服务。</p><p>也可到官方示例仓库中 <a href="https://github.com/nestjs/nest/tree/master/sample/31-graphql-federation-code-first" target="_blank" rel="noopener noreferrer">nest/sample/31-graphql-federation-code-first</a> 和 <a href="https://github.com/nestjs/nest/tree/master/sample/32-graphql-federation-schema-first" target="_blank" rel="noopener noreferrer">nest/sample/32-graphql-federation-schema-first</a> 查看两者代码上的区别。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="快速生成-graphql-模块">快速生成 GraphQL 模块<a class="hash-link" href="#快速生成-graphql-模块" title="标题的直接链接">​</a></h3><p>nest 提供 cli 的方式来快速生成 GraphQL 模块</p><div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">nest g resource </span><span class="token operator" style="color:rgb(0, 0, 0)">&lt;</span><span class="token plain">name</span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p><img loading="lazy" src="https://img.kuizuo.cn/image_L9yYAn78Dw.png" class="img_ev3q"></p><p>比如创建一个 blog 模块</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">nest g resource blog --no-spec</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">? What transport layer </span><span class="token keyword" style="color:rgb(0, 0, 255)">do</span><span class="token plain"> you use? GraphQL </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">code first</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">? Would you like to generate CRUD entry points? Yes</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">CREATE src/blog/blog.module.ts </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">217</span><span class="token plain"> bytes</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">CREATE src/blog/blog.resolver.ts </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">1098</span><span class="token plain"> bytes</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">CREATE src/blog/blog.resolver.spec.ts </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">515</span><span class="token plain"> bytes</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">CREATE src/blog/blog.service.ts </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">623</span><span class="token plain"> bytes</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">CREATE src/blog/blog.service.spec.ts </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">446</span><span class="token plain"> bytes</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">CREATE src/blog/dto/create-blog.input.ts </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">196</span><span class="token plain"> bytes</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">CREATE src/blog/dto/update-blog.input.ts </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">243</span><span class="token plain"> bytes</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">CREATE src/blog/entities/blog.entity.ts </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">187</span><span class="token plain"> bytes</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">UPDATE src/app.module.ts </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">643</span><span class="token plain"> bytes</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>便会生成如下文件</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_XemqTcfz_D.png" class="img_ev3q"></p><div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">blog.resolver.ts</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">Resolver</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> Query</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> Mutation</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> Args</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> Int</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'@nestjs/graphql'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">BlogService</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'./blog.service'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">Blog</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'./entities/blog.entity'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">CreateBlogInput</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'./dto/create-blog.input'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">UpdateBlogInput</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'./dto/update-blog.input'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token decorator at operator" style="color:rgb(0, 0, 0)">@</span><span class="token decorator function" style="color:rgb(0, 0, 255)">Resolver</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> Blog</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">BlogResolver</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">constructor</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">private</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">readonly</span><span class="token plain"> blogService</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> BlogService</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token decorator at operator" style="color:rgb(0, 0, 0)">@</span><span class="token decorator function" style="color:rgb(0, 0, 255)">Mutation</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> Blog</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">createBlog</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token decorator at operator" style="color:rgb(0, 0, 0)">@</span><span class="token decorator function" style="color:rgb(0, 0, 255)">Args</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'createBlogInput'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> createBlogInput</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> CreateBlogInput</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">blogService</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">create</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">createBlogInput</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token decorator at operator" style="color:rgb(0, 0, 0)">@</span><span class="token decorator function" style="color:rgb(0, 0, 255)">Query</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">Blog</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">name</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'blogs'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">findAll</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">blogService</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">findAll</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token decorator at operator" style="color:rgb(0, 0, 0)">@</span><span class="token decorator function" style="color:rgb(0, 0, 255)">Query</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> Blog</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">name</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'blog'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">findOne</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token decorator at operator" style="color:rgb(0, 0, 0)">@</span><span class="token decorator function" style="color:rgb(0, 0, 255)">Args</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'id'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token function-variable function" style="color:rgb(0, 0, 255)">type</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> Int</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> id</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(0, 112, 193)">number</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">blogService</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">findOne</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token decorator at operator" style="color:rgb(0, 0, 0)">@</span><span class="token decorator function" style="color:rgb(0, 0, 255)">Mutation</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> Blog</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">updateBlog</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token decorator at operator" style="color:rgb(0, 0, 0)">@</span><span class="token decorator function" style="color:rgb(0, 0, 255)">Args</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'updateBlogInput'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> updateBlogInput</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> UpdateBlogInput</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">blogService</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">update</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">updateBlogInput</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> updateBlogInput</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token decorator at operator" style="color:rgb(0, 0, 0)">@</span><span class="token decorator function" style="color:rgb(0, 0, 255)">Mutation</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> Blog</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">removeBlog</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token decorator at operator" style="color:rgb(0, 0, 0)">@</span><span class="token decorator function" style="color:rgb(0, 0, 255)">Args</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'id'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token function-variable function" style="color:rgb(0, 0, 255)">type</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> Int</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> id</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(0, 112, 193)">number</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">blogService</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">remove</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>此时 Schema 如下</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_sJCQpllOXK.png" class="img_ev3q"></p><p>不过<code>nest cli</code>创建的<code>blog.service.ts</code> 只是示例代码，并没有实际业务的代码。</p><p>此外<code>blog.entity.ts</code>也不为数据库实体类，因此这里引入<code>typeorm</code>，并使用<code>sqlite3</code></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="集成-typeorm">集成 Typeorm<a class="hash-link" href="#集成-typeorm" title="标题的直接链接">​</a></h3><p>安装依赖</p><div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">pnpm install </span><span class="token decorator at operator" style="color:rgb(0, 0, 0)">@</span><span class="token decorator function" style="color:rgb(0, 0, 255)">nestjs</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain">typeorm typeorm sqlite3</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">app.module.ts</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">Module</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'@nestjs/common'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">AppController</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'./app.controller'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">AppService</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'./app.service'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">GraphQLModule</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'@nestjs/graphql'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">ApolloDriver</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> ApolloDriverConfig</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'@nestjs/apollo'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">AppResolver</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'./app.resolver'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">BlogModule</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'./blog/blog.module'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">TypeOrmModule</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'@nestjs/typeorm'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token decorator at operator" style="color:rgb(0, 0, 0)">@</span><span class="token decorator function" style="color:rgb(0, 0, 255)">Module</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  imports</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    TypeOrmModule</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">forRoot</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      type</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'sqlite'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      database</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'db.sqlite3'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      entities</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">__dirname </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'/**/*.entity{.ts,.js}'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      synchronize</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    GraphQLModule</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token generic-function function" style="color:rgb(0, 0, 255)">forRoot</span><span class="token generic-function generic class-name operator" style="color:rgb(0, 0, 0)">&lt;</span><span class="token generic-function generic class-name" style="color:rgb(38, 127, 153)">ApolloDriverConfig</span><span class="token generic-function generic class-name operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      driver</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> ApolloDriver</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      autoSchemaFile</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      playground</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    AppModule</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    BlogModule</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  controllers</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">AppController</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  providers</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">AppService</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> AppResolver</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">AppModule</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>将 <code>blog.entity.ts</code> 改成实体类，代码为</p><div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">blog.entity.ts</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">ObjectType</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> Field</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'@nestjs/graphql'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  Column</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  Entity</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  PrimaryGeneratedColumn</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  CreateDateColumn</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  UpdateDateColumn</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'typeorm'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token decorator at operator" style="color:rgb(0, 0, 0)">@</span><span class="token decorator function" style="color:rgb(0, 0, 255)">ObjectType</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token decorator at operator" style="color:rgb(0, 0, 0)">@</span><span class="token decorator function" style="color:rgb(0, 0, 255)">Entity</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">Blog</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token decorator at operator" style="color:rgb(0, 0, 0)">@</span><span class="token decorator function" style="color:rgb(0, 0, 255)">Field</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> Int</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token decorator at operator" style="color:rgb(0, 0, 0)">@</span><span class="token decorator function" style="color:rgb(0, 0, 255)">PrimaryGeneratedColumn</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  id</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(0, 112, 193)">number</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token decorator at operator" style="color:rgb(0, 0, 0)">@</span><span class="token decorator function" style="color:rgb(0, 0, 255)">Field</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token decorator at operator" style="color:rgb(0, 0, 0)">@</span><span class="token decorator function" style="color:rgb(0, 0, 255)">Column</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  title</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(0, 112, 193)">string</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token decorator at operator" style="color:rgb(0, 0, 0)">@</span><span class="token decorator function" style="color:rgb(0, 0, 255)">Field</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token decorator at operator" style="color:rgb(0, 0, 0)">@</span><span class="token decorator function" style="color:rgb(0, 0, 255)">Column</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">type</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'text'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  content</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(0, 112, 193)">string</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token decorator at operator" style="color:rgb(0, 0, 0)">@</span><span class="token decorator function" style="color:rgb(0, 0, 255)">Field</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token decorator at operator" style="color:rgb(0, 0, 0)">@</span><span class="token decorator function" style="color:rgb(0, 0, 255)">CreateDateColumn</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">name</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'created_at'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> comment</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'创建时间'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  createdAt</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> Date</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token decorator at operator" style="color:rgb(0, 0, 0)">@</span><span class="token decorator function" style="color:rgb(0, 0, 255)">Field</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token decorator at operator" style="color:rgb(0, 0, 0)">@</span><span class="token decorator function" style="color:rgb(0, 0, 255)">UpdateDateColumn</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">name</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'updated_at'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> comment</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'更新时间'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  updatedAt</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> Date</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>其中 <code>@ObjectType()</code> 装饰器让 <code>@nestjs/graphql</code> 自动让其视为一个 <code>type Blog</code></p><p>而 <code>@Field()</code> 则是作为可展示的字段，比如 <code>password</code> 字段无需返回，就不必要加该装饰器。</p><div class="theme-admonition theme-admonition-tip alert alert--success admonition_LlT9"><div class="admonitionHeading_tbUL"><span class="admonitionIcon_kALy"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>提示</div><div class="admonitionContent_S0QG"><p>如果你认为 添加 <code>@Field()</code> 是件繁琐的事情（nest 官方自然也想到），于是提供了 <a href="https://docs.nestjs.com/graphql/cli-plugin" target="_blank" rel="noopener noreferrer">GraphQL + TypeScript - CLI Plugin </a> 用于省略 <code>@Field()</code> 等其他操作。（类似于语法糖）</p><p>借用官方的话: </p><blockquote><p>Thus, you won't have to struggle with @Field decorators scattered throughout the code.</p></blockquote><p>因此，您不必为分散在代码中的@Field 装饰符而烦恼。</p></div></div><div class="theme-admonition theme-admonition-caution alert alert--warning admonition_LlT9"><div class="admonitionHeading_tbUL"><span class="admonitionIcon_kALy"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>警告</div><div class="admonitionContent_S0QG"><p><code>@nestjs/graphql</code> 会将 typescript 的 number 类型视为 Float，所以需要转成 Int 类型，即 <code>@Field(() =&gt; Int)</code></p></div></div><p>为 BlogService 编写 CRUD 数据库业务代码，并在 dto 编写参数效验代码，这里简单暂时部分代码。</p><div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">blog.service.ts</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">Injectable</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'@nestjs/common'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">InjectRepository</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'@nestjs/typeorm'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">Repository</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'typeorm'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">CreateBlogInput</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'./dto/create-blog.input'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">UpdateBlogInput</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'./dto/update-blog.input'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">Blog</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'./entities/blog.entity'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token decorator at operator" style="color:rgb(0, 0, 0)">@</span><span class="token decorator function" style="color:rgb(0, 0, 255)">Injectable</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">BlogService</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">constructor</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token decorator at operator" style="color:rgb(0, 0, 0)">@</span><span class="token decorator function" style="color:rgb(0, 0, 255)">InjectRepository</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">Blog</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">private</span><span class="token plain"> blogRepository</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> Repository</span><span class="token operator" style="color:rgb(0, 0, 0)">&lt;</span><span class="token plain">Blog</span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">create</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">createBlogInput</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> CreateBlogInput</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">blogRepository</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">save</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">createBlogInput</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">findAll</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">blogRepository</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">find</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">findOne</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">id</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(0, 112, 193)">number</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">blogRepository</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">findOneBy</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">async</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">update</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">id</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(0, 112, 193)">number</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> updateBlogInput</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> UpdateBlogInput</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> blog </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">blogRepository</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">findOneBy</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> item </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token operator" style="color:rgb(0, 0, 0)">...</span><span class="token plain">blog</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">...</span><span class="token plain">updateBlogInput</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">blogRepository</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">save</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">item</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">remove</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">id</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(0, 112, 193)">number</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">blogRepository</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">delete</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">create-blog.input.ts</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">InputType</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> Field</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'@nestjs/graphql'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token decorator at operator" style="color:rgb(0, 0, 0)">@</span><span class="token decorator function" style="color:rgb(0, 0, 255)">InputType</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">CreateBlogInput</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token decorator at operator" style="color:rgb(0, 0, 0)">@</span><span class="token decorator function" style="color:rgb(0, 0, 255)">Field</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  title</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(0, 112, 193)">string</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token decorator at operator" style="color:rgb(0, 0, 0)">@</span><span class="token decorator function" style="color:rgb(0, 0, 255)">Field</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  content</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(0, 112, 193)">string</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>此时</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_7-twN56Aym.png" class="img_ev3q"></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="crud">CRUD<a class="hash-link" href="#crud" title="标题的直接链接">​</a></h3><p>下面将演示 graphql 的 Mutation。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="新增">新增<a class="hash-link" href="#新增" title="标题的直接链接">​</a></h4><p><img loading="lazy" src="https://img.kuizuo.cn/image_NPqShDN3Pl.png" class="img_ev3q"></p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="修改">修改<a class="hash-link" href="#修改" title="标题的直接链接">​</a></h4><p><img loading="lazy" src="https://img.kuizuo.cn/image_c4ycwRs-po.png" class="img_ev3q"></p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="删除">删除<a class="hash-link" href="#删除" title="标题的直接链接">​</a></h4><p><img loading="lazy" src="https://img.kuizuo.cn/image_xpkHhpS1-K.png" class="img_ev3q"></p><p>Query 就不在演示。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="小结-1">小结<a class="hash-link" href="#小结-1" title="标题的直接链接">​</a></h3><p>至此，在 Nest.js 中配置 GraphQL 服务的就演示到此，从这里来看，Nest.js 配置 GraphQL 服务还算比较轻松，但是做了比较多的工作量，创建 resolver，创建 modal（或在已有实体添加装饰器），不过本文案例中只演示了基本的 CRUD 操作，实际业务中还需要涉及鉴权，限流等等。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="strapi">Strapi<a class="hash-link" href="#strapi" title="标题的直接链接">​</a></h2><p>Strapi 官方提供 <a href="https://market.strapi.io/plugins/@strapi-plugin-graphql" target="_blank" rel="noopener noreferrer" title="GraphQL插件">GraphQL 插件</a> 免去了配置的繁琐。更具体的配置参见 <a href="https://docs.strapi.io/developer-docs/latest/development/plugins/graphql.html" target="_blank" rel="noopener noreferrer" title="GraphQL - Strapi Developer Documentation">GraphQL - Strapi Developer Documentation</a></p><p>这里我就选用 <a href="https://github.com/kuizuo/vitesse-nuxt-strapi" target="_blank" rel="noopener noreferrer" title="kuizuo/vitesse-nuxt-strapi">kuizuo/vitesse-nuxt-strapi</a> 作为演示，并为其提供 graphQL 支持。</p><p>strapi 安装</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">npm install @strapi</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain">plugin</span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain">graphql</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>接着启动 strapi 项目，并在浏览器打开 graphql 控制台 <a href="http://localhost:1337/graphql" target="_blank" rel="noopener noreferrer" title="http://localhost:1337/graphql">http://localhost:1337/graphql</a>，以下将演示几个应用场景。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="例子">例子<a class="hash-link" href="#例子" title="标题的直接链接">​</a></h3><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="查询所有-todo">查询所有 todo<a class="hash-link" href="#查询所有-todo" title="标题的直接链接">​</a></h4><p><img loading="lazy" src="https://img.kuizuo.cn/image_4GFUs8CmQJ.png" class="img_ev3q"></p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="查询-id-为-2-的-todo">查询 id 为 2 的 todo<a class="hash-link" href="#查询-id-为-2-的-todo" title="标题的直接链接">​</a></h4><p><img loading="lazy" src="https://img.kuizuo.cn/image_NMM4e3L_y8.png" class="img_ev3q"></p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="查询-id-为-2-的-todo-并只返回-value-属性">查询 id 为 2 的 todo 并只返回 value 属性<a class="hash-link" href="#查询-id-为-2-的-todo-并只返回-value-属性" title="标题的直接链接">​</a></h4><p><img loading="lazy" src="https://img.kuizuo.cn/image_E1eWrzjaEs.png" class="img_ev3q"></p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="新增-todo">新增 todo<a class="hash-link" href="#新增-todo" title="标题的直接链接">​</a></h4><p><img loading="lazy" src="https://img.kuizuo.cn/image_pclR7Zb6TE.png" class="img_ev3q"></p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="更新-todo">更新 todo<a class="hash-link" href="#更新-todo" title="标题的直接链接">​</a></h4><p><img loading="lazy" src="https://img.kuizuo.cn/image_g3RJL7RQWR.png" class="img_ev3q"></p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="删除-todo">删除 todo<a class="hash-link" href="#删除-todo" title="标题的直接链接">​</a></h4><p><img loading="lazy" src="https://img.kuizuo.cn/image_m7s17q2TG0.png" class="img_ev3q"></p><p>由于 <a href="https://strapi.nuxtjs.org/" target="_blank" rel="noopener noreferrer" title="Nuxt Strapi">Nuxt Strapi</a> 提供 <a href="https://strapi.nuxtjs.org/usage#usestrapigraphql" target="_blank" rel="noopener noreferrer" title="useStrapiGraphQL">useStrapiGraphQL</a> 可以非常方便是在客户端调用 GraphQL 服务。</p><div class="language-html codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-html codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">script</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">setup</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">lang</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">ts</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">  </span><span class="token script language-javascript keyword" style="color:rgb(0, 0, 255)">const</span><span class="token script language-javascript"> route </span><span class="token script language-javascript operator" style="color:rgb(0, 0, 0)">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript function" style="color:rgb(0, 0, 255)">useRoute</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">  </span><span class="token script language-javascript keyword" style="color:rgb(0, 0, 255)">const</span><span class="token script language-javascript"> graphql </span><span class="token script language-javascript operator" style="color:rgb(0, 0, 0)">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript function" style="color:rgb(0, 0, 255)">useStrapiGraphQL</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">  </span><span class="token script language-javascript comment" style="color:rgb(0, 128, 0)">// Option 1: use inline query</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">  </span><span class="token script language-javascript keyword" style="color:rgb(0, 0, 255)">const</span><span class="token script language-javascript"> restaurant </span><span class="token script language-javascript operator" style="color:rgb(0, 0, 0)">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript keyword control-flow" style="color:rgb(0, 0, 255)">await</span><span class="token script language-javascript"> </span><span class="token script language-javascript function" style="color:rgb(0, 0, 255)">graphql</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token script language-javascript template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token script language-javascript template-string string" style="color:rgb(163, 21, 21)"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript template-string string" style="color:rgb(163, 21, 21)">  query {</span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript template-string string" style="color:rgb(163, 21, 21)">    restaurant(id: </span><span class="token script language-javascript template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">${</span><span class="token script language-javascript template-string interpolation">route</span><span class="token script language-javascript template-string interpolation punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token script language-javascript template-string interpolation property-access">params</span><span class="token script language-javascript template-string interpolation punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token script language-javascript template-string interpolation property-access">id</span><span class="token script language-javascript template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token script language-javascript template-string string" style="color:rgb(163, 21, 21)">) {</span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript template-string string" style="color:rgb(163, 21, 21)">      data {</span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript template-string string" style="color:rgb(163, 21, 21)">        id</span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript template-string string" style="color:rgb(163, 21, 21)">        attributes {</span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript template-string string" style="color:rgb(163, 21, 21)">          name</span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript template-string string" style="color:rgb(163, 21, 21)">        }</span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript template-string string" style="color:rgb(163, 21, 21)">      }</span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript template-string string" style="color:rgb(163, 21, 21)">    }</span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript template-string string" style="color:rgb(163, 21, 21)">  }</span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript template-string string" style="color:rgb(163, 21, 21)"></span><span class="token script language-javascript template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">  </span><span class="token script language-javascript comment" style="color:rgb(0, 128, 0)">// Option 2: use imported query</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">  </span><span class="token script language-javascript keyword" style="color:rgb(0, 0, 255)">const</span><span class="token script language-javascript"> restaurant </span><span class="token script language-javascript operator" style="color:rgb(0, 0, 0)">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript keyword control-flow" style="color:rgb(0, 0, 255)">await</span><span class="token script language-javascript"> </span><span class="token script language-javascript function" style="color:rgb(0, 0, 255)">graphql</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token script language-javascript">query</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token script language-javascript literal-property property">id</span><span class="token script language-javascript operator" style="color:rgb(0, 0, 0)">:</span><span class="token script language-javascript"> route</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token script language-javascript property-access">params</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token script language-javascript property-access">id</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript"></span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">script</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="小结-2">小结<a class="hash-link" href="#小结-2" title="标题的直接链接">​</a></h3><p>对于 Strapi 来说，搭建 GraphQL 服务基本没有配置的负担，安装一个插件，即可配合 Strapi 的 content-type 来提供 GraphQL 服务。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="总结">总结<a class="hash-link" href="#总结" title="标题的直接链接">​</a></h2><p><strong>GraphQL</strong> 翻译过来为 <strong>图表 Query Language</strong>，我所理解的理念是通过 json 数据格式的方式去写 SQL，而且有种前端人员在写 sql 语句。在我看来 GraphQL 更多是业务数据特别复制的情况下使用，往往能够事半功倍。但对于本文中示例的代码而言，GraphQL 反倒有点过于先进了。</p><p>如今看来，GraphQL 还处于不温不火的状态，目前更多的站点主流还是使用 Restful API 架构。我不过我猜测，主要还是大多数业务没有 API 架构的升级的需求，原有的 Restful API 虽说不够优雅，但是也能够满足业务的需求，反而 GraphQL 是一个新项目 API 架构的选择，但不是一个必须的选择。</p><p>至于如何选择，可以参阅官方 <a href="https://graphql.cn/learn/best-practices/" target="_blank" rel="noopener noreferrer">GraphQL 最佳实践</a>，至于说有没有必要学 GraphQL，这篇文章 <a href="https://blog.csdn.net/kevin_tech/article/details/120735500" target="_blank" rel="noopener noreferrer">都快 2022 年了 GraphQL 还值得学吗</a> 能给你答案。我的建议是了解即可，新项目可以考虑使用，就别想着用 GraphQL 来重构原有的 API 接口，工作量将会十分巨大，并且还可能是费力不讨好的事。反正我认为这门技术不像 Git 这种属于必学的技能，我的五星评分是⭐⭐</p><p>但多了解一门技术，就是工作面试的资本。回想我为何尝试 GraphQL，就是因为我无意间看到了一份 ts 全栈的远程面试招聘，在这份招聘单中写到 【会 graphql 编写是加分项】。所以抱着这样的态度去尝试了一番，说不准未来就是因为 graphql 让我拿到该 offer。当然也是因为很早之前就听闻 GraphQL，想亲手目睹下是否有所谓的那么神奇。</p>]]></content:encoded>
            <category>api</category>
            <category>graphql</category>
            <category>nest</category>
            <category>strapi</category>
        </item>
        <item>
            <title><![CDATA[重构kz-admin]]></title>
            <link>https://kuizuo.cn/refactor-kz-admin</link>
            <guid>refactor-kz-admin</guid>
            <pubDate>Mon, 07 Nov 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[kz-admin 是一个基于 NestJs + TypeScript + TypeORM + Redis + MySql + Vben Admin 编写的一款前后端分离的权限管理系统]]></description>
            <content:encoded><![CDATA[<p><img loading="lazy" src="https://img.kuizuo.cn/logo_irKdpu5Epv.png" class="img_ev3q"></p><blockquote><p>kz-admin 使用 NestJs + TypeScript + TypeORM + Redis + MySql + Vben Admin
等技术栈，并采用 monorepo 管理项目，希望这个项目在 ts 全栈的路上能够帮助到你。</p></blockquote><p>详细介绍可以参见 <a href="/kz-admin">kz-admin后台管理系统</a></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="为何重构">为何重构<a class="hash-link" href="#为何重构" title="标题的直接链接">​</a></h2><p>前段时间基于我的 <a href="https://github.com/kuizuo/kz-admin" target="_blank" rel="noopener noreferrer" title="kz-admin">kz-admin</a>
模板写了一个link-admin的项目（可以访问 <a href="http://link.kuizuo.cn/" target="_blank" rel="noopener noreferrer" title="link.kuizuo.cn">link.kuizuo.cn</a> 在线体验，账号 admin，密码a123456），是一个“一次性”充值链接管理系统，具体自行体验即可（项目未开源）。</p><p>该项目有前端管理页面，后端服务，和一个链接使用页面，共三个项目。</p><p>每次启动时候，都需要进入到对应项目下，打开终端，输入命令。要么使用<code>npm-run-all</code> 来批量执行 dev 与 build 命令。</p><p>想到后续项目的应用场景大概率也可能是多项目的，于是就准备使用 turborepo 将项目重构为 monorepo 管理，将前后端项目都统一放到一个仓库中，并且将 nestjs 版本升级到 v9，顺便在完善一下api接口文档，并提供 <a href="https://www.apifox.cn/" target="_blank" rel="noopener noreferrer" title="ApiFox">ApiFox</a> 文档。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="monorepo重构">monorepo重构<a class="hash-link" href="#monorepo重构" title="标题的直接链接">​</a></h2><p>monorepo的重构相对简单，首先使用 <a href="https://turbo.build/repo/docs/getting-started/create-new" target="_blank" rel="noopener noreferrer" title="Turborepo">Turborepo</a> 新建一个 monorepo 的仓库，目录结构如下</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_Svd1WZKBdf.png" class="img_ev3q"></p><p>将 packages 与 apps 下的文件清空，然后把原 kz-admin 的<a href="https://github.com/kuizuo/kz-vue-admin" target="_blank" rel="noopener noreferrer">前端项目</a>与<a href="https://github.com/kuizuo/kz-nest-admin" target="_blank" rel="noopener noreferrer">后端项目</a>放到 apps 下。修改下 README.md 与 package.json 其启动命令即可。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_eYL2rKrakb.png" class="img_ev3q"></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="依赖升级">依赖升级<a class="hash-link" href="#依赖升级" title="标题的直接链接">​</a></h2><p>我原先的nestjs依赖是8.0.0，但是技术发展太快，nestjs
9.0.0都已经发布了，所以这次更新属于大版本更新，通常属于<strong>破坏性更新，可能会导致原代码失效</strong>，所以更新依赖要慎重。</p><p>我使用的是<a href="https://github.com/antfu/taze" target="_blank" rel="noopener noreferrer" title="antfu/taze">antfu/taze</a> 来更新依赖，也可以使用 <code>yarn upgrade-interactive -- latest</code>。</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">npx taze </span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain">r</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>由于此次属于大版本更新，所以使用<code>taze major</code>，小版本则使用 <code>taze minor</code>。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_xJ_Bh1NZih.png" class="img_ev3q"></p><p><code>npx taze major -r -w</code> 将更新依赖写入到package.json下，接着执行pnpm i更新依赖即可。</p><p>既然都将nestjs更新了，那么nestjs相关生态的库自然也是要更新的，于是就遇到的typeorm 0.2.0 → 0.3.0用法的问题，主要是将findOne等方法改写，如 <code>findOne(id) → findOneBy({ id })</code> 。整个过程还算顺利，</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="使用apifox编写接口文档与接口测试">使用ApiFox编写接口文档与接口测试<a class="hash-link" href="#使用apifox编写接口文档与接口测试" title="标题的直接链接">​</a></h2><p>在原项目中我Swagger写的其实够完善，但是在代码协同上只给前端一个Swagger地址不是很友好。但直到我接触并体验一段时间ApiFox后，让我更想去编写Swagger，给前端同事一个良好的Api接口测试体验，因为我自身也作为前端开发者，我太清楚API接口文档的重要性了。</p><p>其实早听闻ApiFox，但当时我还在用ApiPost，觉得ApiPost足够好用就没有更换的欲望。直到看到别人给我分享用ApiFox编写的接口文档时，让我眼前一亮，至于有多好用，可以参阅官方的介绍视频<a href="https://www.bilibili.com/video/BV1ae4y1y7bf" target="_blank" rel="noopener noreferrer" title="21分钟学会Apifox">21分钟学会Apifox</a>。发自使用者内心的好用，下面会有些实际接口案例来说明到底有多好用。</p><p>你可以访问 <a href="https://admin.kuizuo.cn/swagger-ui" target="_blank" rel="noopener noreferrer" title="https://admin.kuizuo.cn/swagger-ui">https://admin.kuizuo.cn/swagger-ui</a> 来查看kz-admin的Swagger文档</p><p>json格式为<a href="https://admin.kuizuo.cn/swagger-ui/json" target="_blank" rel="noopener noreferrer" title="https://admin.kuizuo.cn/swagger-ui/json">https://admin.kuizuo.cn/swagger-ui/json</a>，用于导入ApiFox中。</p><p>ApiFox在线链接: <a href="https://www.apifox.cn/apidoc/shared-7a07def2-5b82-4c71-bf57-915514f61f25" target="_blank" rel="noopener noreferrer" title="https://www.apifox.cn/apidoc/shared-7a07def2-5b82-4c71-bf57-915514f61f25">https://www.apifox.cn/apidoc/shared-7a07def2-5b82-4c71-bf57-915514f61f25</a> 访问密码: kz-admin</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="数据实体">数据实体<a class="hash-link" href="#数据实体" title="标题的直接链接">​</a></h3><p>本次重构对于数据实体花费的时间比较多，主要就是数据实体重命名，如</p><ul><li><p>CreateUserDto → UserCreateDto</p></li><li><p>UpdateUserDto → UserUpdateDto</p></li><li><p>DeleteUserDto → UserDeleteDto</p></li><li><p>PageUserDto→ UserPageDto</p></li><li><p>...</p></li></ul><p>将操作动词后置，这样做好处就是不用从一堆<code>CreatxxxxDto</code>中找一个<code>CreateUserDto</code>，而是转变成从几个<code>UserxxxxDto</code>找<code>UserCreateDto</code>，就像下图这样，左侧Swagger，右侧ApiFox，在数据实体比较多的时候显示的会更加直观。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_a4g_9OfyUw.png" class="img_ev3q"></p><p><img loading="lazy" src="https://img.kuizuo.cn/image_avg9_2fE5G.png" class="img_ev3q"></p><p>当然在ApiFox中可以通过搜索来筛选模型，但在开发体验方面，我认为此次重命名重构还是非常有必要的。</p><p>定义数据实体（Schemas）非常重要，这样我们就能知道该请求接口应该传递什么参数，会接收到什么样的数据。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="接口文档">接口文档<a class="hash-link" href="#接口文档" title="标题的直接链接">​</a></h3><p>Apifox是以文档作为驱动的，可以说把Swagger文档写好，Apifox就会好用。直接上例子</p><p>以用户新增和分页查询用户为例，直接上效果图（左侧是ApiFox，右侧为Swagger代码）</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_Zs3cEmA7KD.png" class="img_ev3q"></p><p><img loading="lazy" src="https://img.kuizuo.cn/image_WLjlJRNBlH.png" class="img_ev3q"></p><p>在定义完Swagger并通过ApiFox导入后，不用修改ApiFox就能得到上述效果。这里强烈建议将ApiFox接口问题，与nestjs的Swagger代码进行对比，就能体会到写好Swagger就能得到一份如此优雅的Api文档。</p><p>做前端和做后端看到这文档，这不得发自内心的赞美。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="了解更多">了解更多<a class="hash-link" href="#了解更多" title="标题的直接链接">​</a></h3><p>此外 ApiFox 的好处远远不止于此，篇幅有限，好东西不是一句两句就能说明白的东西，建议自行体验一番，绝对会有不一样的收获。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="回顾项目">回顾项目<a class="hash-link" href="#回顾项目" title="标题的直接链接">​</a></h2><p>Vben admin 是我21年6月当时接触 Vue3 的第一个项目，在当时Vue3测试版已经发布，而vue-element-admin都早已烂大街了，也有点审美疲劳了。想给自己换一个后台管理系统的模板，恰好无意间刷到了 Vben Admin，管理面板的效果让我眼前一亮，迄今为止我都认为非常耐看。</p><p>但是Vben Admin仅仅只是前端模板与mock数据，并无后端数据，于是就正好利用我使用的 Node 后端框架 Nestjs 来编写后端服务。但当时项目并不完善，在我编写了几个相似的后端管理的项目后，将核心部分抽离出来，并将其封装出来，kz-admin也就此诞生。</p><p>鸣谢 <a href="https://github.com/hackycy/sf-nest-admin" target="_blank" rel="noopener noreferrer">hackycy/sf-nest-admin</a>，我的后端 nestjs 架构与部分代码都借鉴该项目。</p><p>最后也要感谢 Vben 项目，在当时让我进一步了解到 Vite + Vue + TypeScript 等最新前端相关技术。</p>]]></content:encoded>
            <category>project</category>
            <category>admin</category>
        </item>
        <item>
            <title><![CDATA[Protocol 协议复现模板]]></title>
            <link>https://kuizuo.cn/protocol-template</link>
            <guid>protocol-template</guid>
            <pubDate>Sun, 30 Oct 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[一个用于快速复现请求协议的 Web 开发模板。基于 Nuxt3 开发，并集成了NaiveUI，Unocss，等相关工具库封装。]]></description>
            <content:encoded><![CDATA[<p align="center"><img loading="lazy" src="https://api.kuizuo.cn/api/icon/carbon:api.svg" width="80" height="80" class="img_ev3q"></p><p align="center"><i> Artwork from <a href="https://v3.nuxtjs.org/" target="_blank" rel="noopener noreferrer">Nuxt3</a></i></p><h1 align="center">Protocol</h1><p align="center">🧪 一个用于快速复现请求协议的 Web 开发模板。</p><p align="center"><a href="https://github.com/kuizuo/protocol" target="_blank" rel="noopener noreferrer"><img loading="lazy" src="https://img.shields.io/github/stars/kuizuo/protocol?style=social" alt="GitHub stars" class="img_ev3q"></a><a href="https://protocol.kuizuo.cn" target="_blank" rel="noopener noreferrer">🖥 在线预览</a><a href="https://stackblitz.com/github/kuizuo/protocol" target="_blank" rel="noopener noreferrer"><img loading="lazy" src="https://developer.stackblitz.com/img/open_in_stackblitz.svg" class="img_ev3q"></a></p><br><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="为什么我要写这样的一个模板网站">为什么我要写这样的一个模板(网站)<a class="hash-link" href="#为什么我要写这样的一个模板网站" title="标题的直接链接">​</a></h2><p>我曾经是做 API 请求的，经常要模拟某些请求（协议复现）。所以写过比较多的 api 请求代码，在此期间尝试编写过许多代码方式和软件形态。但都不令我满意，不是过于繁琐，就是开发太慢，都达不到我想要的预期。尤其是开发体验，可以说是苦不堪言。</p><p>就在前段时间接触了 SSR 框架（Nuxt3）与 Serverless Function，并用其写了一些项目，如 <a href="https://github.com/kuizuo/api-service" target="_blank" rel="noopener noreferrer" title="api-service">api-service</a> 。而<a href="https://7y8y.vercel.app" target="_blank" rel="noopener noreferrer">某了个羊刷次数的网站</a>的实现，则让我意外发现这貌似就是我理想中的的协议复现最佳实现？于是我立马开启了 VSCode，将我的这一想法用代码的方式来实现出来，在经历了两周几乎不间断的开发，最终达到了我的预期效果！</p><p>在 <a href="https://kuizuo.cn/request-protocol-scheme" target="_blank" rel="noopener noreferrer" title="模拟请求|协议复现方案">模拟请求|协议复现方案</a> 这篇文章中我对协议复现的一些方案总结，而这篇就是对 SSR 框架方案的一个具体实践。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="技术栈">技术栈<a class="hash-link" href="#技术栈" title="标题的直接链接">​</a></h2><p>这个模板基于<a href="https://v3.nuxtjs.org/" target="_blank" rel="noopener noreferrer">Nuxt3</a>开发的，该框架拥有全栈开发能力（即全栈框架），并有诸多<a href="https://modules.nuxtjs.org/" target="_blank" rel="noopener noreferrer">模块</a>，即装即用。同时由于采用<code>Serverless Function</code> 方式来定义 api 接口，可以轻易地部署在自有服务器或<a href="https://vercel.com" target="_blank" rel="noopener noreferrer" title="Vercel">Vercel</a>， <a href="https://www.netlify.com/" target="_blank" rel="noopener noreferrer" title="Netlify">Netlify</a>这样的平台上。由于要做到敏捷开发，该模板集成了<a href="https://www.naiveui.com/" target="_blank" rel="noopener noreferrer" title="Naive UI">Naive UI</a> 组件库，组件库的质量足够胜任常规前端业务开发。此外还封装了一些我个人的所用到的工具库以提高开发效率。</p><p>为此我给这个模板起名 Protocol，即协议，也可以认为是礼仪。<strong>一个用于快速复现请求协议的 Web 开发模板。</strong></p><p>废话不多数，就正式来介绍下 <a href="https://github.com/kuizuo/protocol" target="_blank" rel="noopener noreferrer" title="Protocol">Protocol</a>。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="目录结构">目录结构<a class="hash-link" href="#目录结构" title="标题的直接链接">​</a></h2><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">protocol</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├── assets </span><span class="token comment" style="color:rgb(0, 128, 0)"># 前端静态资源文件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├── components </span><span class="token comment" style="color:rgb(0, 128, 0)"># 组件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├── composables </span><span class="token comment" style="color:rgb(0, 128, 0)"># 组合式API</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├── content </span><span class="token comment" style="color:rgb(0, 128, 0)"># content 模块</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   ├── changelog.md </span><span class="token comment" style="color:rgb(0, 128, 0)"># 更新日志</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   └── help.md </span><span class="token comment" style="color:rgb(0, 128, 0)"># 帮助说明</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├── data </span><span class="token comment" style="color:rgb(0, 128, 0)"># 持久化数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   └── db</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├── layouts </span><span class="token comment" style="color:rgb(0, 128, 0)"># 布局</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├── nuxt.config.ts </span><span class="token comment" style="color:rgb(0, 128, 0)"># nuxt 配置文件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├── package.json </span><span class="token comment" style="color:rgb(0, 128, 0)"># 依赖包</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├── pages </span><span class="token comment" style="color:rgb(0, 128, 0)"># 页面</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├── plugins </span><span class="token comment" style="color:rgb(0, 128, 0)"># 插件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├── public </span><span class="token comment" style="color:rgb(0, 128, 0)"># 服务端静态资源文件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   └── logo.svg</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├── server </span><span class="token comment" style="color:rgb(0, 128, 0)"># 服务端文件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   ├── api </span><span class="token comment" style="color:rgb(0, 128, 0)"># 后端接口</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   └── protocol </span><span class="token comment" style="color:rgb(0, 128, 0)"># 协议请求逻辑代理</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├── stores </span><span class="token comment" style="color:rgb(0, 128, 0)"># pinia 状态管理</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   └── user.ts </span><span class="token comment" style="color:rgb(0, 128, 0)"># 用户状态</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├── types </span><span class="token comment" style="color:rgb(0, 128, 0)"># 类型定义</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   └── user.d.ts </span><span class="token comment" style="color:rgb(0, 128, 0)"># 用户类型声明文件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├── ecosystem.config.js </span><span class="token comment" style="color:rgb(0, 128, 0)"># pm2 配置文件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├── nitro.config.ts </span><span class="token comment" style="color:rgb(0, 128, 0)"># nitro 配置文件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├── app.config.ts </span><span class="token comment" style="color:rgb(0, 128, 0)"># 前端配置文件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">└── app.vue </span><span class="token comment" style="color:rgb(0, 128, 0)"># 入口文件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>从这个项目的目录结构中其实就可以看出，本项目是集成了<strong>全栈</strong>能力，并且使用 Vue 与 Node 来编写前端与后端，并<strong>不会产生前后端分离的分割感</strong>，只需要打开一个项目即可开始工作。这得益于<a href="https://v3.nuxtjs.org/" target="_blank" rel="noopener noreferrer" title="Nuxt3">Nuxt3</a> 与 <a href="https://nitro.unjs.io/" target="_blank" rel="noopener noreferrer" title="Nitro">Nitro</a>。</p><p>由于是基于 Nuxt3 开发的，所以使用该项目是需要一些 SSR 开发经验。如果你还没有接触 SSR，可以根据你熟悉的前端框架选择对应的 SSR 框架来尝试体验一番。<del>都要 2023 年了，不会还有前端程序员没用过 SSR 框架吧。</del></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="基本功能"><strong>基本功能</strong><a class="hash-link" href="#基本功能" title="标题的直接链接">​</a></h2><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="全栈开发">全栈开发<a class="hash-link" href="#全栈开发" title="标题的直接链接">​</a></h3><p>这里我不想过多介绍 Nuxt3 的基本功能与使用，在我的一个 <a href="https://kuizuo.cn/use-nuxt3-build-api-server#nuxt3-%E4%BB%8B%E7%BB%8D" target="_blank" rel="noopener noreferrer" title="基于Nuxt3的API接口服务网站">基于 Nuxt3 的 API 接口服务网站</a> 的项目中，有简单介绍过 Nuxt3，有兴趣可以去看看。</p><p>这里你只需要知道 Nuxt3 具有全栈开发的能力，如果你想，完成可以基于 Nuxt3 这个技术栈来实现 Web 开发的前端后端工作。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="类型提示">类型提示<a class="hash-link" href="#类型提示" title="标题的直接链接">​</a></h3><p>首先，最重要的就是类型提示，对于大多数 api 请求而言，类型往往常被忽略。这就导致不知道这个请求的提交参数、响应结果有什么数据字段。举个例子</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_75GsdEZuLK.png" class="img_ev3q"></p><p>这是一个 post 请求用于实现登录的，但是这个响应数据 data 没有任何具体提示（这里的提示是 vscode 记录用户常输入的提示），这时候如果一旦拼接错误，就会导致某个数据没拿到，从而诱发 bug。同理提交的请求体 body 不做约束，万一这个请求还有验证码 code 参数，但是我没写上，那请求就会失败，这是就需要通过调试输出，甚至需要抓包比对原始数据包才能得知。</p><p>最主要的是没有类型约束的情况下，非常容易出现出现访问的对象属性不存在，做 js 开发的肯定经常遇到如下错误提示。</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token maybe-class-name">Uncaught</span><span class="token plain"> </span><span class="token known-class-name class-name" style="color:rgb(38, 127, 153)">TypeError</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token maybe-class-name">Cannot</span><span class="token plain"> read properties </span><span class="token keyword" style="color:rgb(0, 0, 255)">of</span><span class="token plain"> </span><span class="token keyword nil" style="color:rgb(0, 0, 255)">undefined</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">reading </span><span class="token string" style="color:rgb(163, 21, 21)">'data'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>有太多很多时候就是因为没有类型，无形间诱发 bug。就极易造成开发疲惫，不愿维护代码，这也是很多做 api 接口都常常忽视的一点。包括我之前也是同样如此。</p><p>对于 js 而言，上述情况自然是解决不了，但这种场景对于 ts 来说在适合不过了。所以 Protocol 自然是集成了 ts，并且有良好的类型提示。下面展示几张开发时的截图就能体会到，当然你前提是得会 ts 或者看的懂 ts。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_VbEuizLRfz.png" class="img_ev3q"></p><p>上面的类型提示演示代码仅仅作为体现类型的好处，将类型定义（interface，type 等）和核心逻辑都在同一个文件自然不好，容易造成代码冗余。实际开发中，更多使用命名空间，将类型写到 ts 声明文件.d.ts 中。比如将上面的改写后如下</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_48-YSpYd1g.png" class="img_ev3q"></p><p><img loading="lazy" src="https://img.kuizuo.cn/image_9b9ns2BM67.png" class="img_ev3q"></p><p>就在我写这篇文章做代码演示的时候，又发生了拼写错误，如下图。由于使用 ts 类型与 eslint，所以在开发时的问题我就能立马发现，而不是到了运行时才提示错误。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_PfpxCKZomB.png" class="img_ev3q"></p><p><strong>有了类型提示能非常有效的避免上述问题</strong>。同时 ts 并不像 java 那样的强类型语言，你完全可以选择是否编写 ts 的类型（type 或 interfere），这由你决定，你乐意都可以将 typescript 写成 anyscript，因为确实有些人确实不喜欢写类型。</p><p>ts 的类型提示仅是其次，此外还配置了 eslint 对代码检查，让代码在 2 个空格缩进，无分号，单引号等代码规范下。保证代码质量，而不会出现这边一个分号，那边来个双引号的情况。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="工具库">工具库<a class="hash-link" href="#工具库" title="标题的直接链接">​</a></h3><p>要想在实际项目中使用，还需要做很多功课，例如数据格式转换，编码，加解密，cookie 存储，IP 代理等等。这段时间也特此对常用工具封装成 npm 包，也就是 <a href="https://www.npmjs.com/package/@kuizuo/http" target="_blank" rel="noopener noreferrer">@kuizuo/http</a> 与 <a href="https://www.npmjs.com/package/@kuizuo/utils" target="_blank" rel="noopener noreferrer">@kuizuo/utils</a>。</p><p>大部分的代码我都会采用最新的 ECMAScript 标准来编写，目的也是为了简化代码，减少不必要的负担。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="数据库">数据库<a class="hash-link" href="#数据库" title="标题的直接链接">​</a></h3><p>既然是全栈框架，那么必然少不了数据库的存取，<a href="https://nitro.unjs.io/guide/introduction/storage" target="_blank" rel="noopener noreferrer" title="nitro">nitro</a> 自然是提供了数据存储选择，即 <a href="https://github.com/unjs/unstorage#http-universal" target="_blank" rel="noopener noreferrer" title="unjs/unstorage">unjs/unstorage</a>。使用特别简单：</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">useStorage</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">setItem</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'test:foo'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token literal-property property">hello</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'world'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">useStorage</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">getItem</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'test:foo'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>不指定则使用内存，当然了想要持久化配置，<a href="https://nitro.unjs.io/guide/introduction/storage#defining-mountpoints" target="_blank" rel="noopener noreferrer" title="nitro">nitro</a> 也提供了相关配置</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">nitro.config.ts</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)">// nitro.config.ts</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword module" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token imports">defineNitroConfig</span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'nitropack'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword module" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">default</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">defineNitroConfig</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">storage</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">redis</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">driver</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'redis'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token comment" style="color:rgb(0, 128, 0)">/* redis connector options */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">db</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">driver</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'fs'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">base</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'./data/db'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>并根据不同前缀（根据 nitro.config.ts 中的 storage 对象的属性）存储在不同存储位置，如</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)">// 存内存缓存中</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">useStorage</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">setItem</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'cache:foo'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token literal-property property">hello</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'world'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">useStorage</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">getItem</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'cache:foo'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// 存db中</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">useStorage</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">setItem</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'db:foo'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token literal-property property">hello</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'world'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">useStorage</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">getItem</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'db:foo'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// 存redis中</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">useStorage</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">setItem</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'redis:foo'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token literal-property property">hello</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'world'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">useStorage</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">getItem</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'redis:foo'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>从目前来看，<a href="https://github.com/unjs/unstorage#http-universal" target="_blank" rel="noopener noreferrer" title="unjs/unstorage">unjs/unstorage</a>并没有提供 sql 数据库的方案。不过对于这类项目而言，似乎也没有上 sql 数据库的必要，文件和 redis 就足以了。如果需要也可以<a href="https://github.com/unjs/unstorage#making-custom-drivers" target="_blank" rel="noopener noreferrer" title="自定义 drivers">自定义 drivers</a>。</p><div class="theme-admonition theme-admonition-caution alert alert--warning admonition_LlT9"><div class="admonitionHeading_tbUL"><span class="admonitionIcon_kALy"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>注意</div><div class="admonitionContent_S0QG"><p>由于 Vercel 是不支持文件读写的，所以想要文件方式数据存储功能就行不通，需要更换存储方案，比如远程 redis 数据库。</p><p>如果是部署到自由的服务器（通常是 Linux 系统），则需要分配相应的读写权限。</p></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="用户凭证存储">用户凭证存储<a class="hash-link" href="#用户凭证存储" title="标题的直接链接">​</a></h3><p>通常来说，有两种用户凭证，Cookie 和 Token，有了上述数据存储的方案，存取用户凭证并不是什么难题。不过用户凭证更多的是用来鉴权的，这时候就需要配置前端<a href="https://v3.nuxtjs.org/guide/directory-structure/middleware#middleware-directory" target="_blank" rel="noopener noreferrer">Middleware</a> 和后端 <a href="https://v3.nuxtjs.org/guide/directory-structure/server#server-middleware" target="_blank" rel="noopener noreferrer">Middleware</a>，至于选择哪种，根据实际网站情况来选择即可。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="更新日志与帮助说明">更新日志与帮助说明<a class="hash-link" href="#更新日志与帮助说明" title="标题的直接链接">​</a></h3><p>我提供了两个 md 页面，更新日志（ChangeLog）和帮助说明（Usage），如果需要更新内容，在根目录下 <code>content</code> 文件夹中找到对应文件修改即可。</p><p>如果你想在创建新的 md 页面只需要在 content 中新建一个文件（如test.md），在页面路由创建同名vue文件(test.vue)，将下方的 path 修改相应文件名即可。</p><div class="language-html codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">pages/test.vue</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-html codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">script</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">setup</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">lang</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">ts</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript"></span><span class="token script language-javascript function" style="color:rgb(0, 0, 255)">definePageMeta</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">  </span><span class="token script language-javascript literal-property property">layout</span><span class="token script language-javascript operator" style="color:rgb(0, 0, 0)">:</span><span class="token script language-javascript"> </span><span class="token script language-javascript string" style="color:rgb(163, 21, 21)">'markdown'</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript"></span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript"></span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">script</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">template</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">div</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">ContentDoc</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">class</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">prose text-left</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">path</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">/test</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">/&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">div</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">template</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="打包与部署">打包与部署<a class="hash-link" href="#打包与部署" title="标题的直接链接">​</a></h3><p>传统的 node 后端框架，通常需要将原文件或者打包后的文件放到服务器上，执行 <code>npm i</code> 下载 <code>package.json</code> 里的依赖文件，然后执行运行命令启动。这一步骤的下载依赖就尤为致命，因为通常下载依赖将会特别耗时。</p><p>但 Nuxt3 则是会将前后端的资源文件，打包到 <code>.output</code> 文件夹下，以本项目为例，打包的大小为 14.6MB,gzip 压缩为 3.11MB（写本章时的记录），如果不使用<a href="https://content.nuxtjs.org/" target="_blank" rel="noopener noreferrer">Content</a> 模块体积将会更小。打包完成提示如下</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">Σ Total size: </span><span class="token number" style="color:rgb(9, 134, 88)">14.6</span><span class="token plain"> MB </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">3.11</span><span class="token plain"> MB </span><span class="token function" style="color:rgb(0, 0, 255)">gzip</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">√ You can preview this build using </span><span class="token function" style="color:rgb(0, 0, 255)">node</span><span class="token plain"> .output/server/index.mjs</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>然后你只需要将 <code>.output</code> 整个文件夹放到服务器上，并且安装好 node 环境，输入 <code>node .output/server/index.mjs</code> 即可启动项目，默认端口为 3000。当然也可以通过 pm2 的配置文件来启动，配置文件如下</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">ecosystem.config.js</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">module</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">exports</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">apps</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">name</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'Protocol'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">exec_mode</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'cluster'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">instances</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'1'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">env</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token constant" style="color:rgb(129, 31, 63)">NITRO_PORT</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">8010</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token constant" style="color:rgb(129, 31, 63)">NITRO_HOST</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'localhost'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token constant" style="color:rgb(129, 31, 63)">NODE_ENV</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'production'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">script</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'./.output/server/index.mjs'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>接着执行 <code>pm2 start ecosystem.config.js --env production</code> 即可运行。相比传统需要手动下载依赖的方式，Nuxt3 则是直接将 web 项目实际所需要的依赖都打包在一起，只需要在有 node 环境下机器中就可以立马运行，无需等待依赖下载。</p><p>如果部署在 Vercel 或 Netlify 就更轻松了，根据官方的步骤即可做到一键部署。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="开发流程形态"><strong>开发流程（形态）</strong><a class="hash-link" href="#开发流程形态" title="标题的直接链接">​</a></h2><p>介绍完工具库，如果不介绍下开发流程，很多人都不知道该如何起手，这里我会用 Github 的 api 作为案例演示，也就是模板源代码中所演示的那样。当然，后续我会根据一些实战项目考虑弄个案例展示（在写中），以来方便使用与完善该模板。毕竟如果开发者自己都不愿意用，又怎么去说服他人来使用呢。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="修改内容">修改内容<a class="hash-link" href="#修改内容" title="标题的直接链接">​</a></h3><p>如何修改某文字内容或某图标，这里就不再赘述了，Ctrl + Shift + F 搜索你想修改的内容并修改即可。大部分能修改的配置都写在了 <code>app.config.ts</code> 下。</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">app.config.ts</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword module" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">default</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">defineAppConfig</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">title</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'Protocol'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">description</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token string" style="color:rgb(163, 21, 21)">'一个用于快速复现请求协议的Web开发模板。'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">author</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">name</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'kuizuo'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">link</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token string" style="color:rgb(163, 21, 21)">'https://github.com/kuizuo'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">qq</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'https://im.qq.com/'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">wx</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'https://wx.qq.com/'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>通过 <code>const appConfig = useAppConfig()</code> 获取配置对象数据。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="定义协议复现逻辑代码重要"><strong>定义协议复现逻辑代码（重要）</strong><a class="hash-link" href="#定义协议复现逻辑代码重要" title="标题的直接链接">​</a></h3><p>这里以调用 Github 的 api 为例，因为业务相对简单，所以使用的是静态方法来调用，简单展示一下代码</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">server/protocol/github/index.ts</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword module" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token imports"> </span><span class="token imports maybe-class-name">AHttp</span><span class="token imports"> </span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'@kuizuo/http'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> http </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">AHttp</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">baseURL</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'https://api.github.com'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword module" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">Github</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">static</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">async</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">getUser</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter literal-property property">username</span><span class="token parameter operator" style="color:rgb(0, 0, 0)">:</span><span class="token parameter"> string</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> data </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> http</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">get</span><span class="token operator" style="color:rgb(0, 0, 0)">&lt;</span><span class="token constant" style="color:rgb(129, 31, 63)">API</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access maybe-class-name">User</span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string string" style="color:rgb(163, 21, 21)">/users/</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">${</span><span class="token template-string interpolation">username</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> data</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">static</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">async</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">getRepos</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter literal-property property">username</span><span class="token parameter operator" style="color:rgb(0, 0, 0)">:</span><span class="token parameter"> string</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> data </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> http</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">get</span><span class="token operator" style="color:rgb(0, 0, 0)">&lt;</span><span class="token constant" style="color:rgb(129, 31, 63)">API</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access maybe-class-name">Repo</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string string" style="color:rgb(163, 21, 21)">/users/</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">${</span><span class="token template-string interpolation">username</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token template-string string" style="color:rgb(163, 21, 21)">/repos</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> data</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>我个人是习惯也喜欢将逻辑部分用 <a href="https://es6.ruanyifeng.com/#docs/class" target="_blank" rel="noopener noreferrer">class</a> 的方式来编写，也推荐用这种去定义这些业务逻辑代码。这里我举个例子来说明，假设现在有一个博客网站，有登陆、获取博文列表、评论等功能。那么我会这么写</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword module" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token imports"> </span><span class="token imports maybe-class-name">AHttp</span><span class="token imports"> </span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'@kuizuo/http'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">interface</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">User</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">username</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> string</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">password</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> string</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword module" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">Blog</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">public</span><span class="token plain"> </span><span class="token literal-property property">http</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token maybe-class-name">AHttp</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">public</span><span class="token plain"> </span><span class="token literal-property property">user</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token maybe-class-name">User</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">constructor</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter literal-property property">user</span><span class="token parameter operator" style="color:rgb(0, 0, 0)">:</span><span class="token parameter"> </span><span class="token parameter maybe-class-name">User</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">http</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">AHttp</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">baseURL</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'https://blog.kuizuo.cn'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">user</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token maybe-class-name">User</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">async</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">login</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">// login logic code</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">async</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">getBlogList</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">// getBlogList logic code</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">async</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">comment</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter literal-property property">id</span><span class="token parameter operator" style="color:rgb(0, 0, 0)">:</span><span class="token parameter"> number</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">// comment logic code</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>定义完这些后，我只需要实例化一个对象 account，调用 login 方法即可登录，后续的获取博文列表与评论操作我只需要拿这个 account 来操作即可。</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> account </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">Blog</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token literal-property property">username</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'kuizuo'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">password</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'123456'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> account</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">login</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> blogList </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> account</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">getBlogList</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> account</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">comment</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>如果想换一个账号操作，就需要重新按照上面的方式实例化一个新的对象，拿这个对象操作即可。</p><p>并且这种方式在迁移代码的时候尤为方便，可以直接将这份代码放到不同的 Node 项目中来运行。</p><p>通常也是在这一流程中，会编写大量的类型代码，来完善整个项目，保证代码的健壮。通常我会在同文件下或者在 types 下定义 <code>.d.ts</code> 声明文件，通过声明文件与命名空间，无需导入即可全局使用类型。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="定义后端数据接口">定义后端数据接口<a class="hash-link" href="#定义后端数据接口" title="标题的直接链接">​</a></h3><p>定义完复现协议的逻辑代码后，那么就到前后端数据交互部分了，首先定义后端的接口，由于上面我们已经定义好了协议复现逻辑代码，这边只需要导入使用即可。就像下面这样</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">server/api/uesr/[username].ts</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword module" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token imports"> </span><span class="token imports maybe-class-name">Github</span><span class="token imports"> </span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'~~/server/protocol/github'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword module" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token imports"> </span><span class="token imports maybe-class-name">ResOp</span><span class="token imports"> </span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'~~/server/utils'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword module" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">default</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">defineEventHandler</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">event</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> username </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">context</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">params</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> user </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> </span><span class="token maybe-class-name">Github</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">getUser</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">username</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token operator" style="color:rgb(0, 0, 0)">!</span><span class="token plain">user</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">login</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token maybe-class-name">ResOp</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">404</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> user</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">message</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">??</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'User not found'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">useStorage</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">setItem</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string string" style="color:rgb(163, 21, 21)">db:github:user:</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">${</span><span class="token template-string interpolation">username</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> user</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token maybe-class-name">ResOp</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">success</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">user</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>这一部分的代码建立在 Serverless Function 上，每一个接口都是以函数的方式对外暴露出去。这些代码会根据文件位置生成对应的路由，比如说上面的文件为 <code>server/api/user/[username].ts</code>，就映射为 <code>/api/user/:username</code>，前端请求 <code>/api/user/kuizuo</code> 通过<code>event.context.params.username</code> 便可以拿到 username 的值为 kuizuo。</p><p>至此后端部分就暂以告告落。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="定义前端状态管理">定义前端状态管理<a class="hash-link" href="#定义前端状态管理" title="标题的直接链接">​</a></h3><p>对于前端而言，肯定是需要全局管理一些数据状态的，这样能够在不同的组件间共享数据，并且需要持久化这些数据，以保证下次用户再次打开网页的时候无需向后台请求数据，pinia 持久化使用到了 <a href="https://github.com/prazdevs/pinia-plugin-persistedstate" target="_blank" rel="noopener noreferrer">pinia-plugin-persistedstate</a> 插件。</p><p>同时在状态管理中，会定义一些方法来调用后端接口。如下演示</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">stores/user.ts</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword module" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token imports"> useMessage </span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'naive-ui'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword module" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> useUserStore </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">definePiniaStore</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'user'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> user </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> ref</span><span class="token operator" style="color:rgb(0, 0, 0)">&lt;</span><span class="token constant" style="color:rgb(129, 31, 63)">API</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access maybe-class-name">User</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token keyword null nil" style="color:rgb(0, 0, 255)">null</span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword null nil" style="color:rgb(0, 0, 255)">null</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> repos </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> ref</span><span class="token operator" style="color:rgb(0, 0, 0)">&lt;</span><span class="token constant" style="color:rgb(129, 31, 63)">API</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access maybe-class-name">Repo</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> message </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">useMessage</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">async</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">getUser</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter literal-property property">username</span><span class="token parameter operator" style="color:rgb(0, 0, 0)">:</span><span class="token parameter"> string</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> data </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> http</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">get</span><span class="token operator" style="color:rgb(0, 0, 0)">&lt;</span><span class="token constant" style="color:rgb(129, 31, 63)">API</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access maybe-class-name">User</span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string string" style="color:rgb(163, 21, 21)">/api/user/</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">${</span><span class="token template-string interpolation">username</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">login</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      user</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">value</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> data</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      message</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">success</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'获取成功'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">else</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      message</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">message</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">async</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">getRepos</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> username </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> user</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">value</span><span class="token operator" style="color:rgb(0, 0, 0)">?.</span><span class="token plain">login</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> data </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> http</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">get</span><span class="token operator" style="color:rgb(0, 0, 0)">&lt;</span><span class="token constant" style="color:rgb(129, 31, 63)">API</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access maybe-class-name">Repo</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string string" style="color:rgb(163, 21, 21)">/api/repo/</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">${</span><span class="token template-string interpolation">username</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    repos</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">value</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> data</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">async</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">reset</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    user</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">value</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword null nil" style="color:rgb(0, 0, 255)">null</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    repos</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">value</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    user</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    repos</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    getUser</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    getRepos</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    reset</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">persist</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">key</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'user'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>这里的 http 是经过封装的，因为返回数据格式如：<code>{"code":200,"data":{},"message":"success"}</code> ，但对于业务逻辑而言，我们通常只需要关注 <code>data</code> 里面的数据，而请求的状态 code 与信息 message 则不是所要着重关系的对象。</p><p>至于想要返回原数据，还是带有 code, message 的数据，因人而异，我更喜欢后者将数据格式规范化，这样我就能知道本次请求的状态结果，在响应拦截器中就能够进行预先处理。</p><p>在 vue 组件中只需要使用演示如下</p><div class="language-html codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">components\Demo.vue</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-html codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">script</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">setup</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">lang</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">ts</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript"></span><span class="token script language-javascript keyword" style="color:rgb(0, 0, 255)">let</span><span class="token script language-javascript"> username </span><span class="token script language-javascript operator" style="color:rgb(0, 0, 0)">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript function" style="color:rgb(0, 0, 255)">$ref</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token script language-javascript string" style="color:rgb(163, 21, 21)">'kuizuo'</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript"></span><span class="token script language-javascript keyword" style="color:rgb(0, 0, 255)">let</span><span class="token script language-javascript"> loading </span><span class="token script language-javascript operator" style="color:rgb(0, 0, 0)">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript function" style="color:rgb(0, 0, 255)">$ref</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token script language-javascript boolean">false</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript"></span><span class="token script language-javascript keyword" style="color:rgb(0, 0, 255)">const</span><span class="token script language-javascript"> userStore </span><span class="token script language-javascript operator" style="color:rgb(0, 0, 0)">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript function" style="color:rgb(0, 0, 255)">useUserStore</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript"></span><span class="token script language-javascript keyword" style="color:rgb(0, 0, 255)">const</span><span class="token script language-javascript"> user </span><span class="token script language-javascript operator" style="color:rgb(0, 0, 0)">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript function" style="color:rgb(0, 0, 255)">$computed</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token script language-javascript"> userStore</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token script language-javascript property-access">user</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript"></span><span class="token script language-javascript keyword" style="color:rgb(0, 0, 255)">async</span><span class="token script language-javascript"> </span><span class="token script language-javascript keyword" style="color:rgb(0, 0, 255)">function</span><span class="token script language-javascript"> </span><span class="token script language-javascript function" style="color:rgb(0, 0, 255)">getUser</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">  loading </span><span class="token script language-javascript operator" style="color:rgb(0, 0, 0)">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript boolean">true</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">  </span><span class="token script language-javascript keyword control-flow" style="color:rgb(0, 0, 255)">try</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">    </span><span class="token script language-javascript keyword control-flow" style="color:rgb(0, 0, 255)">await</span><span class="token script language-javascript"> userStore</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token script language-javascript method function property-access" style="color:rgb(0, 0, 255)">getUser</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token script language-javascript">username</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">  </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token script language-javascript"> </span><span class="token script language-javascript keyword control-flow" style="color:rgb(0, 0, 255)">finally</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">    loading </span><span class="token script language-javascript operator" style="color:rgb(0, 0, 0)">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript boolean">false</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">  </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript"></span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript"></span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">script</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="编写前端页面与组件">编写前端页面与组件<a class="hash-link" href="#编写前端页面与组件" title="标题的直接链接">​</a></h3><p>这一部分自由发挥即可了，这里我是集成了 NaiveUI 与 Unocss，足够应对大部分的前端开发需求。没什么过多要说的了。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="流程总结">流程总结<a class="hash-link" href="#流程总结" title="标题的直接链接">​</a></h3><p>整个开发流程就是这样的，如果我想要添加一个功能，用于获取 Github 用户已点的 Star 项目列表，那么按照上面流程将会清晰的实现出来。</p><p>这里仅举调用 Github api 为例，想调用其他第三方的 api 都不成问题，本模板只提供一个这样的开发流程（形态）能够帮助快速实现 Web 站点开发，同时极易部署，做到敏捷开发。</p><p>对比传统前后端分离的开发流程，这种开发流程可以说更加清晰，更加规范，更加高效。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="一些问题">一些问题<a class="hash-link" href="#一些问题" title="标题的直接链接">​</a></h2><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="遇到图片防盗链怎么办">遇到图片防盗链怎么办?<a class="hash-link" href="#遇到图片防盗链怎么办" title="标题的直接链接">​</a></h3><p>我的做法相对比较简单粗暴，直接在图片中添加<code>referrerpolicy='no-referrer'</code> 就像下面这样。</p><div class="language-html codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-html codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">img</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">src</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">src</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">referrerpolicy</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">no-referrer</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">/&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>如果你想要集成到 HTML 或者 CSS ，可以直接在 <code>&lt;head&gt;</code> 标签下添加如下代码.</p><div class="language-html codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-html codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">meta</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">name</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">referrer</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">content</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">no-referrer</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">/&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>参阅<a href="https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Referrer-Policy" target="_blank" rel="noopener noreferrer" title="Referrer-Policy - HTTP | MDN (mozilla.org)">Referrer-Policy - HTTP | MDN (mozilla.org)</a></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="跨域问题">跨域问题<a class="hash-link" href="#跨域问题" title="标题的直接链接">​</a></h3><p>几乎不会遇到跨域问题，因为所有的接口都相当于转发过一遍，不是由前端直接发送，而是后端接收到后，通过服务器来进行发送，然后将数据在返还给前端。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="考虑做的">考虑做的<a class="hash-link" href="#考虑做的" title="标题的直接链接">​</a></h2><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="编写一个后台管理系统">编写一个后台管理系统<a class="hash-link" href="#编写一个后台管理系统" title="标题的直接链接">​</a></h3><p>这个模板如果要实现鉴权是相对比较简单的，前后端配置<a href="https://v3.nuxtjs.org/guide/directory-structure/middleware" target="_blank" rel="noopener noreferrer" title="Middleware">Middleware</a> 即可实现。使用 cookie 和 token 都随意，甚至第三方的登录。</p><p>但这时数据多了，难免需要去管理数据，不如专门为此编写一个后台管理系统，同时提供一个鉴权相关的功能。主要还是借助 ntrio 来开发，毕竟提供全栈开发能力，要实现只是时间开发的问题。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="使用-tauri-编译跨平台程序">使用 tauri 编译跨平台程序<a class="hash-link" href="#使用-tauri-编译跨平台程序" title="标题的直接链接">​</a></h3><p>编译成跨平台程序有一个好处，就是所有的流量请求与接收都是存放在用户的机器中，就相当于传统的桌面应用开发。而部署在 Web 端请求流量的压力都将会来到服务器上，就避免不了用户量大，导致请求缓慢，甚至 ip 被封禁的问题。</p><p>由于我暂且还不会 tauri 开发，也还不会 rust，所以这个功能估计得到寒假才有可能去实现了。electron 占用比较大的资源空间，不作为跨平台框架优先选择。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="写在最后">写在最后<a class="hash-link" href="#写在最后" title="标题的直接链接">​</a></h2><p>这种开发形态自打我接触协议复现到前端开发我就考虑过，但奈何在没接触 ssr 框架之前，这种开发形态多半是需要前后端分离，要么使用模板语言，这样接口交互方面将会十分繁琐，开发效率过于低效。</p><p>因此当我发觉 ssr框架的可行性后，我几乎整整花费了两周的时间在不断的探索与完善中，希望将其编写成一个我日后随时都会用到的模板，即写即用，极速上线。因为这样的开发场景对我来说太过于常见了，而很多时间就是因为没有一个相应的模板与工具库，代码总是东凑西凑，后续维护与测试总是花费不小的时间去解决。</p><p>目前这种方案已有初步雏形，由于一些特殊的因素，我并未将已经写过的站点作为案例放在这上面作为演示，而将 Github api 作为演示，后续大概率会弄个案例展示供参考学习。</p><p>后续我还是会不断去完善与维护该项目，并基于该项目去重构我的一些项目。</p><p><strong>本模板仅仅是 web 模板，任何开发者用该模板做什么样的站点都与本人无关。仅作为个人技术专研，仅供学习参考。</strong></p>]]></content:encoded>
            <category>project</category>
            <category>protocol</category>
            <category>template</category>
            <category>nuxt3</category>
        </item>
        <item>
            <title><![CDATA[rollup.js 初体验]]></title>
            <link>https://kuizuo.cn/rollup-js-experience</link>
            <guid>rollup-js-experience</guid>
            <pubDate>Tue, 18 Oct 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[rollup.js]]></description>
            <content:encoded><![CDATA[<p><img loading="lazy" src="https://img.kuizuo.cn/rollupjs.png" alt="rollup.js" class="img_ev3q"></p><p>近期准备写一个工具包 <a href="https://github.com/kuizuo/utils" target="_blank" rel="noopener noreferrer" title="@kuizuo/utils">@kuizuo/utils</a>，由于要将其发布到npm上，必然就要兼容不同模块（例如 CommonJS 和 ESModule），通过打包器可以很轻松的将代码分别编译成这不同模块格式。</p><p>恰好 <a href="https://github.com/rollup/rollup/releases/tag/v3.0.0" target="_blank" rel="noopener noreferrer" title="rollup 3">rollup 3</a> 正式发布，也算是来体验一下。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="为什么不是webpack">为什么不是Webpack？<a class="hash-link" href="#为什么不是webpack" title="标题的直接链接">​</a></h3><p><code>rollup</code> 的特色是 <code>ES6</code> 模块和代码 <code>Tree-shaking</code>，这些 <code>webpack</code> 同样支持，除此之外 <code>webpack</code> 还支持热模块替换、代码分割、静态资源导入等更多功能。</p><p>当开发应用时当然优先选择的是 <code>webpack</code>，但是若你项目只需要打包出一个简单的 <code>bundle</code> 包，并是基于 <code>ES6</code> 模块开发的，可以考虑使用 <code>rollup</code>。</p><p><strong><code>rollup</code> 相比 <code>webpack</code>，它更少的功能和更简单的 api，是我们在打包类库时选择它的原因。</strong>例如本次要编写的工具包就是这类项目。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="支持打包的模块格式">支持打包的模块格式<a class="hash-link" href="#支持打包的模块格式" title="标题的直接链接">​</a></h2><p>目前常见的模块规范有：<!-- --> </p><ul><li><p>IFFE：使用立即执行函数实现模块化 例：<code>(function(){})()</code></p></li><li><p>CJS：基于 CommonJS 标准的模块化</p></li><li><p>AMD：使用 Require 编写</p></li><li><p>ESM：ES 标准的模块化方案 ( ES6 标准提出 )</p></li><li><p>UMD：兼容 CJS 与 AMD、IFFE 规范</p></li></ul><p>以上 Rollup 都是支持的。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="使用">使用<a class="hash-link" href="#使用" title="标题的直接链接">​</a></h2><p>官方有一篇文章 <a href="https://rollupjs.org/guide/en/#creating-your-first-bundle" target="_blank" rel="noopener noreferrer" title="创建你的第一个bundle">创建你的第一个bundle</a> ，不过英文文档比较难啃，同时通过命令方式+选项的方式来打包肯定不是工程化想要的。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="配置文件">配置文件<a class="hash-link" href="#配置文件" title="标题的直接链接">​</a></h3><p>所以这里所演示的是通过 <code>rollup.config.js</code> 文件，通过<code>rollup -c</code> 来打包。</p><p>一个示例文件如下</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">rollup.config.js</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword module" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">default</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">input</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'src/main.js'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">output</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">file</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'bundle.js'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">format</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'cjs'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>执行 <code>rollup -c</code> 就会将<code>main.js</code> 中所引用到的js代码，通过<code>commonjs</code>的方式编写到<code>bundle.js</code>，就像这样。</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">bundle.js</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token string" style="color:rgb(163, 21, 21)">'use strict'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">var</span><span class="token plain"> foo </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'hello world!'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">main</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">foo</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">module</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">exports</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> main</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>但是更多的情况下，是需要同时打包多个模块格式的包，就可以在output传入数组，例如</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">rollup.config.js</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword module" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">default</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">input</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'src/main.js'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">output</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">file</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'bundle.cjs'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">format</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'cjs'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">file</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'bundle.mjs'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">format</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'esm'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>便会生成 <code>bundle.cjs</code>, <code>bundle.mjs</code> 两种不同的模块格式的文件。同时在 <code>package.json</code> 中，指定对应模块路径，在引入时，便会根据当前的项目环境去选择导入哪个模块。</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">package.json</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token string-property property">"main"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"bundle.cjs"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token string-property property">"module"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"bundle.mjs"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="结合rollup插件使用">结合rollup插件使用<a class="hash-link" href="#结合rollup插件使用" title="标题的直接链接">​</a></h3><p>不过更多情况下，rollup需要配置插件来使用。官方插件地址：<a href="https://github.com/rollup/plugins" target="_blank" rel="noopener noreferrer" title="rollup/plugins: 🍣 The one-stop shop for official Rollup plugins (github.com)">rollup/plugins: 🍣 The one-stop shop for official Rollup plugins (github.com)</a></p><p>比如使用 <a href="https://github.com/egoist/rollup-plugin-esbuild" target="_blank" rel="noopener noreferrer" title="rollup-plugin-esbuild">rollup-plugin-esbuild</a> 插件来使用<a href="https://esbuild.docschina.org/" target="_blank" rel="noopener noreferrer" title="esbuild">esbuild</a>（也是一个打包器，并且构建非常快）来加快打包速度。可以使用 <a href="https://github.com/rollup/plugins/tree/master/packages/babel" target="_blank" rel="noopener noreferrer" title="@rollup/plugin-babel">@rollup/plugin-babel</a> 借助babel，编译成兼容性更强的js代码或者代码转换等等。</p><p>以下是rollup+插件的配置示例，来源 <a href="https://github.com/antfu/utils/blob/main/rollup.config.js" target="_blank" rel="noopener noreferrer" title="antfu/utils/rollup.config.js">antfu/utils/rollup.config.js</a> ，也作为本次工具包的配置。</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">rollup.config.js</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword module" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token imports">esbuild</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'rollup-plugin-esbuild'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword module" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token imports">dts</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'rollup-plugin-dts'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword module" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token imports">resolve</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'@rollup/plugin-node-resolve'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword module" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token imports">commonjs</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'@rollup/plugin-commonjs'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword module" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token imports">json</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'@rollup/plugin-json'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword module" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token imports">alias</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'@rollup/plugin-alias'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> entries </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token string" style="color:rgb(163, 21, 21)">'src/index.ts'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> plugins </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">alias</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">entries</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">find</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token regex regex-delimiter">/</span><span class="token regex regex-source language-regex">^node:(.+)$</span><span class="token regex regex-delimiter">/</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">replacement</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'$1'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">resolve</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">preferBuiltins</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">json</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">commonjs</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">esbuild</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">target</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'node14'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword module" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">default</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token spread operator" style="color:rgb(0, 0, 0)">...</span><span class="token plain">entries</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">map</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">input</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    input</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">output</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token literal-property property">file</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> input</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">replace</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'src/'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'dist/'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">replace</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'.ts'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'.mjs'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token literal-property property">format</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'esm'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token literal-property property">file</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> input</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">replace</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'src/'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'dist/'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">replace</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'.ts'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'.cjs'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token literal-property property">format</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'cjs'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">external</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    plugins</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token spread operator" style="color:rgb(0, 0, 0)">...</span><span class="token plain">entries</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">map</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">input</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    input</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">output</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">file</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> input</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">replace</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'src/'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">''</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">replace</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'.ts'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'.d.ts'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">format</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'esm'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">external</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">plugins</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token function" style="color:rgb(0, 0, 255)">dts</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">respectExternal</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>以下是对应的npm 安装命令</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token function" style="color:rgb(0, 0, 255)">pnpm</span><span class="token plain"> i -D rollup @rollup/plugin-alias @rollup/plugin-commonjs @rollup/plugin-json @rollup/plugin-node-resolve rollup-plugin-esbuild rollup-plugin-dts</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>关于rollup更多使用，不妨参见 <a href="https://rollupjs.org/" target="_blank" rel="noopener noreferrer" title="rollup官方文档">rollup官方文档</a>，以及一些使用 rollup 来打包的开源项目。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="类似工具">类似工具<a class="hash-link" href="#类似工具" title="标题的直接链接">​</a></h2><p>类似的工具还有 <a href="https://webpack.js.org/" target="_blank" rel="noopener noreferrer" title="webpack.js">webpack.js</a>, <a href="https://esbuild.github.io/" target="_blank" rel="noopener noreferrer" title="esbuild">esbuild</a>, <a href="https://parceljs.org/" target="_blank" rel="noopener noreferrer" title="parceljs">parceljs</a></p><p>不过就打包类库而言，并不要求过强的性能，有个相对简单的配置就足以，而 <a href="https://rollupjs.org/" target="_blank" rel="noopener noreferrer" title="rollup">rollup</a> 正是这样的打包工具。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="相关文章">相关文章<a class="hash-link" href="#相关文章" title="标题的直接链接">​</a></h2><p><a href="https://juejin.cn/post/7145090564801691684" target="_blank" rel="noopener noreferrer" title="【实战篇】最详细的Rollup打包项目教程">【实战篇】最详细的Rollup打包项目教程</a></p><p><a href="https://zhuanlan.zhihu.com/p/221968604" target="_blank" rel="noopener noreferrer" title="一文带你快速上手Rollup">一文带你快速上手Rollup</a></p>]]></content:encoded>
            <category>rollup</category>
            <category>webpack</category>
            <category>utils</category>
        </item>
        <item>
            <title><![CDATA[深谈个人对新技术的看法]]></title>
            <link>https://kuizuo.cn/talk-new-technologies-opinion</link>
            <guid>talk-new-technologies-opinion</guid>
            <pubDate>Sat, 15 Oct 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[目前技术圈的发展速度可谓是有目共睹，尤其是前端，每隔一段时间就出新的技术，可以说让很多初学者非常畏惧，没有一个明确的方向不知道从何学起。]]></description>
            <content:encoded><![CDATA[<p>目前技术圈的发展速度可谓是有目共睹，尤其是前端，每隔一段时间就出新的技术，可以说让很多初学者非常畏惧，没有一个明确的方向不知道从何学起。</p><p>同时也有很多人，只局限于使用手头已掌握的技术，而不愿去尝试新技术。举个例子，如今 vue3 都已经正式发布，但仍还有停留在 vue2 不愿尝试 vue3 的开发者。而 java 都发布 18 版本了，可还有很多人都还使用着 java8，这种现象可以说是非常常见了。</p><p>这里说说我个人编码经验与看法，<strong>仅作为个人观点，没别的意思</strong>。</p><p>熟悉我的人应该都知道，我对很多新鲜的技术有一种难以用言语表达的情感，又哭又笑。属于是那种看到感兴趣的就会开始尝试，在之前也许更强烈。</p><p>驱使我去接触的原因无非就以下几点：</p><ul><li>开发体验、性能提升</li><li>对已有技术的厌倦感和对新鲜事物的好奇心</li><li>更多机会与方向</li><li>对未来技术趋势有更好的了解</li></ul><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="写不完的代码">写不完的代码<a class="hash-link" href="#写不完的代码" title="标题的直接链接">​</a></h2><p>首先要知道一点，在任何的软件开发迭代中都没有最终形态的代码。说白话就是代码都是不断更新的，永远写不出最好的代码。</p><p>你能看到如今很多开源项目或者商业项目都在不断新增代码或者功能，除非作者不维护了，不然这份代码可以说写到世界末日。</p><p>究其原因还是因为社会不断在发展，硬件升级，性能提升，不断的业务需求。毕竟人都在进步，社会难道还不能进步。所以必然会有新的技术出现，只是出现的时间快慢，与技术难点突破。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="开发体验性能提升">开发体验、性能提升<a class="hash-link" href="#开发体验性能提升" title="标题的直接链接">​</a></h2><p>毋庸置疑，在购买方面，肯定是买新不买旧，同样的在技术（软件更新）方面也是则从用新不用旧。驱使软件和框架更新的原因也就是新增了某些功能（特性），对用户（开发者）的体验有所提升。一般而言比较少的会存在反向更新的操作，这里除了某些国产软件<del>（如某信，某 Q 等等）</del></p><p>就我对此的看法也是如此，假设一个开发工具启动花费了 5s 钟启动，而在它的最新版只需要 1s 钟就能够启动，你会选择更新尝试吗？。再比如一个框架原先的代码需要 10 行代码才能实现的功能，由于新版本提供一个语言级别的语法糖，使该功能只需一行。</p><p>并且我对开发体验非常在意，尤其是不好用，或者不好配置的东西，我基本秉持能不用就不用的原则，像 vue2 与 webpack 就是这样，我跟愿意使用 vue3 或 vite。诸如此类的替换有非常多，便不一一列举。</p><p>要我肯定毫不犹豫的更新去使用，但有些人可能对此提升不是很在意，又或者是升级的成本相对较高，也可能是因为这个开发工具（框架）他用的比较少，更新的意义自然就不大。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="对代码厌倦和对新事物的好奇心">对代码厌倦和对新事物的好奇心<a class="hash-link" href="#对代码厌倦和对新事物的好奇心" title="标题的直接链接">​</a></h2><p>我写代码时常处于三分钟热度的状态，有些东西可能也就一开始的时候感觉比较新奇，然后就不了了之了。我对此的看法主要还是容易对代码产生厌倦感，不想写代码，不愿意学习。当厌倦感产生了，自然而然就放弃编写，也就是三分钟热度的状态。不过也能侧重体验一点，那就是肯定我对此不是那么感兴趣，既然不是那么感兴趣的东西，又何必在写下去呢？</p><p>接着过段时间又遇到了一个新的技术，冲击了我的好奇心，开始尝试。 如此重复，就会发现啥都学了一点，但实际是啥都没学到。但至少，让我肯去学习，而不是在原地踏步。而从心底里就想接触的新鲜事物，每次接触到就能满足自己内心的好奇心，就这一点我便知足了。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="重构的艺术">重构的艺术<a class="hash-link" href="#重构的艺术" title="标题的直接链接">​</a></h3><p>如果回头看看自己 1，2 年前写的代码，会发现原来自己也曾写过丑陋不堪的代码，也成为过自己所讨厌的样子。如果这份代码我将来还会用到，那么我就尝试去重构，也许在当时还不支持某种特性，代码就无法简化。基于现有的水平，便会发现很多代码都有可改善的地方，可以化繁为简。代码重构属于将杂乱摆放的东西，收拾的整整齐齐的样子。重构是在提升观赏度和舒适度的同时，还减少 bug 的诱发概率。</p><blockquote><p>在编程语言级别水平上，也就是我为什么会想去使用最新的版本（ES2022，TypeScript 4.9），即便是兼容性的问题，我也会去使用，就是因为能够满足我对代码的舒适度，这便足以。</p></blockquote><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="生态与解决问题方面">生态与解决问题方面<a class="hash-link" href="#生态与解决问题方面" title="标题的直接链接">​</a></h3><p>我是很感谢新技术的出现，他实实在在的解决了一些我已有的痛点，提升了我的开发体验。当然它也让我踩了无数的坑，也折磨过我。但不可否认的是，我的自我解决问题的能力也在不断提升，如果我学的是一门比较流行的技术，那么我所遇到的问题，很有可能别人也遇到过，并将他的解决方案分享出来。而我就很容易根据报错描述找他的解决方案来解决我的问题。但在新技术下，用的人自然而然就少了，所分享的问题解决方案也就少了，所以在这种环境下，我就需要自行翻看源码，查阅文档，提出 issues 才能够解决问题。自然而然解决问题的能力也就有所提升。</p><p>像流行框架能有这么有问题解决方案，就是因为强大的生态，同时这也是生态好处之一。</p><blockquote><p>因此也有很多人顾忌使用新技术，就是因为遇到问题不知如何解决。包括我也是，但通常我会观察一段时间，等成熟了我才去尝试，而不是直接上手，避免踩一些不必要且耗时的坑。</p></blockquote><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="总是活在舒适圈">总是活在舒适圈<a class="hash-link" href="#总是活在舒适圈" title="标题的直接链接">​</a></h3><p>在圈内有着熟悉的环境，与认识的人相处，做自己会做的事，所以会感到很轻松、很自在。但是当踏出这个圈子的界限的时候，就马上会面对不熟悉的变化与挑战，因而感到不舒适，很自然的想要退回到舒适圈内。</p><p>我在阅读英文博客的时候，我也时常感到不舒适，阅读不下去。我也很想回到舒适圈，使用翻译软件来翻译但是这样就会导致我非常依赖翻译软件，就间接失去了一次英文环境与英语能力的提升。</p><p>长时间待在舒适圈，会让自己过得很舒服，但是却很难提升自己。不过想想也是，<strong>提升的过程不就是苦尽甘来</strong>。</p><p>以目前来看有一种这样的学习趋势，别人学什么，当下什么技术火，就去学什么。我其实特别反感这种现象，也不推崇这种学习理念。我会做出我的解释：</p><p>首先，什么技术会火就学什么，这固然没什么问题，如果一门技术没有热度，没有生态，那么学了的意义不大，一是难有长久稳定的技术发展，二是不能将技术变现。而绝大多数人之所以选择火的技术，有很大一点是因为有前人给他铺了很多“路”，如学习指南，思维导图，视频教程仿佛跟着学就能成为编程大牛似的。可一旦没有这些，就不知道该如何下手。始终都是跟着别人步伐学习，思维很难扩散出去。</p><p>并且这种现象必然会导致内卷，首先看看国内的技术，Vue 和 Spring boot 的可以说 10 个 web 开发程序员中有 8 个技术栈是这套，比麻花还是卷了，可薪资呢？</p><p>这里我并不想贴相关的薪资图片，你完全可以自行去了解，但是我可以肯定且直接告诉你，React 的薪资普遍会比 Vue 高上一截，而 Java 后端开发，如果技术只停留在 CRUD 的层面，工资普遍也高不了多少。</p><p><strong>如果你不去拓展自身的技术栈，不多去了解一些未来的可能会火的技术，还停留在当下，活在舒适圈。那么薪资大概率不变，并且自身会有很大被劝退的概率。</strong></p><p>与时俱进，这是我认为不断学习新技术，提升自身技术栈，非常重要的一点。<strong>过得舒服，反而过得难受</strong></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="更多的机会与方向">更多的机会与方向<a class="hash-link" href="#更多的机会与方向" title="标题的直接链接">​</a></h2><p>技术更新迭代越来，也带来越多的机会，这对于接触前端的我感到尤为明显。假设当下又出了某某技术，那么必然会引起软件开发者的关注，于此同时就带来了维护者，贡献者，甚至是一些金主投资商。像 <a href="https://tailwindcss.com" target="_blank" rel="noopener noreferrer">Tailwind CSS</a> 与 <a href="https://vercel.com/" target="_blank" rel="noopener noreferrer">Vercel</a> 就是一个很好的例子，两个前端明星项目，有兴趣可以了解它们的故事。</p><p><strong>不过这种机会在国内不太多见，反而在国外特别普遍。</strong></p><p>但必须要承认的一个事实，如今技术发展过于迅猛，加上目前就业行情不容乐观，当别人了解过的东西，你却不了解，那么别人所能遇到的机会自然就比你多。说的难听点也就是没有对技术提升的想法，今后项目迭代的过程中使用到一些前沿技术就难以胜任。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="没有目标的学习等同于乱学">没有目标的学习，等同于乱学<a class="hash-link" href="#没有目标的学习等同于乱学" title="标题的直接链接">​</a></h3><p><strong>没有一个明确的目标，学任何（新）技术都是乱学，充其量也就只比不学好一点。</strong></p><p>这在我初学阶段尤为明显，我一开始也不清楚我以后会从事什么行业，可以说是什么都乱学一顿。在我的一篇年终总结 <a href="https://kuizuo.cn/2019.7-2020.7-log" target="_blank" rel="noopener noreferrer">2019.7-2020.7 编程年记</a> 中可以说是尤为明显，尤其是在 <a href="https://kuizuo.cn/2019.7-2020.7-log#%E5%AE%9A%E4%B8%80%E4%B8%8B%E6%98%8E%E5%B9%B4%E7%9A%84%E7%9B%AE%E6%A0%87" target="_blank" rel="noopener noreferrer">定一下明年的目标</a> 的段落中，最后我真正深入学习的也就是只有 Web 开发。</p><p>我相信很多初学者也会遇到类似的问题，不知道学什么，想学好找工作的但是薪资不高，想学感兴趣的但又不知如何下手。说实话，要我回到当初，我也难以抉择。也有可能处于摆烂状态或是乱学一同，到头来啥都会一点点，但是又好像啥也不会的样子。</p><p>这里我是奉劝先定一个短期的目标，为了这个目标我要去学习哪些技术知识。这里就说我未来一年的目标为例：我未来一年想写开源项目，为开源社区做一份微薄贡献，乃至从事开源行业。那么我就需要了解写开源我需要那些预备知识，例如 Github 的使用，项目规范，英文交流等对应开源项目的技能知识，这才是我所该学的，并且能够实实在在用到的，且对我未来有用的。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="对未来技术趋势有更好的了解">对未来技术趋势有更好的了解<a class="hash-link" href="#对未来技术趋势有更好的了解" title="标题的直接链接">​</a></h2><p><strong>当你了解的技术越多，你就越能知道自己适合哪些技术。</strong>并且当你去尝试过后，更能加深你对某个技术的信仰。</p><p>在未来技术只会越来越多，因为当下要解决太多问题，有太多的业务需求开发。只要不断有需求，就不断会有技术更新。但技术更新必然是朝着好的方向去发展，即技术趋势方向。而了解的越多，能看到技术趋势也就更远，方向就更难偏移。</p><p>像我目前就比较看好未来 js/ts 的发展，这也是使我从逆向和爬虫转到 Web 开发行业上，并且将会长期发展下去。</p><p>但很多程序员就缺乏这种对<strong>技术的认可</strong>，甚至眼光比较浅薄，认为自己当下所学的就足以，可没却从未到真正的”外面”去看过。</p><p>当有了对未来技术趋势的了解，自身就有相对明确的目标学习，而不是漫无目的学习，跟风学习。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="我是如何了解到这些技术的">我是如何了解到这些技术的？<a class="hash-link" href="#我是如何了解到这些技术的" title="标题的直接链接">​</a></h2><p>也许有些人并不在意新技术是否学习，而是好奇我是如何知道这些技术的。这个问题非常好，我自己简单总结通过那些途径来获取到这些相关技术的新闻。</p><p>主要有以下几种来源：</p><ul><li>多加技术群，不定时看群聊</li><li><strong>多刷技术大佬文章（推特），或者是技术公众号和掘金（最多的也是最有效的）</strong></li><li>订阅一些技术周刊，或订阅某个项目</li></ul><p>没啥技巧，就靠刷技术文章，自然而然的了解也就越来越多了。</p><p>尤其是第二点，也是我了解这些新技术的最直接途径。与其自己去主动了解新的技术，将刷抖音的时间改成刷技术文章，了解新技术就是分分钟的事情。可以说我写博客是因为这个契机，记录自己用到的技术的开发过程，并分享个人的开发体验，让更多人了解到这些新技术。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="面对新技术该怎么学">面对新技术该怎么学？<a class="hash-link" href="#面对新技术该怎么学" title="标题的直接链接">​</a></h2><p>其实更多时候是比较在意如何去学一门新技术，而不是找一门新技术，当阅历多了，技术自然就了解的多。这里我分享下我对于新技术是如何起步与学习的。</p><p>首先我会列举出我近期感兴趣的技术，这一步很关键，我当然不可能每个技术都去尝试一遍，时间精力根本不够。通常在我了解到这个技术的时候，比如文章与视频中，都会介绍到这个的优点与用法，这就足以了。</p><p>但想要进一步的学习，还是得依靠实战项目（至少我都是通过实战项目来学习的），这时候我会看看手头的项目，看看有没有能够基于上面所列举出的新技术升级的想法，如果有的话，那正好就当重构与新技术的学习，这是最好的，也是相对比较节省时间的。</p><p>但如果没有的话，我通常是会考虑另写一个项目，而这个项目可能是某个灵感的实现，也可能是久违想写的项目，或者是复刻某个感兴趣的站点，总之从上面所列举出来的技术中去选择一个来进行实践。在项目实践中去尝试使用这些新技术，哪怕只是实现一个简单的demo，也总比单纯的刷文档，看代码来的有效。</p><p><strong>在项目实践中学习，永远是最直接也是最有效的</strong>。回想你编写课设或者工作的项目，是不是在项目开发中进步的最快？如果这时候还有点时间紧迫感，进步反而会更快。（当然焦虑和压力也会随之提升）</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="最后感悟">最后感悟<a class="hash-link" href="#最后感悟" title="标题的直接链接">​</a></h2><p>关于本文，必然有引来一些不同看法与见解，每个人都有对不同事物的理解，我只是将我对新技术的看法，以文章的方式输出出来。本文并未带有任何的技术的偏见，我对任何技术都保持一视同仁，并且愿意去尝试学习。</p><p>不必抱怨新技术发展的过快，自己来不及学，学不完。或者担心自己学的东西在未来将会淘汰，等同于白学。学习过程就是一个非常好的经验总结，当你回顾整个学习过程，其实都没有白学。反而多一次的学习过程，在未来学习新的东西时，学习的成效也会显著提升。保持不断学习，就永远来的及学习。</p><p>更多时候，不应该只学如何使用，而是该想想这东西是在什么样的契机下如何被创造出来的，解决了什么问题。而这个问题在未来有没有什么更好的解决方案可替代，如果有更好的解决方案，那么必将又将发展出新的技术来更好的解决这个问题。这在我曾经的学习中，我是从未考虑到的，只专注于学习，而没去了解为什么。</p><p>我是希望越来越多的新技术出现，无论它是为了解决什么，必然能解决某些人的一些需求，那么它的出现就很有意义。至于未来该技术和相关生态发展如何，不得而知。也没人敢笃定未来这个技术必定会火，就去学这门技术。绝大大多情况下都是比较看好这门技术，认为未来可期，同时又感兴趣，就开始学习并使用。</p>]]></content:encoded>
            <category>随笔</category>
            <category>杂谈</category>
            <category>感悟</category>
        </item>
        <item>
            <title><![CDATA[前端自动化测试]]></title>
            <link>https://kuizuo.cn/frontend-automated-testing</link>
            <guid>frontend-automated-testing</guid>
            <pubDate>Thu, 06 Oct 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[v2-45d641f2191559d4eff581d0607efd611440w]]></description>
            <content:encoded><![CDATA[<p><img loading="lazy" src="https://img.kuizuo.cn/v2-45d641f2191559d4eff581d0607efd61_1440w.jpg" alt="v2-45d641f2191559d4eff581d0607efd61_1440w" class="img_ev3q"></p><p>如果你的项目要长期使用并维护的话，那么代码自动测试就非常有必要使用。因为没人能保证在修改代码后，不会引发其他额外 bug（功能失效，渲染失败），而在修改完代码后，跑一遍测试就能很大程度让开发者发现自己所修改的代码是否存在问题，是否会导致原有功能失效。</p><p>尤其是在其他人接手这个项目时，诱发 bug 的概率自然也就更高（因为他有很大的可能不知道这部分代码的上下文的功能用途），所以这也就是为什么很多开源项目与大型企业的公司都会使用自动化测试，以及要求一定的代码覆盖率。</p><p>当然如果项目不是长期维护的，那么完全没必要编写测试代码，这么做无疑是在浪费开发者的时间。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="适合引入自动化测试的场景">适合引入自动化测试的场景<a class="hash-link" href="#适合引入自动化测试的场景" title="标题的直接链接">​</a></h2><p>提前简单总结下<strong>适合引入自动化测试的场景（优点）</strong>：</p><ul><li><p>中长期项目迭代/重构（需要频繁的修改代码）</p></li><li><p>准确定位代码问题，提高代码质量</p></li><li><p>引用了不可控的第三方依赖，极易发生 bug（例：beta 版相关的包）</p></li></ul><p>测试的目的在于，<strong>及时发现错误，提高代码质量和开发效率，避免存在 BUG 的代码发布上线造成损失</strong>。</p><p>自动化测试要注意的点</p><ul><li><p>并不是所有项目都适合引入自动化测试，反而会增加一定代码成本</p></li><li><p>如果项目开发阶段还不稳定，那么手动测试效率会比自动化测试更好</p></li><li><p>有些代码可能这辈子都不会在碰第二次，就没有编写自动化测试的意义</p></li></ul><p><strong>在代码编写阶段，建议只对重点功能进行测试，没必要一定追求过高的测试覆盖率</strong>。注意，是编写阶段</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="测试思想">测试思想<a class="hash-link" href="#测试思想" title="标题的直接链接">​</a></h2><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="tddtest-driven-development测试驱动开发">TDD：Test-Driven Development（测试驱动开发）<a class="hash-link" href="#tddtest-driven-development测试驱动开发" title="标题的直接链接">​</a></h3><ul><li>TDD：Test-Driven Development（测试驱动开发）：TDD 则要求在编写某个功能的代码之前先编写测试代码，然后只编写使测试通过的功能代码，通过测试来推动整个开发的进行</li></ul><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="bddbehavior-driven-development行为驱动开发">BDD：Behavior-Driven Development（行为驱动开发）<a class="hash-link" href="#bddbehavior-driven-development行为驱动开发" title="标题的直接链接">​</a></h3><ul><li>BDD：Behavior-Driven Development（行为驱动开发）：BDD 可以让项目成员（甚至是不懂编程的）使用自然语言来描述系统功能和业务逻辑，从而根据这些描述步骤进行系统自动化的测试</li></ul><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="自动化测试类型">自动化测试类型<a class="hash-link" href="#自动化测试类型" title="标题的直接链接">​</a></h2><p>测试类型有以下几种：</p><ul><li><p><strong>单元测试（Unit Testing）</strong></p><p>代码中多个组件共用的工具类库、多个组件共用的子组件等。通常情况下，在公共函数/组件中一定要有单元测试来保证代码能够正常工作。单元测试也应该是项目中数量最多、覆盖率最高的。</p></li><li><p><strong>集成测试（Integration Testing）</strong></p><p>测试经过单元测试后的各个模块组合在一起是否能正常工作。会对组合之后的代码整体暴露在外接口进行测试，查看组合后的代码工作是否符合预期。集成测试是安全感较高的测试，能很大程度提升开发者的信心，集成测试用例设计合理且测试都通过能够很大程度保证产品符合预期。</p></li><li><p><strong>UI 测试 （UI Testing）</strong></p><p>对于前端的测试，是脱离真实后端环境的，仅仅只是将前端放在真实环境中运行，而后端和数据都应该使用 Mock 的。</p></li><li><p><strong>端对端测试（End-to-End Testing）</strong></p><p>将整个应用放到真实的环境中运行，包括数据在内也是需要使用真实的。</p></li></ul><p>关于测试框架，我主要使用 <a href="https://vitest.dev/" target="_blank" rel="noopener noreferrer">Vitest</a> 与 <a href="https://cypress.io/" target="_blank" rel="noopener noreferrer">Cypress</a>。这两个作为测试框架都相对比较新，并且性能与开发上会比 <a href="https://jestjs.io/" target="_blank" rel="noopener noreferrer">Jest</a>，<a href="https://pptr.dev/" target="_blank" rel="noopener noreferrer">Puppeteer</a> 来的好。本文的一些测试示例也是基于这两类框架之上。</p><div class="theme-admonition theme-admonition-note alert alert--secondary admonition_LlT9"><div class="admonitionHeading_tbUL"><span class="admonitionIcon_kALy"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>备注</div><div class="admonitionContent_S0QG"><p>其实还有个接口测试，不过这就不是前端要关心的内容了，所以就没列举在这上面。</p></div></div><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="自动化测试的误区">自动化测试的误区<a class="hash-link" href="#自动化测试的误区" title="标题的直接链接">​</a></h2><p>自动化测试和普通说的测试是有些不大一样的，有很多测试，其实都不能归类为前端自动化测试。这里我会举个例子来说明一下。</p><p>在自动化测试来说有个要求：<strong>自动化测试要的不是某次测试执行的是否通过，而是每次执行都必须通过。</strong></p><p>怎么理解这句话呢：比方说我要测试获取博客列表的函数，假设实际的接口失效了，那么就会导致结果与预期不一致，就会导致代码测试不通过。既然不通过，那我就要去查看为什么不通过。当我点击这个单元测试的时，发现原来是后端接口失效了。可万一哪天这个接口突然好了，又或者发现刚刚原来没插网线导致的请求失败导致测试不通过。像这些 <strong>不稳定因素</strong> 在前端自动化测试中就会使用 mock 的方式，强制返回一定格式的数据给测试框架。到这里你可能会好奇，为什么要这么做？</p><p>想想看，如果因为接口失效导致测试失败，是因为测试代码的问题吗？那跟测试代码有毛关系，明显是后端或者服务器的问题。我们要测试的是<strong>获取博客列表的函数，而不是在测试接口（接口自动化测试）</strong>。测试接口不应该是前端要做的事情。确保后端返回正确的响应结果，前端能够对这些数据进行处理渲染，这才是我们要做的。</p><p><strong>每次测试都存在不可控的因素，就会导致每次测试结果都有可能不同，这就违背测试的意义了。</strong> 所以这也就是为什么要数据 mock 的原因了。</p><p><strong>给测试输入的值，在经过测试后，要保证输出的值与我们预期想要结果的值相同。</strong></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="自动化测试到底在测试什么">自动化测试到底在测试什么？<a class="hash-link" href="#自动化测试到底在测试什么" title="标题的直接链接">​</a></h2><p>其实目前前端有个尴尬的点，目前绝大部分实际业务项目里，前端的单元测试都没啥鸟用，UI 自动测试又太难搞。</p><p>这就导致很多开发者不清楚到底要测试什么，导致对测试特别不重视，包括我一开始也是如此。看到很多文章都是在演示测试 1+1 =2，介绍测试框架，很少从实际项目中出发进行测试。不过原因无非就是实际项目写的少，就别说测试代码了。再不然就是写过的代码都不怎么维护（重构，阅读），自然的就不会去写测试了。</p><p>不过确实没什么好举例的，因为太多东西可以写成单元测试了，比方说<code>formatTime.test.ts</code>, <code>param2Obj.test.ts</code>,<code>validate.test.ts</code>，从文件名就知道在测试什么了，就看开发者想不想写的问题了。</p><p>可以到 <a href="https://github.com/vitest-dev/vitest" target="_blank" rel="noopener noreferrer" title="vitest-dev/vitest">vitest-dev/vitest</a> / <a href="https://github.com/facebook/jest" target="_blank" rel="noopener noreferrer">facebook/jest</a> 等测试框架中的 example 中查看测试案例。</p><p>关于 UI 测试和 e2e 测试，我非常推荐看看 cypress 的<a href="https://example.cypress.io/todo" target="_blank" rel="noopener noreferrer" title="Todo示例">Todo 示例</a>，测试的特别清楚，这里放张官方测试结果供参考。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_a_B5FPFfJI.png" class="img_ev3q"></p><p>这里补充一句，vitest 是能做 UI 测试的，可以通过 <a href="https://github.com/vuejs/test-utils" target="_blank" rel="noopener noreferrer" title="vuejs/test-utils">vuejs/test-utils</a> 库来实现，但是 vitest 的运行环境是 nodejs，通过 jsdom 等库来模拟浏览器环境，而 cypress 是实实在在的运行在浏览器上，而且有可视化页面操作。这两者的区别也就是运行时环境的区别，有些实际场景对真实环境是有需求的，所以针对 UI 测试更多会选择像 cypress 这种直接运行在浏览器的测试框架。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="为何我开始重视起测试">为何我开始重视起测试?<a class="hash-link" href="#为何我开始重视起测试" title="标题的直接链接">​</a></h2><p>在之前我根本不会在意测试，就连已有的测试代码我都不会尝试运行。就在前段时间我正重构我的一个项目时，但当我写了一大部分的代码后，我尝试运行发现有些功能失效了。于是我进一步的排查，终于找到我修改代码并还原成我原来的代码。</p><p>假设一开始有份完整的测试代码，当我修改一部分代码后，跑一遍测试查看测试情况。发现没问题后，再开始下一步的代码工作，反复测试，直到最终重构完毕。<strong>与其浪费代码的时间，不如将这些时间去用来完善测试代码</strong>。不仅自己后续使用需要，到时候项目交付给别人的时，别人也不至于修改你的代码时兢兢业业。</p><p><strong>究其原因是为了保证代码质量</strong>。</p><p>当然，虽说重视，但我也不会立马为已有的项目增加测试.耗时且费力不讨好。更多时候只会在准备重构的项目，或者是新项目上去增加测试代码。</p><p>编写这篇文章主要解惑我自己对往常对测试的看法，也借此机会养成 TDD 模式的开发的习惯。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="参考文章">参考文章<a class="hash-link" href="#参考文章" title="标题的直接链接">​</a></h2><p><a href="https://juejin.cn/post/6844904194600599560" target="_blank" rel="noopener noreferrer">试试前端自动化测试！（基础篇） - 掘金 (juejin.cn)</a></p>]]></content:encoded>
            <category>frontend</category>
            <category>test</category>
        </item>
        <item>
            <title><![CDATA[Gitea 与 Drone 实践]]></title>
            <link>https://kuizuo.cn/gitea-drone-practice</link>
            <guid>gitea-drone-practice</guid>
            <pubDate>Wed, 28 Sep 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[使用 Gitea 搭建一个轻量级 git 私有仓库，并配置 Drone CI 来实现自动构建与部署。]]></description>
            <content:encoded><![CDATA[<p>之前搭建过 Gitlab，但是就只是搭建而已，并未实际使用，因为我大部分的代码还是存放在 <a href="https://github.com/kuizuo?tab=repositories" target="_blank" rel="noopener noreferrer">Github</a> 上。</p><p>并且大部分项目都是在 <a href="https://vercel.com" target="_blank" rel="noopener noreferrer">Vercel</a> 上运行的（Vercel 是真好用），但是最近国内访问 vercel 情况不容乐观，貌似被墙了呜呜。然后 Gitlab 的资源占用非常严重，几乎占用了一半的服务器性能，可 <a href="https://kuizuo.cn/gitlab-code-management-environment#%E8%BF%90%E8%A1%8C%E7%8A%B6%E6%80%81" target="_blank" rel="noopener noreferrer">点我</a> 查看运行状态。与此同时，随着很多私有项目越来越多，使用 git 私有仓库以及 Vercel 部署，肯定不如自建私有 git 服务和自有服务器部署使用体验来好。</p><p>于是就想搭建一个轻量级仓库，同时支持 CI/CD。经过一番的调研，决定使用 Gitea 和 Drone 作为解决方案。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="gitea">Gitea<a class="hash-link" href="#gitea" title="标题的直接链接">​</a></h2><p><a href="https://gitea.io/zh-cn/" target="_blank" rel="noopener noreferrer" title="Gitea">Gitea</a> 是一个开源社区驱动的轻量级代码托管解决方案，后端采用 <a href="https://golang.org/" target="_blank" rel="noopener noreferrer" title="Go">Go</a> 编写，采用 <a href="https://github.com/go-gitea/gitea/blob/master/LICENSE" target="_blank" rel="noopener noreferrer" title="MIT">MIT</a> 许可证.</p><p>你可以在 <a href="https://docs.gitea.io/zh-cn/comparison/#%E6%A8%AA%E5%90%91%E5%AF%B9%E6%AF%94-gitea-%E4%B8%8E%E5%85%B6%E5%AE%83-git-%E6%89%98%E7%AE%A1%E5%B7%A5%E5%85%B7" target="_blank" rel="noopener noreferrer" title="横向对比 Gitea 与其它 Git 托管工具">横向对比 Gitea 与其它 Git 托管工具</a> 查看 gitea 与其他 git 工具的优势与缺陷。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="安装">安装<a class="hash-link" href="#安装" title="标题的直接链接">​</a></h3><p>这里我选用 Docker 进行安装，安装文档可在<a href="https://docs.gitea.io/zh-cn/" target="_blank" rel="noopener noreferrer" title="官方文档">官方文档</a>中查看其他安装方式</p><div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">docker-compose.yml</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token key atrule">version</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'3'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token key atrule">networks</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token key atrule">gitea</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token key atrule">external</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> </span><span class="token boolean important">false</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token key atrule">volumes</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token key atrule">gitea</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token key atrule">driver</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> local</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token key atrule">services</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token key atrule">server</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token key atrule">image</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> gitea/gitea</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain">1.17.1</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token key atrule">container_name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> gitea</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token key atrule">environment</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain"> USER_UID=1000</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain"> USER_GID=1000</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token key atrule">restart</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> always</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token key atrule">networks</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain"> gitea</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token key atrule">volumes</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain"> gitea</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain">/data</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain"> /etc/timezone</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain">/etc/timezone</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain">ro</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain"> /etc/localtime</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain">/etc/localtime</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain">ro</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token key atrule">ports</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'10800:3000'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'2221:22'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>根据自身需求配置 docker-compose.yml 内容。运行 <code>docker-compose up</code> 等待部署</p><p>服务器防火墙与云服务安全组都需要开放端口才可访问，<code>服务器ip:10800</code>，将会出现如下界面</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_8ix-AMvt3t.png" class="img_ev3q"></p><p><strong>因为修改配置相对比较麻烦，所以在首次安装的时候，请根据实际需求进行配置安装。</strong></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="修改配置">修改配置<a class="hash-link" href="#修改配置" title="标题的直接链接">​</a></h3><p>假设要修改其中的配置的话，gitea 的后台管理面板是无法直接修改的。需要到 <code>/data/gitea/conf/app.ini</code> 中修改，具体修改的配置 参阅 <a href="https://docs.gitea.io/zh-cn/customizing-gitea/" target="_blank" rel="noopener noreferrer" title="自定义 Gitea 配置 - Docs">自定义 Gitea 配置 - Docs</a></p><div class="theme-admonition theme-admonition-caution alert alert--warning admonition_LlT9"><div class="admonitionHeading_tbUL"><span class="admonitionIcon_kALy"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>注意</div><div class="admonitionContent_S0QG"><p>必须完全重启 Gitea 以使配置生效。</p></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="迁移仓库">迁移仓库<a class="hash-link" href="#迁移仓库" title="标题的直接链接">​</a></h3><p>从其他第三方 git 仓库迁移到 gitea，可以访问<a href="https://git.kuizuo.cn/repo/migrate" target="_blank" rel="noopener noreferrer" title="https://git.kuizuo.cn/repo/migrate">https://git.kuizuo.cn/repo/migrate</a> 来迁移仓库</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_sRQV5hAKUh.png" class="img_ev3q"></p><p>稍等片刻，取决于访问 github 仓库的速度。有可能还会迁移失败，就像下面这样。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_X9IpG2q36n.png" class="img_ev3q"></p><p>所以可以申请访问令牌（Access Token），在 <a href="https://github.com/settings/tokens/new" target="_blank" rel="noopener noreferrer" title="New Personal Access Token">New Personal Access Token</a> 处创建。迁移成功后，如下图所示</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_Rug0AmD8GE.png" class="img_ev3q"></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="镜像仓库">镜像仓库<a class="hash-link" href="#镜像仓库" title="标题的直接链接">​</a></h3><p>很大部分时间，gitea 只能作为我的副仓库，或者说 github 的镜像仓库。</p><p>gitea 也提供镜像仓库的方案，官方文档<a href="https://docs.gitea.io/en-us/repo-mirror/" target="_blank" rel="noopener noreferrer" title="Repository Mirror">Repository Mirror</a></p><p><img loading="lazy" src="https://img.kuizuo.cn/image_Q5IaHnKCYJ.png" class="img_ev3q"></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="drone">Drone<a class="hash-link" href="#drone" title="标题的直接链接">​</a></h2><p>由于 Gitea 并没有内置 CI/CD（持续集成/持续部署） 的解决方案，所以需要配置第三方的，这里推荐使用 Drone CI。</p><p>Drone 是面向繁忙开发团队的自助服务持续集成平台。相对于常见的Jenkins，选中 Drone 的原因在于它非常简洁，不像 Jenkins 那样复杂，同时它拥有可以满足基本需求的能力，并且提供了许多实用的<a href="https://plugins.drone.io/" target="_blank" rel="noopener noreferrer">插件</a>，如GitHub，Email，微信，钉钉等</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="安装-1">安装<a class="hash-link" href="#安装-1" title="标题的直接链接">​</a></h3><p>由于我们使用了 gitea，所以 drone 中选择 gitea 来安装，这是官方文档 <a href="https://docs.drone.io/server/provider/gitea/" target="_blank" rel="noopener noreferrer" title="Gitea | Drone">Gitea | Drone</a>，照着操作即可。</p><p>需要安装 Server 和 Runner，一个是 Drone 的服务，另一个用于检测 Git 记录，以重新构建项目。</p><p>这里贴下 drone 的 docker 配置（根据文档和自己部署的 git 服务配置来替换）。</p><div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">server</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">docker run \</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">volume=/var/lib/drone</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain">/data \</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">env=DRONE_GITEA_SERVER=https</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain">//try.gitea.io \</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">env=DRONE_GITEA_CLIENT_ID=05136e57d80189bef462 \</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">env=DRONE_GITEA_CLIENT_SECRET=7c229228a77d2cbddaa61ddc78d45e \</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">env=DRONE_RPC_SECRET=super</span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">duper</span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">secret \</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">env=DRONE_SERVER_HOST=drone.company.com \</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">env=DRONE_SERVER_PROTO=https \</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">publish=80</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain">80 \</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">publish=443</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain">443 \</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">restart=always \</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">detach=true \</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">name=drone \</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  drone/drone</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token number" style="color:rgb(9, 134, 88)">2</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">runner</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">docker run </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">detach \</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">volume=/var/run/docker.sock</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain">/var/run/docker.sock \</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">env=DRONE_RPC_PROTO=https \</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">env=DRONE_RPC_HOST=drone.company.com \</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">env=DRONE_RPC_SECRET=super</span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">duper</span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">secret \</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">env=DRONE_RUNNER_CAPACITY=2 \</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">env=DRONE_RUNNER_NAME=my</span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">first</span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">runner \</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">publish=3000</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain">3000 \</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">restart=always \</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">name=runner \</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  drone/drone</span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">runner</span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">docker</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token number" style="color:rgb(9, 134, 88)">1</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>查看连接情况</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token function" style="color:rgb(0, 0, 255)">docker</span><span class="token plain"> logs runner</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>执行完毕后，然后访问线上的 drone 服务，点击 CONTINUE 将会跳转到你的 Git 授权页面</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_rUdNHPlB73.png" class="img_ev3q"></p><p>点击应用授权，再次回到 drone，此时页面 Dashboard 列出了 gitea 的所有仓库（如果没有的话，可以点击右上角的 SYNC 来同步）。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_TXWZgDOhrQ.png" class="img_ev3q"></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="实战">实战<a class="hash-link" href="#实战" title="标题的直接链接">​</a></h2><p>上述只是安装了，我们还需要编写 <code>.drone.yml</code> 配置文件来告诉 drone 我们要做什么，编写过程与 Github Action类似。相关文档: <a href="https://docs.drone.io/pipeline/overview/" target="_blank" rel="noopener noreferrer" title="Overview | Drone">Pipeline | Drone</a></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="部署前端项目">部署前端项目<a class="hash-link" href="#部署前端项目" title="标题的直接链接">​</a></h3><p>这里就选用 <a href="https://github.com/antfu/vitesse" target="_blank" rel="noopener noreferrer" title="antfu/vitesse">antfu/vitesse</a> 作为演示。这里省略 clone 仓库的步骤。进入到自己的 gitea 仓库，然后添加 <code>.drone.yml</code> 文件，内容如下：</p><div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token key atrule">kind</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> pipeline</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token key atrule">type</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> docker</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> ci</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token key atrule">steps</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> install &amp; build</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token key atrule">image</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> node</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token key atrule">commands</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain"> npm config set registry http</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain">//mirrors.cloud.tencent.com/npm/</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain"> npm i </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">g pnpm</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain"> pnpm i</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain"> pnpm run build</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> upload</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token key atrule">image</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> appleboy/drone</span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">scp</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token key atrule">settings</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token key atrule">host</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token key atrule">from_secret</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> host</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token key atrule">username</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token key atrule">from_secret</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> username</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token key atrule">password</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token key atrule">from_secret</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> password</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token key atrule">port</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">22</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token key atrule">command_timeout</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> 2m</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token key atrule">target</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> /www/wwwroot/$</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">DRONE_REPO_OWNER</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain">/$</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">DRONE_REPO_NAME</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token key atrule">source</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain"> ./dist</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>这里对 <code>.drone.yml</code> 配置进行详解：</p><p>其中 build 这个不用多说，与 node 构建相关的，不过多介绍。</p><p>upload 则使用<a href="https://plugins.drone.io/plugins/scp" target="_blank" rel="noopener noreferrer" title="appleboy/drone-scp">appleboy/drone-scp</a>插件，可以将构建出来的文件通过发送到服务器指定位置。在这里 source 对应就是构建的文件，target 则是要移动的位置，这里的 <code>/www/wwwroot/${DRONE_REPO_OWNER}/${DRONE_REPO_NAME}</code> 对应本项目为 <code>/www/wwwroot/kuizuo/vitesse</code>。此外 ssh 的 host，username，password 或 key，都作为环境变量（私有变量的方式传递，这在 drone 的控制台中可以设置）。</p><p>由于每次构建可能需要删除原有的已部署的资源文件，那么可以使用 <a href="https://plugins.drone.io/plugins/ssh" target="_blank" rel="noopener noreferrer">appleboy/drone-ssh</a> 插件来执行终端命令来删除，例如</p><div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token key atrule">kind</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> pipeline</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> default</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token key atrule">steps</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> deploy</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token key atrule">image</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> appleboy/drone</span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">ssh</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token key atrule">environment</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token key atrule">DEPLOY_PATH</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token key atrule">from_secret</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> /www/wwwroot/$</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">DRONE_REPO_OWNER</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain">/$</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">DRONE_REPO_NAME</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token key atrule">settings</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token key atrule">host</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token key atrule">from_secret</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> host</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token key atrule">username</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token key atrule">from_secret</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> username</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token key atrule">password</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token key atrule">from_secret</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> password</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token key atrule">port</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">22</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token key atrule">command_timeout</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> 2m</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token key atrule">envs</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">DEPLOY_PATH</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token key atrule">script</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain"> rm </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">rf $$</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">DEPLOY_PATH</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>具体就因人而异了，这里我仅作为演示。</p><p>大致介绍完毕（其实已经介绍差不多了），有关更多插件可以参阅 <a href="https://plugins.drone.io" target="_blank" rel="noopener noreferrer" title="drone 插件">drone 插件</a>。这里开始演示，进入 drone 页面，找到仓库，默认情况下，所有仓库都处于未激活状态。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_6XBrsAY8VE.png" class="img_ev3q"></p><p>点击 <code>ACTIVATE REPOSITORY</code> 根据选项选择，点击右上角的<code>NEW BUILD</code>选择分支，添加 drone 环境变量（私有变量），即上面的 from_secret 后面的内容（host，username，password），即可开始运行。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_PAM6QQS1V_.png" class="img_ev3q"></p><p>静等 PIPELINE 执行完毕，结果如下</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220928152635955.png" alt="image-20220928152635955" class="img_ev3q"></p><p>此时打开宝塔，跳转到指定目录下，就可以看到构建的内容都已经放到指定位置了</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220928152725853.png" alt="image-20220928152725853" class="img_ev3q"></p><p>这时候只需要配置下 nginx，就能将页面展示到公网上，这里就不在这里赘述。当完成上述配置完毕后，每次只需要 pull request，drone 就会自动拉取 gitea 的代码，并开始执行<code>.drone.yml</code>中的任务。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="部署-nest-项目">部署 nest 项目<a class="hash-link" href="#部署-nest-项目" title="标题的直接链接">​</a></h3><p>TODO。。。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="参考文章">参考文章<a class="hash-link" href="#参考文章" title="标题的直接链接">​</a></h2><p><a href="https://juejin.cn/post/7073380337766072350" target="_blank" rel="noopener noreferrer" title="【CI/CD】搭建drone服务，构建前端cicd工作流，实现博客的自动化打包并部署 - 掘金 (juejin.cn)">【CI/CD】搭建 drone 服务，构建前端 cicd 工作流，实现博客的自动化打包并部署 - 掘金 (juejin.cn)</a></p><p><a href="https://learnku.com/articles/71333" target="_blank" rel="noopener noreferrer">单机部署 CI/CD 进阶版：宝塔+gitea+drone | Laravel China 社区 (learnku.com)</a></p>]]></content:encoded>
            <category>git</category>
            <category>gitea</category>
            <category>drone</category>
        </item>
        <item>
            <title><![CDATA[模拟请求|协议复现方案]]></title>
            <link>https://kuizuo.cn/request-protocol-scheme</link>
            <guid>request-protocol-scheme</guid>
            <pubDate>Sun, 25 Sep 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[模拟请求/协议复现 最佳实践方案]]></description>
            <content:encoded><![CDATA[<p>前段时间看了别人的一个写了羊了个羊刷次数网页版，但是 js 代码做了混淆，然后我的那个解混淆的工具还没适配上，短时间内还原不了。但由于是网页版，所以抓包数据还是能看到的，于是就准备复刻了一个（其实就没有也照样能写出来，因为确实没啥难度）。</p><p>可在此体验：<a href="https://7y8y.vercel.app" target="_blank" rel="noopener noreferrer">7y8y.vercel.app</a> （当然由于官方改动，现在功能已经失效了，但看看页面到不成问题，可能需要科学上网）</p><p>原本我是不考虑写的，但是这背后所涉及到的技术以及技术框架我是特别想聊聊，加之以后我也有很大的可能会再写一个类似的刷 xx 的网页版，所以就考虑写一个类似的模板以便后续应用需求。</p><p>相关模板：<a href="https://github.com/kuizuo/protocol" target="_blank" rel="noopener noreferrer">https://github.com/kuizuo/protocol</a></p><p>与此同时，我也快有半年的时间没碰<strong>协议复现</strong>（网络通信协议重新实现，后文都简称协议复现）。我更喜欢说这个词，也有的人会说<strong>模拟请求</strong>，对应的关键词可能有 post 请求，抓包，发包，爬虫等等，但大致的意思是<strong>抓取请求数据包，然后脱离宿主机（浏览器，手机），将抓取的数据包重新发送一遍</strong>。</p><p>你也可以理解成爬虫，但和爬虫相比，要做的不只是爬取数据，而是要基于某些请求包（或者说调用他人不提供的 api 接口，即爬取），来实现一定的功能。比如登录协议，签到协议，抢购协议，游戏封包等等，然后不依靠宿主机（即不用登录浏览器或者应用设备）就能实现诸如登录，签到等功能（在后台记录是有的）。因为这些都是基于网络通信协议的，只要抓包（抓取数据包），然后使用编程提供的网络请求模块来模拟请求，达到重新发包，重新请求的目的。在网页中有 http 协议，websocket 协议，而游戏中有相应的与游戏服务器对应的协议，邮件短信文件又是不同的协议（这里的协议都叫网络通信协议），所以我个人更倾向于称之为协议复现。</p><p>所以要做协议复现，那基本上有一定的逆向功底和爬虫能力，还有网络通信协议相关的知识了。此次的开发也算是回顾下这些相关技术了。</p><div class="theme-admonition theme-admonition-danger alert alert--danger admonition_LlT9"><div class="admonitionHeading_tbUL"><span class="admonitionIcon_kALy"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"></path></svg></span>危险</div><div class="admonitionContent_S0QG"><p>注：<strong>本项目仅用于学习研究使用，请勿将本项目的任何内容用于商业或非法目的，否则后果自负。</strong></p></div></div><p>在这里容我多废话几句，讲一个我之前的开发经历，可以说这个开发经历算是这篇文章的由来。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="小区开门应用">小区开门应用<a class="hash-link" href="#小区开门应用" title="标题的直接链接">​</a></h2><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="应用需求">应用需求<a class="hash-link" href="#应用需求" title="标题的直接链接">​</a></h3><p>在之前住的一个小区，有个门禁系统，需要安装一个开门的 app（后文都称开门 app），然后注册一个账号到物业那边登记为户主或家庭成员。</p><p>每次开门的时候，都需要打开这个开门 app，然后点击你要的开的门，接着门就打开了。或者叫保安开个门，总之就是特别麻烦，还不提供创建应用快捷方式。</p><p>于是我想的是将接口数据“偷”了过来，将大门列表展示在前端上，然后点击对应的大门，然后将大门 id 转发给原 app 的服务器，就实现了开门的效果，也就是这个小区开门的网页版的核心逻辑。</p><p>大致界面如下，展示小区的大门，点击即可开门（远程）</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_Zv0hXU8h1j.png" class="img_ev3q"></p><p>因为是网页版的，所以只需要在浏览器打开对应的网址，点击大门即可（主要还是这个 app 不提供桌面快捷方式，点击这个 app 还需要观看首屏广告，手机网页浏览器提供某个网站的快捷打开） 。此外他人也不用到物业登记，就能开门，对于一些朋友或者住户来说，省去了物业登记的繁琐。</p><p>不过这个软件还是有挺多要注意的点：首先就是鉴权了，由于我当时主要目的是为了我自己和身边朋友，网站也没有特意发布到互联网上，所以就没做鉴权相关的，不然正常情况下是一定要做鉴权和调用记录的，以及 ip 白名单的。否则搞不好登录原 app 的账号直接因为调用过于频繁直接给禁用了；最主要的安全问题，这里的安全可不只是网站的安全，而是现实的安全。想想如果有一个可以随意进出小区大门的程序，那么任何人都可以进入这个小区，小区的公共设施，业主生活质量安全等等谁来保障？而且最主要所绑定的账号还是我的，万一小区真出了事，那么我的责任将会非常大。</p><p>综合考量，这个应用是绝对不可能大肆发布到网上的。个人自用问题还是不大，因为这种调用量对服务器几乎没有什么压力。</p><p>我的初衷也仅仅只是因为作为开发者的我，<strong>降低了我点击开门的频率，免去登记的繁琐。</strong></p><p>在当时我甚至想基于手机的 GPS 定位，来实现靠近小区自动开门。真羡慕当时我的一堆想法，但也遗憾当时没有去尝试实现这一个想法。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="开发">开发<a class="hash-link" href="#开发" title="标题的直接链接">​</a></h3><p>这个应用就大致初衷就说到这了，接下来我要说说开发，这也就是本文说要的重点内容了。下面是我当时的项目结构：</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_7J7PhsdaQy.png" class="img_ev3q"></p><p>不难看出，这是一个前后端分离的项目，其中前端使用 uniapp 来开发一套代码多端运行，并且使用的是 Hbuilder 编辑器来开发。而后端就是常规的 Node 后端服务，使用的是 Express 框架。</p><p>技术栈就介绍完毕，这里我要介绍整个流程。</p><p>就说说获取大门列表和开门的两个接口请求：</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="获取大门列表">获取大门列表<a class="hash-link" href="#获取大门列表" title="标题的直接链接">​</a></h4><p>后端接口：<code>http://localhost:3000/api/list</code></p><p>这个接口主要的作用就是获取原开门 app 的大门列表，这里简单介绍下代码</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">router</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">get</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'/list'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">req</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> res</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> next</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token comment" style="color:rgb(0, 128, 0)">// 模拟请求获取所有大门数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> url </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string string" style="color:rgb(163, 21, 21)">https://xxx.com/api/getDoorList</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> data </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">xxx</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> json </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> axios</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">post</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">url</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">data</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> json </span><span class="token comment" style="color:rgb(0, 128, 0)">// [{...},{...},{...}]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>然后前端请求后，将列表数据渲染到页面上。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="开门请求">开门请求<a class="hash-link" href="#开门请求" title="标题的直接链接">​</a></h4><p>后端接口：<code>http://localhost:3000/api/open</code></p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">router</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">get</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'/open'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">req</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> res</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> next</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> id </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> req</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">query</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token comment" style="color:rgb(0, 128, 0)">// 模拟请求开门</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> url </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string string" style="color:rgb(163, 21, 21)">https://xxx.com/api/openDoorControl</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> data </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">id</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> id</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> json </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> axios</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">post</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">url</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">data</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> json </span><span class="token comment" style="color:rgb(0, 128, 0)">// { "code": 0 ,"msg": "success" }</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>这里的代码也仅仅只是作为演示，实际代码可不止这么简单，因为还需要涉及到登录，加密等等环节。</p><p>我的前端页面访问地址是 http://localhost:5000，我需要 http://localhost:3000/api/list 和 http://localhost:3000/api/openDoor。</p><p>可能有些人会问，为啥要后端服务，不直接在前端向开门 app 的服务器发送请求，然后将响应直接渲染到前端上。比如直接在前端代码中写 openopenDoor 函数</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">async</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">openDoor</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token comment" style="color:rgb(0, 128, 0)">// 模拟请求开门</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> url </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string string" style="color:rgb(163, 21, 21)">https://xxx.com/api/openDoorControl</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> data </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">id</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> id</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> json </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> axios</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">post</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">url</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">data</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> json </span><span class="token comment" style="color:rgb(0, 128, 0)">// { "code": 0 ,"msg": "success" }</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>这个疑惑在我初次想使用 web 端来实现协议复现的时候也考虑过，但浏览器不支持。这也是我下面所要说的</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="同源策略-跨域">同源策略 跨域<a class="hash-link" href="#同源策略-跨域" title="标题的直接链接">​</a></h3><p>一般用户的浏览器是有非常强的页面安全策略的，这里要说的就是同源策略，更细分点就是跨域，比如说 kuizuo.cn 这个站点，想要向 baidu.com 发送请求，请求是能够正常发送过去的，但是 kuizuo.cn 这个站点是接收不到任何数据。因为 kuizuo.cn 和 baidu.com 根本不是同一个网址，专业点说就是不同源，这种不同源的请求在浏览器，称为跨域请求。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_QLEJFPTkb6.png" class="img_ev3q"></p><p>跨域请求如果请求的服务端不允许跨域，即响应协议头没有如下内容</p><div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">access-control-allow-credentials: true</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">access-control-allow-headers: Content-Type, Authorization, X-Requested-With</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">access-control-allow-methods: GET, POST, PUT, DELETE, OPTIONS</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">access-control-allow-origin: *</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>浏览器会直接拒绝接收响应，但浏览器确实将请求发送给了服务端（打开控制台中的网络是看不到该请求的响应结果的）。</p><p>跨域限制只存在于浏览器端，在其他环境下是不存在，请求都是能够发送出去，并且是可以接收到的。所以说为什么不在前端直接向原应用程序的服务器发送请求，罪魁祸首也就是<strong>同源策略</strong>。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="不支持修改协议头">不支持修改协议头<a class="hash-link" href="#不支持修改协议头" title="标题的直接链接">​</a></h3><p>像 origin，reference，user-agents 等协议头是无法修改的</p><div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">origin: https://xxx.com</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">referer: https://xxx.com/api/test</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36 Edg/105.0.1343.42</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>而有些请求是会效验你的设备信息，来源地址，这些内容在浏览器中都写在协议头中，且浏览器不支持修改。使用浏览器来发送数据，无疑就是告诉服务器我是浏览器发送的。服务器判断来源不是自家的域名，那就直接拒绝响应。像防盗链就是检测 referer 。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="方案">方案<a class="hash-link" href="#方案" title="标题的直接链接">​</a></h2><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="桌面端应用开发">桌面端应用开发<a class="hash-link" href="#桌面端应用开发" title="标题的直接链接">​</a></h3><p>正是因为同源策略的限制，导致做协议复现时往往都会选择在本地中直接运行，比如使用易语言，python 等语言，将应用打包成 exe，然后跑在 window 系统上。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_hyjd395YGI.png" class="img_ev3q"></p><p>这样的应用会有以下几点缺陷：</p><ul><li><p><strong>易破解</strong>：由于你的大部分核心逻辑最终都会进行编译打包成 exe，如果会些破解技术，恰好你不做任何防护手段，要破解你的程序非常容易。所以也就为什么很多 exe 程序（尤其是易语言）会带有 .vmp.exe 也就是 vmp 加壳，让程序很难被分析与破解。并且我就可以开启系统抓包，就可以看到应用程序模拟发送的请求数据包是什么。</p></li><li><p><strong>不易跨平台</strong>：大多数的协议复现都是 exe 桌面应用程序，虽然也有安卓，但一般比较少。对于非 windows 用户或者说手头不方便用电脑的用户就很难体验到，并且还要特意安装一个应用，应用程序更新也需要重新安装。</p></li></ul><p>其实我说的这些，也算是绝大部分都是桌面应用程序的一个“通病”，但也不是没有优点，这在后面介绍后端应用开发的会做一个比较。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="后端应用开发">后端应用开发<a class="hash-link" href="#后端应用开发" title="标题的直接链接">​</a></h3><p>另一种方式就是我自行搭建一个后端服务，然后将我要模拟的请求封装成一个接口供外部调用。只要我的这个后端服务允许跨域请求，那么我在浏览器或者在桌面端应用都能调用该接口。这样做调用者根本不可能知到你这个接口返回的数据的核心代码（除非他能渗透你的服务器）。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_pVEHwQk1AJ.png" class="img_ev3q"></p><p>别人像要复现一个相同的协议请求的话，就必须自行抓包分析原站点的数据。而原站点可能做了一定的防护手段，例如验证码 浏览器指纹等风控手段。对于一般人而言，非常难破解。但是假设你能复现该请求的话，又非常不想让别人复现，那么自行搭建一个后端服务封装是最好的手段。而在此基础上，你可以做一些限制，比如接口封装，调用收费等等。</p><p>这里我就不细说太多了，但也不是说没有缺点，甚至可以说这个缺点不比桌面端应用好到哪里：</p><ul><li><p><strong>部署后端服务</strong>：由于搭建了一个后端服务，那么就需要将后端服务部署到服务器上，部署后端服务是小事（但其实也很麻烦，有些写协议复现也不一定会后端开发），但是需要考虑用户的访问量，可能并发量大，那么请求就可能会阻塞导致响应速度变慢。</p></li><li><p><strong>请求限制</strong>：从上流程图也不难看出，由于后端应用是部署在自己的服务器上，同时需要承载多个接口请求，然后模拟的请求都是由<strong>自己后端应用服务器发送</strong>的，这和桌面端应用不同。桌面端模拟的请求发送是用户自己的电脑，即用户自己电脑的 ip 地址，而后端应用服务器是服务器的 ip。一旦发送的请求多了，必然是会限制请求的，说白了就是将 ip 黑了，无法访问。要解决的最有效的办法就是换 ip，使用一些 ip 代理服务商，在请求 xx 服务器的时候使用动态 ip 来请求，检测被黑 ip 之后就换另一个 ip 来请求，但是这样就需要额外支付一些 ip 的费用。</p></li></ul><p>如果你需要<strong>跨平台</strong>（web 端，桌面端，手机端）并且想要<strong>保护好你的模拟请求的代码</strong>，那么就要考虑选择后端应用开发方案。</p><p>像我一开始所介绍的小区开门网页版就是属于这一范围，这里就不再赘述其实现过程了。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="前端应用开发反向代理可行">前端应用开发/反向代理（可行）<a class="hash-link" href="#前端应用开发反向代理可行" title="标题的直接链接">​</a></h3><p>假设你手头已经有了某个网站的大部分协议复现的代码接口，但是<strong>不想搭建一个后端应用，却想要在前端中使用</strong>。有没有解决方案，这也是有的。</p><p>一种就是通过浏览器插件来允许任何请求跨域，或者本地开启 http 响应替换，将允许跨域的协议头加到响应中。但这些手段都需要使用者有一定的开发能力，对于普通用户而言就无能为力。</p><p>目前绝大多数的网站应该都属于前后端分离的形式，后端只提供服务与接口的，提供的接口一般都带有 <code>/api/</code> 或 <code>/v1/</code> 等请求前缀。那么就可以将前端的请求，通过反向代理，转发到原应用服务器。</p><p>反向代理其实也需要服务器，但是和后端应用相比，只需要配置一个 nginx，例如</p><div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">location /api/ {</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">&nbsp; &nbsp; proxy_set_header Host $host;</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">&nbsp; &nbsp; proxy_set_header X-Real-IP $remote_addr;</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">&nbsp; &nbsp; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">&nbsp; &nbsp; proxy_pass http://要转发的服务器域名/api/;</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">&nbsp; &nbsp; index index.html index.htm index.jsp;</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>举个例子，原后端应用通过 <code>http://target.com/api/user/me</code> 来获取目标服务器用户信息，如果我的前端应用 <code>http://example.com</code> 想要请求该接口必然会有跨域限制。但是通过反向代理，我的前端应用可以请求 <code>http://example.com/api/user/methods</code>，nginx 会判断 <code>url</code> 是否为 <code>/api/</code> 前缀，将请求转发给 <code>http://target.com/API</code>。说白了请求 <code>http://example.com/api/user/me</code> 就是在请求 <code>http://target.com/api</code>，同时还不会触发跨域，反向代理也是解决跨域的常用方法之一。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_PO82fF6A5E.png" class="img_ev3q"></p><p>由于请求还是通过服务器发送的，所以后端应用开发有的限制，在反向代理也同样是有的。还有就是对于限制设备请求的服务器，使用这种方案就不行。。。</p><p>同时这种开发方案对于多域名的应用来说可能就不是那么友好，因为就需要配置比较多的反向代理，同时只是将接口转发，接口的定制化就不是那么好。<strong>只不过你可以原封不动的将原有的请求迁移到前端</strong>，假设有了某个网站的大部分协议复现的代码接口，那么这样迁移将会特别方便。</p><div class="theme-admonition theme-admonition-info alert alert--info admonition_LlT9"><div class="admonitionHeading_tbUL"><span class="admonitionIcon_kALy"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>信息</div><div class="admonitionContent_S0QG"><p>提一嘴，如果使用跨平台开发的，如使用前端技术栈去编写桌面端应用（electron），编写安卓，小程序（uniapp，taro）的话，<strong>除了小程序外，其他都没有跨域限制的</strong>（具体还要看相应跨平台技术的限制）。</p></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="方案选择">方案选择<a class="hash-link" href="#方案选择" title="标题的直接链接">​</a></h3><p>最终选择那种开发方式还是取决对应的应用场景，没有绝对的方案，具体考虑哪种方案是需要考虑用户，代码安全，请求量，是否维护来考量了。</p><p>写到这，可能对大多数人而言还是不懂，也很正常，因为这些内容都不算属于传统开发的范畴，甚至可以说是做 hui 产的利。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="ssr框架">SSR框架<a class="hash-link" href="#ssr框架" title="标题的直接链接">​</a></h2><p>我非常希望使用到浏览器的跨平台性，即多端运行，用户的设备只需要有一个浏览器能打开网页就能体验到。（这其实也算是我为什么学 web 开发的初衷了）</p><p>但是在一开始所介绍的小区开门应用中，这样的开发体验其实并不友好。因为我既要编写前端应用还要编写后端服务，相当于两个项目。同时部署应用和传统部署没有特别大的区别，都需要一台服务器，很多时候都是浪费在部署上。</p><p>而 SSR 框架可以算是后端应用开发和前端应用开发结合。能很好的解决上述存在的问题，并且也易于部署，下面我会细细道来。</p><p>这里我选用的 Nuxt3 框架，羊了个羊刷次数网页版就是基于 Nuxt3 框架来开发的，并且使用 vercel 来进行部署。我手头还写过一个项目 <a href="https://github.com/kuizuo/api-service" target="_blank" rel="noopener noreferrer">api-service</a>。</p><p>首先在 SSR 框架，是有对应的后端服务引擎。像 Nuxt3 使用的是 <a href="https://nitro.unjs.io/" target="_blank" rel="noopener noreferrer">Nitro</a>，而 Next.js 使用的是 koa。都提供了后端服务 API 的解决方案，同时这些都是服务都算是 <code>serverless function</code>（无服务函数），所以在编写与调用非常方便。</p><p>此外基于 <a href="https://www.netlify.com/" target="_blank" rel="noopener noreferrer">Netlify</a> 和 <a href="https://vercel.com" target="_blank" rel="noopener noreferrer">Vercel</a> 这些 <code>serverless development</code> 平台，可以非常方便的部署 SSR 框架。同时内置 CI/CD，只需要提交 git commit 就能实现自动构建自动部署。</p><p>最主要是的我恰好使用 Node.js 来做爬虫与api接口，因此后端复现接口也使用 js 来实现。</p><p>为此我特意编写了一个 <a href="/protocol-template">Protocol 协议复现模板</a> ，这里我就不在过多介绍该模板。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="总结">总结<a class="hash-link" href="#总结" title="标题的直接链接">​</a></h2><p>协议复现能写非常多的程序，因为协议复现的大多数案例都是基于已有的应用服务上去实现的，而很多人的日常生活都使用这些已有的服务上。有些已有的服务可能对于一些人而言，体验不好，或者是有其他限制。因此就有人对这些已有的服务来进行“扩展”，来实现自己所定制化的需求。</p><div class="theme-admonition theme-admonition-danger alert alert--danger admonition_LlT9"><div class="admonitionHeading_tbUL"><span class="admonitionIcon_kALy"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"></path></svg></span>危险</div><div class="admonitionContent_S0QG"><p>这里我需要谨言慎行，因为大多数的协议复现所请求的站点都是他人的站点，如果你的程序或人为控制不当，导致他人服务器崩溃，又或者是非法访问本不属于你所该访问的数据。因此很有可能会触发相关的法律，这里我就不细说了。</p></div></div>]]></content:encoded>
            <category>http</category>
            <category>protocol</category>
        </item>
        <item>
            <title><![CDATA[记 Github 学生认证]]></title>
            <link>https://kuizuo.cn/github-student-certification</link>
            <guid>github-student-certification</guid>
            <pubDate>Tue, 06 Sep 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[记录本人 Github 学生认证艰辛过程与经验分享。]]></description>
            <content:encoded><![CDATA[<p><img loading="lazy" src="https://img.kuizuo.cn/github_copilot_ready.jpg" class="img_ev3q"></p><p>我个人是非常讨厌这些认证提交手续的，例如疫情健康报告，请假申请表等等，当然也包括这次 Github 学生认证。</p><p>这也就是我为什么迟迟不认证 Github 学生的原因，其实说白了就是没必要。但就在前段时间 <a href="https://github.com/features/copilot/" target="_blank" rel="noopener noreferrer" title="github copilot">github copilot</a> 不是内测结束了，然后要开始收费了，收费标准 一个月 $10 / 一年 $100。这费用对于我本不富裕的生活雪上加霜。而 coplot 对教育认证有免费资格使用，于是乎就有了此次较为艰辛的 github 学生认证。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="开始认证">开始认证<a class="hash-link" href="#开始认证" title="标题的直接链接">​</a></h2><p>介绍完故事背景后，就要开始认证了。</p><p>能看到这篇的估计也是想要学生认证的，这里就将我的认证过程总结出来。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="1不要科学上网">1、不要科学上网<a class="hash-link" href="#1不要科学上网" title="标题的直接链接">​</a></h3><p>如果开启科学上网的话，提交时 github 会根据 ip 来判断所提交的学校位置和 ip 地址是否相近，如果差的很远的话是直接认证失败，并提示</p><blockquote><p>You appear not to be near any campus location for the school you have selected. If you are a distance learner then your school-provided academic affiliation documentation must state so.</p></blockquote><p>大致意思：您没有出现在您所选择的学校的任何校园附近。如果你是远程学习者，那么你的学校提供的学术联系文件必须说明这一点。</p><p>也就是这一点，让我放弃我在老家认证学生认证的想法，而到开学才重新认证</p><p>但如果不开启科学上网就有可能获取不了 Google 地图与最终提交，我的做法是修改 host，然后需要 Google 地图的时候开启科学上网，然后获取定位信息后再关闭，最后提交的时候没开启科学上网。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="2学生认证资料">2、学生认证资料<a class="hash-link" href="#2学生认证资料" title="标题的直接链接">​</a></h3><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="教育邮箱">教育邮箱<a class="hash-link" href="#教育邮箱" title="标题的直接链接">​</a></h4><p>有的大学是没有教育邮箱的，就比如我的大学。但不用教育邮箱也是能认证成功的。（当然有的话反而更好通过）</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="学生证">学生证<a class="hash-link" href="#学生证" title="标题的直接链接">​</a></h4><p>学生证学生卡这些都可以作为学生 ID 来认证的，不过在拍学生证之前一定要保证照片清晰，看情况决定时间水印，因为有可能会提示如下信息</p><blockquote><p>Your document does not appear to include a date demonstrating current academic affiliation. For countries utilizing non-standard calendars, you may need to capture the original document beside one with a converted date. You may include multiple documents in your image, so long as they are legible.</p></blockquote><p>大致意思就是提交的资料没有当前时间认证，所以加个时间水印主要是为了这个。</p><p>但不过我有个同学是新号，5 月 github 注册的时候提示要他学生认证，然后他就随手拍了一下学生证的照片提交上去就认证通过了。据他回忆当时认证的信息填的很随意，然后第一次就通过了。而反倒是我提交了好多次学生证都失败了，怎么说呢，可能看账号吧。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="学信网在线验证报告">学信网在线验证报告<a class="hash-link" href="#学信网在线验证报告" title="标题的直接链接">​</a></h4><p>假设你拍照提交学生证一直失败（我就是这样），那么还可以通过 <a href="https://account.chsi.com.cn/passport/login" target="_blank" rel="noopener noreferrer" title="学信网">学信网</a> 的学信档案 <a href="https://my.chsi.com.cn/archive/bab/xj/show.action" target="_blank" rel="noopener noreferrer" title="申请教育部学籍在线验证报告">申请教育部学籍在线验证报告</a></p><p>这个报告默认是中文的，但是 github 不一定认中文的，所以会拒绝。这时候就需要翻译成英文，但是在学信网申请英文在线报告需要额外 30 元，有效期 1 年。当然如果不想花这些钱，就想着是学生认证白嫖的话，也可以使用网页在线翻译，将内容翻译成英文，就得到了一份英文版的在线验证报告。而这个份报告是能通过的，我就是这样操作的。</p><p>每次提交的文件都要求不同，因为 github 后台会对文件做认证，所以就需要多拍照，多截图，做到图片相似，但不相同。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="3修改-github-个人信息">3、修改 github 个人信息<a class="hash-link" href="#3修改-github-个人信息" title="标题的直接链接">​</a></h3><p>如果你按照上面的操作提交了，但还是不通过，并且只有下面一条提示信息的话</p><blockquote><p>You are significantly more likely to be verified if you have completed your <a href="https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-github-profile/customizing-your-profile/personalizing-your-profile" target="_blank" rel="noopener noreferrer" title="GitHub user profile">GitHub user profile</a> with your full name and a short bio.</p></blockquote><p>大致意思是，完善你的 github 个人账号信息（头像，昵称，简介），像我做的就是把昵称改成了我的真实姓名，简介就写我来自什么学校，热爱开源。就差最后大招把头像改成我的自拍照，背景是学校门口。当然 github 还算仁慈，最终还是没让我放出“大招”。</p><p>然后我修改了个人信息，并又提交了几次后，就终于成功了！</p><p>所以只出现了上面的一条提示，那么说明已经快要成功了，只不过 github 还要考核你的坚持程度，看你会不会放弃（我猜的）</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="我的认证过程">我的认证过程<a class="hash-link" href="#我的认证过程" title="标题的直接链接">​</a></h2><p>按照以上的步骤，我将演示一遍我的认证过程。</p><p>1、登录 <a href="https://education.github.com/benefits" target="_blank" rel="noopener noreferrer">github education</a> ，选择学生那个按钮。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20221010134753749.png" alt="image-20221010134753749" class="img_ev3q"></p><p>2、首次表单填写邮箱，学校，以及使用Github的目的。<strong>表单所提交内容全都要使用英文</strong></p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20221010134942952.png" alt="image-20221010134942952" class="img_ev3q"></p><p>3、再次填写一个表单，首先是照片证明，也就是学生认证资料。这里是使用的是<strong>学信网的在线证明英文翻译</strong>，Proof Type 选择 Other (Example: Screenshot of school portal)，备注内容填写证明来源，例如：<strong>这份证明来自中国高等教育学生信息网（学信网），以下是在线证明地址。。。</strong></p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20221010135500357.png" alt="image-20221010135500357" class="img_ev3q"></p><p>其次第二个表单，根据你的学校信息填写即可。<strong>切记到这一步的时候请不要使用科学上课，最好使用学校的网络来提交。</strong></p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20221010135949606.png" alt="image-20221010135949606" class="img_ev3q"></p><p>4、点击Process my application 提交，等待结果即可。</p><p>最终 Github 在今早发送邮箱告知我认证成功了！</p><p><img loading="lazy" src="https://img.kuizuo.cn/github_eduction_success.jpg" class="img_ev3q"></p><p>只要你提供的学生信息真实有效，不断提交最终肯定是会成功的。在这认证期间我一共提交了 11 次请求。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_n3x8Cm8kMv.png" class="img_ev3q"></p><p>期间收到的 Gtihub Education 邮箱信息如下：</p><p><img loading="lazy" src="https://img.kuizuo.cn/github_eduction_eamil.jpg" class="img_ev3q"></p><p>最终也不负众望，在收到 github 通知的时候的，我就立马编写了这篇文章，记录了自己 github 学生认证的过程。</p><p>如果你有幸看到这篇文章，并想要认证 github 学生资格，希望这篇文章有帮到你。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="感谢">感谢<a class="hash-link" href="#感谢" title="标题的直接链接">​</a></h2><p>最终也是要感谢 Github 为广大开发者提供平台，让一群志同道合的人在上面分享并创造想法，同时也感谢这些默默为开源做出贡献的前人，不断为这个世界增添一丝色彩。</p>]]></content:encoded>
            <category>随笔</category>
            <category>github</category>
        </item>
        <item>
            <title><![CDATA[Strapi 实现用户注册与登录]]></title>
            <link>https://kuizuo.cn/strapi-user-register-and-login</link>
            <guid>strapi-user-register-and-login</guid>
            <pubDate>Sat, 03 Sep 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[Strapi 实现用户注册与登录]]></description>
            <content:encoded><![CDATA[<p>在官方博客 <a href="https://strapi.io/blog/registration-and-login-authentication-with-vue-js-and-strapi-1" target="_blank" rel="noopener noreferrer">Registration and Login (Authentication) with Vue.js and Strapi</a> 中演示如何实现注册与登录。实际重点部分是 Strapi 的<a href="https://docs.strapi.io/developer-docs/latest/plugins/users-permissions.html" target="_blank" rel="noopener noreferrer">角色和权限插件</a>，可以说这个插件让开发者不用再为项目考虑的用户登录注册与鉴权相关。</p><p>此外这里有个在线示例可供体验：<a href="https://vitesse-nuxt3-strapi.vercel.app" target="_blank" rel="noopener noreferrer">Vitesse Nuxt 3 Strapi</a></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="创建-strapi-项目">创建 Strapi 项目<a class="hash-link" href="#创建-strapi-项目" title="标题的直接链接">​</a></h2><p>这里省略创建 strapi 项目创建过程，具体可到 <a href="https://docs.strapi.io/developer-docs/latest/getting-started/quick-start.html" target="_blank" rel="noopener noreferrer">Quick Start Guide</a> 中查看。创建完项目，并注册管理员账号后，打开管理面板，根据自己需求创建数据。下面会介绍下管理面板的一些操作（以下针对中文面板）</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="角色列表">角色列表<a class="hash-link" href="#角色列表" title="标题的直接链接">​</a></h3><p>打开 <strong>设置 =&gt; 用户及权限插件 =&gt; 角色列表</strong></p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220825131929320.png" alt="image-20220825131929320" class="img_ev3q"></p><p>默认有两个角色 Authenticated 与 Pubilc，都不可删除，其中还有一个 Admin 是我自己创建的角色，用于分配管理员的权限。</p><p>Authenticated 对应的也就是登录后的角色，即携带 <strong>Authorization</strong> 协议头携带 jwt 的用户。</p><p>另一个 Pubilc 则是未授权用户，默认权限如下</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220825132235027.png" alt="image-20220825132235027" class="img_ev3q"></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="权限分配">权限分配<a class="hash-link" href="#权限分配" title="标题的直接链接">​</a></h3><p>双击角色可以到权限分配页面，比方说我想给 Authenticated 角色分配 Restaurant 表中查询数据，就可以按照如下选项中勾选，并且勾选其中一个权限（增删改查）可以在右侧看到对应的请求 api 接口（路由）</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220825132716257.png" alt="image-20220825132716257" class="img_ev3q"></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="默认角色">默认角色<a class="hash-link" href="#默认角色" title="标题的直接链接">​</a></h3><p>可以在 <strong>设置 =&gt; 用户及权限插件 =&gt; 高级设置</strong> 中分配默认角色，此外这里还可以配置注册，重置密码等操作。对于这些功能而言，传统开发就需要编写相当多的代码了，而 Strapi 的 <a href="https://docs.strapi.io/developer-docs/latest/plugins/users-permissions.html" target="_blank" rel="noopener noreferrer">角色和权限</a> 插件能省去开发这一部分功能的时间。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220825132948740.png" alt="image-20220825132948740" class="img_ev3q"></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="管理员权限">管理员权限<a class="hash-link" href="#管理员权限" title="标题的直接链接">​</a></h3><p>在 <strong>设置 =&gt; 管理员权限</strong> 也可以看到角色列表与用户列表，不过这个只针对登录 strapi 仪表盘的用户，与实际业务的用户毫不相干。通俗点说就是数据库系统的用户与后台管理系统用户的区别。</p><p>一开始登录面板创建的用户在 <strong>设置 =&gt; 管理员权限 =&gt; 用户列表</strong> 中可以看到，而通过api http://localhost:1337/api/auth/local/register 注册的用户则是在 <strong>内容管理 =&gt; User</strong> 中查看。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="使用-http-请求用户操作通用">使用 HTTP 请求用户操作（通用）<a class="hash-link" href="#使用-http-请求用户操作通用" title="标题的直接链接">​</a></h2><p>这里先给出官方提供的注册和登录地址，分别是：</p><p><a href="http://localhost:1337/api/auth/local/register" target="_blank" rel="noopener noreferrer">http://localhost:1337/api/auth/local/register</a></p><p><a href="http://localhost:1337/api/auth/local" target="_blank" rel="noopener noreferrer">http://localhost:1337/api/auth/local</a></p><p>分别可在 <a href="https://docs.strapi.io/developer-docs/latest/plugins/users-permissions.html#login" target="_blank" rel="noopener noreferrer">Login</a> 与 <a href="https://docs.strapi.io/developer-docs/latest/plugins/users-permissions.html#registration" target="_blank" rel="noopener noreferrer">Register</a> 中查看官方演示例子，例如</p><div class="tabs-container tabList__CuJ"><ul role="tablist" aria-orientation="horizontal" class="tabs"><li role="tab" tabindex="0" aria-selected="true" class="tabs__item tabItem_LNqP tabs__item--active">登录</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">注册</li></ul><div class="margin-top--md"><div role="tabpanel" class="tabItem_Ymn6"><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword module" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token imports">axios</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'axios'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// Request API.</span><span class="token plain"></span><br></span><span class="token-line theme-code-block-highlighted-line" style="color:#000000"><span class="token plain">axios</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">post</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'http://localhost:1337/api/auth/local'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">identifier</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'user@strapi.io'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">password</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'strapiPassword'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">then</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">response</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">// Handle success.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'Well done!'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'User profile'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> response</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">user</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'User token'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> response</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">jwt</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">catch</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">// Handle error.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'An error occurred:'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">response</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword module" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token imports">axios</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'axios'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// Request API.</span><span class="token plain"></span><br></span><span class="token-line theme-code-block-highlighted-line" style="color:#000000"><span class="token plain">axios</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">post</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'http://localhost:1337/api/auth/local/register'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">username</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'Strapi user'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">email</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'user@strapi.io'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">password</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'strapiPassword'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">then</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">response</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">// Handle success.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'Well done!'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'User profile'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> response</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">user</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'User token'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> response</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">jwt</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">catch</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">// Handle error.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'An error occurred:'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">response</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></div></div></div><p>除了登录外，还有几个api可能还会用到如获取个人信息，重置密码，修改密码，发送邮箱验证等等。更多可到 <a href="https://docs.strapi.io/developer-docs/latest/plugins/users-permissions.html#authentication" target="_blank" rel="noopener noreferrer">Roles &amp; Permissions</a> 中查看</p><p>通过 HTTP 这种方案可以说是最通用的了，不过有些框架还提供相应的模块来调用 Strapi。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="nuxt">Nuxt<a class="hash-link" href="#nuxt" title="标题的直接链接">​</a></h2><p>官方 Nuxt3 提供了 hooks 方案使用 Strapi。具体可看 <a href="https://strapi.nuxtjs.org/" target="_blank" rel="noopener noreferrer">Nuxt Strapi Module</a>。Nuxt2 可看<a href="https://strapi-v0.nuxtjs.org/hooks" target="_blank" rel="noopener noreferrer">这里</a></p><p>通过相应的 hooks 就可以实现登录注册以及数据增删改查的功能，演示例子可看 <a href="https://strapi.nuxtjs.org/usage" target="_blank" rel="noopener noreferrer">Usage</a></p><p>这里有一份我创建的预设模板 <a href="https://github.com/kuizuo/vitesse-nuxt3-strapi" target="_blank" rel="noopener noreferrer">kuizuo/vitesse-nuxt3-strapi</a>，一开始的示例也是基于这个模板来搭建的。不过目前 Strapi 对 TypeScript 支持不是那么友好，尤其在 window 下会出现无法运行的情况，详看这个 <a href="https://github.com/strapi/strapi/pull/14088" target="_blank" rel="noopener noreferrer">pr</a>。所以目前 backend 使用 js 创建，然后增加 ts 相关支持的，所以有些 ts 支持可能不是那么友好。</p><div class="theme-admonition theme-admonition-note alert alert--secondary admonition_LlT9"><div class="admonitionHeading_tbUL"><span class="admonitionIcon_kALy"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>备注</div><div class="admonitionContent_S0QG"><p>原本我考虑的是使用 starter 方式来创建nuxt3 strapi项目，但是就在我创建完 starter 与 template 准备使用 <code>yarn create strapi-starter strapi-nuxt3 https://github.com/kuizuo/strapi-starter-nuxt3</code> 下载模板时，不出意外又出意外的报错了，由于这个报错也不好排查就暂时放弃了。</p><p>总之又是一趟白折腾的经过。</p></div></div><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="next">Next<a class="hash-link" href="#next" title="标题的直接链接">​</a></h2><p>Next 我暂未找到相关库可以像 Nuxt 提供 Strapi 的服务。不过 Strapi 官方有提供 <a href="https://github.com/strapi/strapi-sdk-javascript" target="_blank" rel="noopener noreferrer">sdk</a>的方案来调用 strapi 服务，而不用发送 http 请求的形式来调用，具体可以到官方提供的 <a href="https://github.com/strapi/strapi-sdk-javascript" target="_blank" rel="noopener noreferrer">sdk</a> 查看如何使用，这里不做演示。有如下两个SDK可供选择：</p><p><a href="https://github.com/strapi/strapi-sdk-javascript" target="_blank" rel="noopener noreferrer">strapi/strapi-sdk-javascript</a> 官网</p><p><a href="https://strapi-sdk-js.netlify.app/" target="_blank" rel="noopener noreferrer">Strapi SDK (strapi-sdk-js.netlify.app)</a> 社区</p>]]></content:encoded>
            <category>strapi</category>
            <category>nuxt</category>
            <category>next</category>
        </item>
        <item>
            <title><![CDATA[pnpm monorepo实践]]></title>
            <link>https://kuizuo.cn/pnpm-monorepo-practice</link>
            <guid>pnpm-monorepo-practice</guid>
            <pubDate>Mon, 29 Aug 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[使用 pnpm monorepo 实践]]></description>
            <content:encoded><![CDATA[<p>老早老早之前就听过 monorepo（单一代码库） 这个名词，也大致了解其出现的意义与功能。但奈何自己的一些小项目中暂时还用不上多项目存储库，所以迟迟没有尝试使用。</p><p>但随着越来越多的开源项目使用 monorepo，现在不实践到时候也肯定是要实践的，这次实践也算是为以后的技能先做个铺垫了。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="介绍">介绍<a class="hash-link" href="#介绍" title="标题的直接链接">​</a></h2><p>前言铺垫这么多，就举个例子介绍下 monorepo 的应用场景，比如现在有个 UI 组件库的开源项目。</p><p>既然是组件库，首先肯定要有组件库的代码吧，此外可能还有脚手架（CLI）或是工具库（utils）或者是插件要作为 npm 包发布，等等。</p><p>如果是传统的开发，每个项目都作为单独的 npm 项目来发布引用，就需要创建多个代码仓库，即<strong>多代码库（multirepos）</strong>。很显然这样在开发以及代码仓库的协同上肯定有弊端，而 monorepo 正是解决这种问题，<strong>将所有的项目在一个代码仓库中，即单一代码库（monorepos）</strong>。</p><p>这只是 monorepo 的一个应用场景例子，这里有一个更好的例子 <a href="https://juejin.cn/post/7043990636751503390" target="_blank" rel="noopener noreferrer">前端工程化：如何使用 monorepo 进行多项目的高效管理</a>，更多可以参考使用 monorepo 的开源项目来了解。在 <a href="https://pnpm.io/zh/workspaces#%E4%BD%BF%E7%94%A8%E7%A4%BA%E4%BE%8B" target="_blank" rel="noopener noreferrer">这里</a> 可查看使用了 pnpm 工作空间功能的最受欢迎的开源项目。</p><p>有篇文章推荐阅读 <a href="https://www.jianshu.com/p/c10d0b8c5581" target="_blank" rel="noopener noreferrer">5 分钟搞懂 Monorepo - 简书 (jianshu.com)</a></p><p>这里还有份手册可供阅读 <a href="https://turborepo.org/docs/handbook/what-is-a-monorepo" target="_blank" rel="noopener noreferrer">What is a Monorepo? | Turborepo</a></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="上手实践">上手实践<a class="hash-link" href="#上手实践" title="标题的直接链接">​</a></h2><p>你可以 clone <a href="https://github.com/kuizuo/monorepo-demo" target="_blank" rel="noopener noreferrer">https://github.com/kuizuo/monorepo-demo</a> 来查看本文示例代码仓库</p><p>这里使用 pnpm 的 <a href="https://pnpm.io/zh/workspaces" target="_blank" rel="noopener noreferrer">workspace</a> 来创建 monorepo 代码仓库，此外目前主流的还有 yarn workspace + <a href="https://lerna.js.org/" target="_blank" rel="noopener noreferrer">lerna</a>，<a href="https://nx.dev/" target="_blank" rel="noopener noreferrer">nx</a>，<a href="https://turborepo.org/" target="_blank" rel="noopener noreferrer">turborepo</a>等等。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="项目结构">项目结构<a class="hash-link" href="#项目结构" title="标题的直接链接">​</a></h3><p>pnpm 内置了对单一存储库（也称为多包存储库、多项目存储库或单体存储库）的支持， 你可以创建一个 workspace 以将多个项目合并到一个仓库中。</p><p>pnpm 要使用 monorepo 的话，需要创建 pnpm-workspace.yaml 文件，其内容如下</p><div class="language-YAML codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-YAML codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">packages:</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  - 'packages/*'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>其中 packages 为多项目的存放路径（一般为公共代码），pnpm 将 packages 下的子目录都视为一个项目。此外如果项目还有文档或在线演示的项目（这些不作为核心库），放在 packages 有些许不妥，就可以像下面这样来配置 workspace</p><div class="language-YAML codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-YAML codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">packages:</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  - packages/*</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  - docs</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  - play</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>像一开始所举例的代码仓库的项目结构如下</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">monorepo-demo</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├── package.json</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├── packages</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   ├── components          </span><span class="token comment" style="color:rgb(0, 128, 0)"># 组件库</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   │   ├── index.js</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   │   └── package.json</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   ├── cli                 </span><span class="token comment" style="color:rgb(0, 128, 0)"># CLI</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   │   ├── index.js</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   │   └── package.json</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   ├── plugins             </span><span class="token comment" style="color:rgb(0, 128, 0)"># 插件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   │   ├── index.js</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   │   └── package.json</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   ├── utils               </span><span class="token comment" style="color:rgb(0, 128, 0)"># 工具</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   │   ├── index.js</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   │   └── package.json</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├── docs                    </span><span class="token comment" style="color:rgb(0, 128, 0)"># 文档</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   │   ├── index.js</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   │   └── package.json</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├── play                    </span><span class="token comment" style="color:rgb(0, 128, 0)"># 在线演示</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   │   ├── index.js</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   │   └── package.json</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├── pnpm-lock.yaml</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">└── pnpm-workspace.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>其中 packages 下存放的就是多个项目代码库，假设项目就叫 demo（因为到时候这些包是有可能要发布的，而名字就要保证唯一），那么项目的 package.json 如下演示：</p><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"name"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"@demo/components"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"version"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"1.0.0"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"description"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">""</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"main"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"index.js"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"scripts"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"test"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"echo \"Error: no test specified\" &amp;&amp; exit 1"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"keywords"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"author"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">""</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"type"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"module"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"license"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"ISC"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"dependencies"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"@packages/utils"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"workspace:^1.0.0"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="安装依赖">安装依赖<a class="hash-link" href="#安装依赖" title="标题的直接链接">​</a></h3><p>执行<code>pnpm install</code> 会自动安装所有依赖（包括 packages 下），所以我们肯定不会傻傻 cd 到每个目录下，然后执行<code>pnpm install</code> 来一个个安装依赖。</p><p>假设现在我要为某个项目添加依赖，例如为 utils 模块添加 lodash 的话，按之前可能会 cd 到 utils 目录执行<code>pnpm add loadsh</code> ，其实完全不用，pnpm 提供 <code>--filter</code> 选项来指定包安装依赖，命令如下</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token function" style="color:rgb(0, 0, 255)">pnpm</span><span class="token plain"> --filter </span><span class="token operator" style="color:rgb(0, 0, 0)">&lt;</span><span class="token plain">package_selector</span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">&lt;</span><span class="token plain">command</span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>例如：</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token function" style="color:rgb(0, 0, 255)">pnpm</span><span class="token plain"> -F @demo/utils </span><span class="token function" style="color:rgb(0, 0, 255)">add</span><span class="token plain"> lodash</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><blockquote><p><code>-F</code>等价于<code>--filter</code></p></blockquote><p>假设现在写好了 utils 模块，<code>@demo/components</code>准备使用 utils 模块，可以按照如下操作</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token function" style="color:rgb(0, 0, 255)">pnpm</span><span class="token plain"> -F @demo/components </span><span class="token function" style="color:rgb(0, 0, 255)">add</span><span class="token plain"> @demo/utils@*</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>这个命令表示在<code>@demo/components</code>安装<code>@demo/utils</code>，其中的<code>@*</code>表示默认同步最新版本，省去每次都要同步最新版本的问题。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="启动项目">启动项目<a class="hash-link" href="#启动项目" title="标题的直接链接">​</a></h3><p>使用<strong>node packages/component</strong> （默认执行 index.js 文件）</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token function" style="color:rgb(0, 0, 255)">node</span><span class="token plain"> packages/components</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>更好的选择是编写 npm scripts 就像下面这样：</p><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"scripts"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"test"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"vitest"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"dev"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"pnpm -C play dev"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"docs:dev"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"pnpm run -C docs dev"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"docs:build"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"pnpm run -C docs build"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"docs:serve"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"pnpm run -C docs serve"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>其中<a href="https://pnpm.io/pnpm-cli#-c-path---dir-path" target="_blank" rel="noopener noreferrer"> -C \&lt;path<!-- -->&gt;</a> 表示 在 path 下运行 npm 脚本 而不是在当前工作路径下。例如根目录下执行 <code>npm run docs:dev</code> 便会执行 <code>docs/package.json</code> <code>dev</code>脚本，同理<code>build</code>和<code>serve</code>也是一样。</p><p>此外更多的可能会在根目录下创建 script 脚本，然后编写（编译，发布）脚本。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="turborepo">Turborepo<a class="hash-link" href="#turborepo" title="标题的直接链接">​</a></h2><p>在上面只是介绍了使用 pnpm workspace 来搭建一个 monorepo 的仓库，但很多时候还需要搭配适当的工具来扩展 monorepo， Turborepo 就是其中之一，利用先进的构建技术和思想来加速开发，构建了无需配置复杂的工作。</p><p>这里就不做介绍，这篇 <a href="https://juejin.cn/post/7129267782515949575" target="_blank" rel="noopener noreferrer">🚀Turborepo：发布当月就激增 3.8k Star，这款超神的新兴 Monorepo 方案，你不打算尝试下吗？ - 掘金 (juejin.cn)</a> 就非常值得推荐阅读。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="总结">总结<a class="hash-link" href="#总结" title="标题的直接链接">​</a></h2><p>搭建一个 monorepo 的仓库其实挺简单的，但也并不是什么项目使用 monorepo 就好，想想看，所有项目和依赖都堆积在一起，那么项目启动速度必然不如单项目启动来的快。就比如一个博客项目，就完全不至于将博客细分为文章/评论/搜索等等划分，还不如统一将代码都直接写到 src 目录下。</p><p>可以说当使用 monorepo 作为项目管理时，每个模块就相当于按照一个 npm 包发布的方式创建，而不是像 src/utils 那么随便了，而开源项目大部分都是要作为 npm 包的方式发布的，使用 monorepo 来管理多个项目自然也就再合适不过了。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="相关文章">相关文章<a class="hash-link" href="#相关文章" title="标题的直接链接">​</a></h2><p><a href="https://www.jianshu.com/p/c10d0b8c5581" target="_blank" rel="noopener noreferrer">5 分钟搞懂 Monorepo - 简书 (jianshu.com)</a></p><p><a href="https://juejin.cn/post/7043990636751503390" target="_blank" rel="noopener noreferrer">前端工程化：如何使用 monorepo 进行多项目的高效管理</a></p><p><a href="https://pnpm.io/zh/workspaces" target="_blank" rel="noopener noreferrer">pnpm workspace</a></p><p><a href="https://juejin.cn/post/7129267782515949575" target="_blank" rel="noopener noreferrer">🚀Turborepo：发布当月就激增 3.8k Star，这款超神的新兴 Monorepo 方案，你不打算尝试下吗？ - 掘金 (juejin.cn)</a></p>]]></content:encoded>
            <category>pnpm</category>
            <category>monorepo</category>
        </item>
        <item>
            <title><![CDATA[正被消磨殆尽的耐心]]></title>
            <link>https://kuizuo.cn/patience-wearing-out</link>
            <guid>patience-wearing-out</guid>
            <pubDate>Mon, 15 Aug 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[在以前，我可以花费 4，5 个小时的时间专注于一件事情上，并且丝毫没有不耐烦的意思。而且这种状态能持续个好几天。例如拼个积木，拼个拼图，写个代码等等。专注个半天根本不成问题。]]></description>
            <content:encoded><![CDATA[<p>在以前，我可以花费 4，5 个小时的时间专注于一件事情上，并且丝毫没有不耐烦的意思。而且这种状态能持续个好几天。例如拼个积木，拼个拼图，写个代码等等。专注个半天根本不成问题。</p><p>当然有很大一部分是因为兴趣，要让我做一件乏味的事，别说坚持了，开始可能都成一个问题。但现在的我对很多东西都难以提起兴趣，要是放在以往，都能让我兴奋个数天。可现在，很难。</p><p>不知为何，感觉专注一件事变得特别困难，总沉不下心来。总感觉一切东西不咋那么美好，都很乏味，难以提起内心仅留的一丝兴趣，总感觉自我内心好像变了个特别无趣的人。这也间接导致我的耐心也不在像之前那样，现在的我遇到一些繁琐的事情，比如写报告，办手续，做核酸等等，我都会感到十分厌烦。</p><p>像之前如果有人问我代码相关的问题，即便是我没接触过的知识方面，我都愿意去尝试了解学习为他解答。可现在，问我不知道的东西，我张口就是不知道。就算我知道，我的回复也往往是丢给他一个相关链接，让他自己研究琢磨，仿佛在告诉他我极不耐烦的样子（当然也有可能是这类问题问的太多了）。之前打车哪怕师傅晚个 10 分钟来接送我都能接受，现在 3 分钟我就已经有点坐立不安了。</p><p>对于这种耐心的转变，我自己都认为有点不太思议。我不知道是不是由于之前太过于耐心，然后种种环境下不断磨练中，导致耐心值不断的下降，最终导致在很多事情都感觉不耐烦，难以平静。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="耐心值下降"><strong>耐心值下降</strong><a class="hash-link" href="#耐心值下降" title="标题的直接链接">​</a></h2><p>自我分析了耐心值下降的可能原因：</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="提不起兴趣"><strong>提不起兴趣</strong><a class="hash-link" href="#提不起兴趣" title="标题的直接链接">​</a></h3><p>说到兴趣，这可就不得不提起 5 年级开始就接触<a href="https://baike.baidu.com/item/%E6%89%8B%E9%83%A8%E6%9E%81%E9%99%90%E8%BF%90%E5%8A%A8/2431307" target="_blank" rel="noopener noreferrer">手部极限运动</a>中的转笔，那也算是我第一个对其感兴趣的东西。期间不断在尝试其他的手指极限运动并持续坚持了整整 8 年，直到高考结束便退坑了。至于为何不再坚持下去，有很大原因是因为 QQ 被永久冻结导致一些社交圈失联，再加上当时假期一直在学习编程。可以说没有这些意外，我依旧会坚持我这持续这份爱好，并且会将其爱好当做一个我的吃饭的本事。</p><p>目前仅余的手指极限运动也就只有转手机了。同样的对于游戏也不再有新鲜感去尝试，偶尔还会下载英雄联盟玩上熟悉的英雄回忆当年的高(下)光(饭)时刻（当然游戏方面也和 QQ 冻结连同游戏账号一并冻结有关）。</p><p>在回到目前主业的编程在我接触了进 3 年内，期间踩的无数的坑，做着重复的业务需求，尤其是所感兴趣，但到头来却又不可完成。渐渐地不再有当初以往的热情，不再乐此不疲。即便完成了一个自我认为成就感爆满的事情，也容易在接下来几天的时间内消磨下去。</p><p>当所感兴趣的东西太多，对于新事物就不再容易提起兴趣。</p><p>人的耐心都是被一些自己感兴趣，但是又不可能完成的事，一点一点消磨殆尽的。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="过快的生活节奏"><strong>过快的生活节奏</strong><a class="hash-link" href="#过快的生活节奏" title="标题的直接链接">​</a></h3><p>现在技术发展是真的快，有很多新的突破和发现。生活质量也在不断变好，但这也间接导致生活节奏过快，社会更加内卷。变化太快。现在的生活总让我感觉一天好像什么事情都没干，一从座位起来就已经是第二天的凌晨。前一秒还在想着吃什么晚饭，后一秒就到了吃夜宵的时刻。看视频也不再是原速播放，而是更快的 1.5 倍，甚至 2 倍速。原本可能要 2 个小时完成的东西，硬是被压缩到 1 个小时内完成。</p><p>在这样的快节奏生活工作下，耐心值怎能不下降？又怎能静的下心来去完成任务？</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="走神"><strong>走神</strong><a class="hash-link" href="#走神" title="标题的直接链接">​</a></h3><p>在写代码任务的时候，有时候一个准备实现的功能好像之前实现过，然后去翻看之前的代码，然后就发现写的还不够好，虽然能用，但总归少些什么，于是就开始重构，然后慢慢的就偏离原本的工作流，导致大部分的时间都在重构该功能，而不是在原本的任务。不过这样也确实完善了该部分的代码，至少不是一次无意义的重构。</p><p>有时候看到一些推荐类的文章或者视频，可能看到中间有一个之前没遇到过的新鲜玩意，然后就开始打开官网，然后去看相关示例。刷着刷着浏览器网页打开多了，哪里还会在意每个标签页的标题，早都给慢慢的标签挤的只剩 logo 了，这时候我大概率是直接整个浏览器关闭，在打开新窗口，而一开始的所推荐的内容，可能早已忘得一干二净了。</p><p>但这样也确实加深了我中途对这玩意的印象和认知，但却让我也忘了一开始的本意。不过一生中要接触许许多多的新的美食，普通人哪里有精力和时间去一遍遍的尝试，要做的只是将自己能够吃到吃进嘴里，体会其中的美味这就足够了。对于任何新鲜事物的尝试也应如此。（有点扯远了）</p><p>所以久而久之，往往越想专注的时候，越容易被细微的东西吸引注意力。专注不下去了，耐心也随之消磨下去。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="消磨耐心"><strong>消磨耐心</strong><a class="hash-link" href="#消磨耐心" title="标题的直接链接">​</a></h2><p>可能是因为经历太多耐心的过程，耐心在无形之间被不断磨灭，最终在不断消磨下导致原本不厌其烦🙂的样子变的极其厌烦😣。</p><p>在这过程中，耐心也实实在在的告诉我正在成长，也在警示我不该松懈。即便内心再怎么烦躁，所表现的也应心照不宣。</p><p>消磨耐心的过程不妨是在打磨工具，将一个钝器打磨成一个利器。绝大多数人一开始的耐心与容忍程度都是非常高的，但随之不断的经历。而多数人的耐心自然也在不断地下降，往往成长的也就越多。</p><p><strong>慢慢磨练一个人的耐心，才更能考验一个人的心智。</strong></p>]]></content:encoded>
            <category>随笔</category>
            <category>杂谈</category>
            <category>感悟</category>
        </item>
        <item>
            <title><![CDATA[Vite使用WebWorker]]></title>
            <link>https://kuizuo.cn/vite-webworker</link>
            <guid>vite-webworker</guid>
            <pubDate>Tue, 26 Jul 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[准备给我的一个 Vite 项目进行重构，其中一个功能(函数)要花费 JS 主线程大量时间，会导致主线程画面卡死，无法正常点击，直到该功能(函数)执行完毕而言。这样的用户体验非常差，于是就准备使用 WebWorker 对该功能封装。]]></description>
            <content:encoded><![CDATA[<p>准备给我的一个 Vite 项目进行重构，其中一个功能(函数)要花费 JS 主线程大量时间，会导致主线程画面卡死，无法正常点击，直到该功能(函数)执行完毕而言。这样的用户体验非常差，于是就准备使用 WebWorker 对该功能封装。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="webworker-限制">WebWorker 限制<a class="hash-link" href="#webworker-限制" title="标题的直接链接">​</a></h2><p>（1）<strong>同源限制</strong></p><p>分配给 Worker 线程运行的脚本文件，必须与主线程的脚本文件同源。</p><p>（2）<strong>DOM 限制</strong></p><p>Worker 线程所在的全局对象，与主线程不一样，无法读取主线程所在网页的 DOM 对象，也无法使用<code>document</code>、<code>window</code>、<code>parent</code>这些对象。但是，Worker 线程可以<code>navigator</code>对象和<code>location</code>对象。</p><p>（3）<strong>通信联系</strong></p><p>Worker 线程和主线程不在同一个上下文环境，它们不能直接通信，必须通过消息完成。</p><p>（4）<strong>脚本限制</strong></p><p>Worker 线程不能执行<code>alert()</code>方法和<code>confirm()</code>方法，但可以使用 XMLHttpRequest 对象发出 AJAX 请求。</p><p>（5）<strong>文件限制</strong></p><p>Worker 线程无法读取本地文件，即不能打开本机的文件系统（<code>file://</code>），它所加载的脚本，必须来自网络。</p><p>综合以上限制，我所要重构的功能面临以下问题</p><ul><li>一些 window 下的函数，或者主线程下全局数据函数，无法共同</li><li>无法读取本地文件，需要创建网络文件（如 Blob 或 Vite 导入）</li><li>Worker 线程和主线程通信要使用<code>worker.postMessage</code>与<code>self.addEventListener</code>来发送与监听数据。</li></ul><p><strong>所以在考虑使用 Worker 的时候就要考虑这个功能是否值得使用 Worker，能否使用 Worker 实现</strong></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="vite-中使用-webworker">Vite 中使用 WebWorker<a class="hash-link" href="#vite-中使用-webworker" title="标题的直接链接">​</a></h2><p>这里先给出我的最优解，在 Vite 中<a href="https://cn.vitejs.dev/guide/assets.html" target="_blank" rel="noopener noreferrer">静态资源处理 </a>，其中可以<a href="https://cn.vitejs.dev/guide/assets.html#importing-script-as-a-worker" target="_blank" rel="noopener noreferrer">导入脚本作为 Worker</a></p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">main.js</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword module" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token imports maybe-class-name">Worker</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'./test.worker.js?worker'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> worker </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">Worker</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>这个 worker 就是所要的 Worker 对象，接着就可以对象的 postMessage 与 onmessage 来数据通信，如</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">main.js</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">worker</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method-variable function-variable method function property-access" style="color:rgb(0, 0, 255)">onmessage</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">e</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'main.js'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> e</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">worker</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">postMessage</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'hello from main'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">test.worker.js</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">self</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">addEventListener</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token string" style="color:rgb(163, 21, 21)">'message'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">e</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'test.worker.js'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> e</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    self</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">postMessage</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'hello from worker'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>不过 Vite 还有<a href="https://cn.vitejs.dev/guide/features.html#web-workers" target="_blank" rel="noopener noreferrer">其他方式</a>导入 Worker</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> worker </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">Worker</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">URL</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'./worker.js'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">import</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">meta</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">url</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>这种方式相对更加标准，但是如果worker并不是一个js文件，而是ts文件，并且还夹杂一些第三方的包，这种方式是有可能会失败，本人测试是这样的，所以推荐一开始的方式，也就是带有查询后缀的导入。</p><p>在打包的时候将其实所用到引入的依赖合并成一个文件，如果打开开发者工具，可以在源代码面板的右侧线程中看到主线程，以及worker线程。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="参考文章">参考文章<a class="hash-link" href="#参考文章" title="标题的直接链接">​</a></h2><p><a href="https://developer.mozilla.org/zh-CN/docs/Web/API/Web_Workers_API/Using_web_workers" target="_blank" rel="noopener noreferrer">使用 Web Workers - Web API 接口参考 | MDN (mozilla.org)</a></p><p><a href="https://www.ruanyifeng.com/blog/2018/07/web-worker.html" target="_blank" rel="noopener noreferrer">Web Worker 使用教程 - 阮一峰的网络日志 (ruanyifeng.com)</a></p>]]></content:encoded>
            <category>vite</category>
            <category>webworker</category>
        </item>
        <item>
            <title><![CDATA[KZ-API接口服务]]></title>
            <link>https://kuizuo.cn/use-nuxt3-build-api-server</link>
            <guid>use-nuxt3-build-api-server</guid>
            <pubDate>Wed, 20 Jul 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[基于 Nuxt3 的 API 接口服务网站，易于封装，调用，部署。]]></description>
            <content:encoded><![CDATA[<p>挺早之前就想写个 api 接口服务，封装下自己收集的一些 api 接口，以便调用，正好最近在接触 SSR 框架，所以就使用 <a href="https://v3.nuxtjs.org/" target="_blank" rel="noopener noreferrer">Nuxt3</a> 来编写该项目。</p><p>在线地址: <a href="https://api.kuizuo.cn" target="_blank" rel="noopener noreferrer">KZ API</a></p><p>开源地址: <a href="https://github.com/kuizuo/api-service" target="_blank" rel="noopener noreferrer">kuizuo/api-service</a></p><p><img loading="lazy" src="https://img.kuizuo.cn/KZ%20API.png" alt="KZ API" class="img_ev3q"></p><p>如果你已经了解过 Nuxt3 与运行过程，那么可以直接跳转至 <a href="#%E5%AE%9E%E6%88%98">实战</a></p><p><a href="https://v3.nuxtjs.org/getting-started/quick-start#new-project" target="_blank" rel="noopener noreferrer">Quick Start</a></p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">npx nuxi init nuxt3</span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain">app</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>可能会安装不上 会提示 <code>could not fetch remote https://github.com/nuxt/starter</code>，大概率就是本地电脑无法访问 github，这时候科学上网都不一定好使，这里建议尝试更换下网络或设置 host 文件。</p><p>安装完毕后，根据提示安装依赖与启动项目</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220714005704602.png" alt="image-20220714005704602" class="img_ev3q"></p><p>初始的 nuxt3 项目及其简单，甚至没有 page、components、assets 等目录。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220714003726413.png" alt="image-20220714003726413" class="img_ev3q"></p><p>关于 nuxt3 本文不做过多介绍，本文只对部分进行介绍。nuxt 已经发布快 1 年了，相信外面很多相关介绍文章。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="nuxt3-介绍">Nuxt3 介绍<a class="hash-link" href="#nuxt3-介绍" title="标题的直接链接">​</a></h2><p><a href="https://v3.nuxtjs.org/guide/concepts/introduction#why-nuxt" target="_blank" rel="noopener noreferrer">What is Nuxt? </a></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="自动导入">自动导入<a class="hash-link" href="#自动导入" title="标题的直接链接">​</a></h3><p>nuxt.js 与 next.js 极其相像，但 nuxt 却精简许多，这归功于 nuxt 的<a href="https://v3.nuxtjs.org/guide/concepts/auto-imports" target="_blank" rel="noopener noreferrer">自动导入</a>，这可以让你无需导入像 vue 中的 ref 等等函数，导入组件等操作，不过前提是代码文件位置要符合 nuxt 规范。如果你尝试使用过 vite 的一些自动导入插件，其效果是一样的，只不过 nuxt 都已经配置好，开箱即用。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="文件路由">文件路由<a class="hash-link" href="#文件路由" title="标题的直接链接">​</a></h3><p>pages 为 nuxt 中页面所存放的位置，会将 pages 目录下的文件(<code>.vue</code>, <code>.js</code>, <code>.jsx</code>, <code>.ts</code> or <code>.tsx</code>) 与路由映射，像<code>pages/index.vue</code> 映射为 <code>/</code>，然后在 app.vue 中通过<code>&lt;NuxtPage/&gt;</code> 来展示 pages。</p><p>要注意，<strong>pages 下的文件一定要有根节点</strong>，不然在路由切换的时候可能会出现问题（事实上建议所以的 vue 组件都有根节点，虽说 vue3 允许多个根节点，但或多或少存在一定问题）</p><p>至于<a href="https://v3.nuxtjs.org/guide/directory-structure/pages" target="_blank" rel="noopener noreferrer">动态路由与嵌套路由</a>，文档说明的比较详细了，这里就不费口舌了</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="服务引擎">服务引擎<a class="hash-link" href="#服务引擎" title="标题的直接链接">​</a></h3><p>Nuxt3 中的的 api 接口服务引擎使用的是<a href="https://nitro.unjs.io/" target="_blank" rel="noopener noreferrer">⚗️ Nitro</a> 的 JavaScript 服务，使用的是<a href="https://github.com/unjs/h3" target="_blank" rel="noopener noreferrer">h3</a>的 http 框架（相当于 hook 版的 http 框架），不过文档不是特别详细，很多东西都要琢磨。（这个框架是真的相对冷门，之前都未曾听闻过）</p><p>关于 Nuxt3 的服务具体可以看 <a href="https://v3.nuxtjs.org/guide/features/server-routes/" target="_blank" rel="noopener noreferrer">Nuxt 3 - Server Routes</a>，这里演示部分代码</p><p>创建一个服务，创建文件<code>server/api/hello.ts</code></p><div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">server/api/helloWord.ts</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">default</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">defineEventHandler</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">event</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'hello nuxt'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>请求 http://localhost/api/hello 便可得到<code>hello nuxt</code>，在 event 可以得到 req 与 res 对象。不过在 req 身上是获取不到 query 和 body 的，这里需要使用 h3 提供的 hooks，如<code>useMethod()</code>,<code>useQuery()</code>,<code>useBody()</code>来获取，例如。</p><div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">default</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">eventHandler</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">event</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> body </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">useBody</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">event</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string string" style="color:rgb(163, 21, 21)">User updated!</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>这与传统的 node 的 http 框架不同点就是 query,body 这些参数不是从函数的上下文(context)取，而是通过 hook 来获取，所以这就是我为什么我说这相当于 hook 版的框架。关于这些 api，可以<a href="https://www.jsdocs.io/package/h3#package-functions" target="_blank" rel="noopener noreferrer">点我查看</a></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="数据获取">数据获取<a class="hash-link" href="#数据获取" title="标题的直接链接">​</a></h3><p>定义完了接口，那必然是要获取数据的，nuxt.js 有四种方式来获取数据，不过主要就二种<code>useFetch</code>与<code>useAsyncData</code>，另外两种是其懒加载形式。</p><p>像上面定义了 helloworld 接口就可以像下面这样使用</p><div class="language-vue codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-vue codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">&lt;script setup&gt;</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">const { data } = await useFetch('/api/hello')</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">console.log(data) // hello nuxt</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">&lt;/script&gt;</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">&lt;template&gt;</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  {{ data }}</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">&lt;/template&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>useAsyncData</p><div class="language-vue codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-vue codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">&lt;script setup&gt;</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">const { data } = await useAsyncData('hello', () =&gt; $fetch('/api/hello'))</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">console.log(data) // hello nuxt</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">&lt;/script&gt;</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">&lt;template&gt;</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  {{ data }}</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">&lt;/template&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>至于 useAsyncData 与 useFetch 有什么区别的话，如果请求的是 url 资源，那么建议使用 useFetch，如果请求的是其他来源的资源，就使用 useAsyncData。可以说在请求 url 资源时，两者是等价的，如下</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token function" style="color:rgb(0, 0, 255)">useFetch</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">url</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">&lt;=</span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">useAsyncData</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">url</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">$fetch</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">url</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>那么如何 SSR(服务端渲染)呢？ <code>nuxt3</code> 默认是全 <code>SSR</code> 的渲染模式，也就是说在上面的数据请求后就是 SSR 渲染，客户端接受到的也就是带有数据页面。</p><p>如果要使用传统的客户端渲染只需要填加一个 options 的 server 参数为 false 即可，如</p><div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> data </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">useFetch</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'/api/hello'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> server</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>自己尝试下将 server 切换，然后打开控制台-&gt;网络中查看 Fetch/XHR 中是否有和数据相关的请求便可知道是在服务端发送的请求数据，还是客户端发送的数据。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="实战">实战<a class="hash-link" href="#实战" title="标题的直接链接">​</a></h2><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="模板">模板<a class="hash-link" href="#模板" title="标题的直接链接">​</a></h3><p>这个项目所使用的模板是 <a href="https://github.com/antfu/vitesse-nuxt3" target="_blank" rel="noopener noreferrer">Vitesse for Nuxt 3</a></p><p><img loading="lazy" src="https://img.kuizuo.cn/vitesse-nuxt3.png" alt="vitesse-nuxt3" class="img_ev3q"></p><p>该模板中集成了一些 vue 生态的相关模块(vueuse, pinia, unocss)，开发者可以不必自行封装这些模块。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="页面设计">页面设计<a class="hash-link" href="#页面设计" title="标题的直接链接">​</a></h3><p>页面设计的话其实没啥好说的，主要使用到了原子类的一个框架<a href="https://github.com/unocss/unocss" target="_blank" rel="noopener noreferrer">unocss</a>。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="接口转发">接口转发<a class="hash-link" href="#接口转发" title="标题的直接链接">​</a></h3><p>这里我会以通过<a href="https://v1.hitokoto.cn/" target="_blank" rel="noopener noreferrer">每日一言</a>的 api 例子来给你演示其功能实现，请求该 api 可以得到</p><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">5233</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"uuid"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"9504a2a2-bab7-4c7d-b643-a6642ed5c55e"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"hitokoto"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"人间没有单纯的快乐，快乐总夹带着烦恼和忧虑。"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"type"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"d"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"from"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"杨绛"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"from_who"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"我们仨"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"creator"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"a632079"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"creator_uid"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1044</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"reviewer"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">4756</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"commit_from"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"web"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"created_at"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"1583786494"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"length"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">22</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>这里创建<code>server/api/one.ts</code>文件</p><div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">server/api/one.ts</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">default</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">defineEventHandler</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">event</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> type </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'text'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">useQuery</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">event</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> data </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">fetch</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'https://v1.hitokoto.cn/'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">json</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">type </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'json'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> data</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">else</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    event</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">setHeader</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'Content-Type'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'text/html;charset=utf-8'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">hitokoto</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>这样，这个接口就已经定义完毕了，此时访问 <a href="http://localhost:3000/api/one" target="_blank" rel="noopener noreferrer">/api/one</a> 所得到的就是一句短语。默认状态下返回文本，如需要 json 数据等额外信息，则可添加<code>type=json</code>。例请求<code>/api/one?type=json</code>，得到的完整数据如下</p><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">7173</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"uuid"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"49eff9ca-7145-4c5f-8e62-d3dca63537fa"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"hitokoto"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"即使人生是一场悲剧，也应该笑着把人生演完。"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"type"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"k"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"from"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"查拉图斯特如是说"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"from_who"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"尼采"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"creator"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Kyanite"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"creator_uid"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">8042</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"reviewer"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"commit_from"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"web"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"created_at"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"1614946509"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"length"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">21</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>而这整个过程也就是其实也就是接口转发，将访问 <code>/api/one</code> 的请求转发给目标 url <a href="https://v1.hitokoto.cn/" target="_blank" rel="noopener noreferrer">https://v1.hitokoto.cn/</a> 的过程，然后对其数据进行抽取和封装，最终展示给调用方。</p><p>然而这只是完成了接口的转发，那么接口的文档又该如何实现呢？</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="接口文档">接口文档<a class="hash-link" href="#接口文档" title="标题的直接链接">​</a></h3><p>要存储接口文档的数据，就需要使用 CMS(内容管理系统)或者 Database(数据库)，一开始我原本打算使用<code>strapi</code>来作为 CMS，毕竟没尝试过<code>strapi</code>，而且 SSR 框架也会搭配<code>strapi</code>来使用，不需再自建后端。但就在我刷<a href="https://modules.nuxtjs.org/?category=CMS&amp;version=3.x" target="_blank" rel="noopener noreferrer">官方模块</a>的时候，无意间发现个官方模块 <a href="https://content.nuxtjs.org/" target="_blank" rel="noopener noreferrer">content</a>。简单了解了一下，发现这个模块有点意思，并且能很简单的满足我当下的需求，于是就选择使用它。也可以使用官方提供的<a href="https://codesandbox.io/s/github/nuxt/starter/tree/content" target="_blank" rel="noopener noreferrer">codesandbox</a>来尝试</p><p>不过<code>content</code>能实现的功能比较有限，没有<code>strapi</code>那么丰富，有多有限呢，基本的 CURD 只能实现查，无法增删改（至少官方文档是没有提供相应的函数）。不过<code>content</code>也不用像<code>strapi</code>那样自建一个服务，可以说是贼简洁了。</p><p>这里省略模块的导入的步骤，在根目录下创建 content 目录，目录下的文件可以是<code>markdonw</code>，<code>json</code>，<code>yaml</code>，<code>csv</code>。和 pages 一样，这里的文件都会映射对应的路由，不过这里需要映射的路由前缀是<code>/api/_content/query/</code>。举个例子</p><div class="tabs-container tabList__CuJ"><ul role="tablist" aria-orientation="horizontal" class="tabs"><li role="tab" tabindex="0" aria-selected="true" class="tabs__item tabItem_LNqP tabs__item--active">content/hello.json</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">output</li></ul><div class="margin-top--md"><div role="tabpanel" class="tabItem_Ymn6"><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"title"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Hello Content v2!"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"description"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"The writing experience for Nuxt 3"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"category"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"announcement"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">_path</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'/hello'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">_draft</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">_partial</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">title</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'Hello Content v2!'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">description</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'The writing experience for Nuxt 3'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">category</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'announcement'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">_id</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'content:hello.json'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">_type</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'json'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">_source</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'content'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">_file</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'hello.json'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">_extension</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'json'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></div></div></div><p>访问<code>/api/_content/query/hello</code>所得到的就是 output 的内容。</p><p>这里只演示 json 数据，是因为该项目主要用到 json 数据来渲染，如果是 markdown 的话，还有一些自带的组件 ContentDoc 来展示 markdown 数据。所提供的功能可以说非常适合用于文档类，或者博客类的站点。</p><p>回到该实战本身，来说明实际数据及其如何请求，上面的例子所对应的 api 文档数据如下</p><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"one"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"name"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"一言"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"desc"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"一言指的就是一句话，可以是动漫中的台词，也可以是网络上的各种小段子"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"path"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"/api/one"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"method"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"GET"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"params"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"name"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"type"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"value"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"json"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"type"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"string"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"desc"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"数据格式(text,json,img)"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"required"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"dataType"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"text"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"example"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"/api/one"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>然后这些数据通过 content 提供的<a href="https://content.nuxtjs.org/api/composables/query-content" target="_blank" rel="noopener noreferrer">queryContent()</a>来获取，这里来看其渲染页面<code>pages/apidoc/[id].vue</code>的部分代码</p><div class="language-vue codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">pages/apidoc/[id].vue</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-vue codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">&lt;script setup lang="ts"&gt;</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">const { data } = await useAsyncData(id, () =&gt; queryContent(id).findOne())</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">const { name, desc, params, path, method, returnType, example } = data.value</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">// ...</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">&lt;/script&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>获取到数据，然后渲染到 vue 上，这些就不过多叙述了。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="接口限流">接口限流<a class="hash-link" href="#接口限流" title="标题的直接链接">​</a></h3><p>假设现在上线了这些接口，但是不做任何限制，那么调用方就可以无限次调用获取接口，这对服务器压力来说是十分巨大的，所以就需要对接口进行限流。</p><p>一般要做限流操作都需要涉及到中间件，在 Nuxt 中有<a href="https://v3.nuxtjs.org/guide/directory-structure/middleware" target="_blank" rel="noopener noreferrer">路由中间件</a>，和<a href="https://v3.nuxtjs.org/guide/features/server-routes#server-middleware" target="_blank" rel="noopener noreferrer">服务中间件</a> ，这里由于是要处理后端接口的，所以就需要使用服务中间。</p><p>创建<code>server/middleware/limit.ts</code> 文件</p><div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">server/middleware/limit.ts</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">default</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">defineEventHandler</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">event</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token builtin" style="color:rgb(0, 112, 193)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string string" style="color:rgb(163, 21, 21)">limit</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>这时候，只要是 Fetch 请求都将打印<code>limit</code>，既然请求能拦截到，那限流就简单了（其实并不简单，因为这个 h3 的文档与相关库实在是少的可怜）。</p><p>不过由于没有使用到用户鉴权等功能（在这个项目中也没打算上），所以限流的操作只有从 IP 的手段下手。这里我选用的是<a href="https://github.com/animir/node-rate-limiter-flexible" target="_blank" rel="noopener noreferrer">node-rate-limiter-flexible</a>这个库，下面是实现代码</p><div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">server/middleware/limit.ts</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> RLWrapperBlackAndWhite</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> RateLimiterMemory </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'rate-limiter-flexible'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> rateLimiter </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">RLWrapperBlackAndWhite</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  limiter</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">RateLimiterMemory</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    points</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    duration</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">getIP</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">req</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">req</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">headers</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'x-forwarded-for'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">as</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(0, 112, 193)">string</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">||</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">req</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">socket</span><span class="token operator" style="color:rgb(0, 0, 0)">?.</span><span class="token plain">remoteAddress </span><span class="token keyword" style="color:rgb(0, 0, 255)">as</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(0, 112, 193)">string</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">replace</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'::ffff:'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">''</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">default</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">defineEventHandler</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">event</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> req</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> res </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> event</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token regex regex-delimiter">/</span><span class="token regex regex-source language-regex">^\/api\/[A-Za-z0-9].*</span><span class="token regex regex-delimiter">/</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">test</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">req</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">url </span><span class="token operator" style="color:rgb(0, 0, 0)">||</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">''</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> ip </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">getIP</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">req</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">try</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> rateLimiter</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">consume</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">ip</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">statusCode </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">429</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> statusCode</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">429</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> statusMessage</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'请求太快了,请稍后再试'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>自行阅读代码即可，设置的限制是 1 秒内只能请求 1 条接口。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="接口缓存">接口缓存<a class="hash-link" href="#接口缓存" title="标题的直接链接">​</a></h3><p>除了接口限流外，对于实时性不高的接口可以开启缓存，这样可以防止过度调用导致接口匮乏。并且对于重复调用的接口响应速度更快，性能更佳。</p><p>可 nuxt 的中间件好像只能拦截用户端发送的请求数据，而服务端发送的给用户端的数据貌似无法拦截，也就无法在中间件中获取到数据或者处理数据了？</p><p>是的，nuxt 的服务层并不像<a href="https://nestjs.com/" target="_blank" rel="noopener noreferrer">nest</a>有 Middleware(中间件),Guards(守卫),Interceptors(拦截器)，而这里所要拦截的部分也就是 nest 中的 Interceptors。</p><p><img loading="lazy" src="https://docs.nestjs.com/assets/Interceptors_1.png" alt="img" class="img_ev3q"></p><p>不过 nuxt 只提供了中间件，这够实现接口缓存的功能了，不过需要一些“技巧”，关于这个技巧我写过的一篇文章 <a href="/js-function-hook">JS 函数 hook</a> 比较详细的介绍该技巧，这里简单说下。</p><p>假设有个 add 函数，我并不想破坏 add 的参数与内部代码结果，但是我又像在调用 add 函数时，查看传入的参数，以及计算的结果，那该如何做？来看下面代码</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">add</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">a</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> b</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> a </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> b</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> original_add </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> add</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token function-variable function" style="color:rgb(0, 0, 255)">add</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'arguments'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> arguments</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> result </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> original_add</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">apply</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> arguments</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'result'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> result</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> result</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>首先重新定义了与 add 相同作用的函数，名为 original_add，然后将 add 修改，同时修改像成上面的代码。这时尝试调用 add 就可以发现输出了传入的参数及计算后的结果。</p><p>知道了这个修改 add 函数的技巧，要拦截 nuxt 的服务端数据也就不难了。只需要将这里的 add 函数替换成 http 框架的返回函数即可，也就是<code>res.end()</code>。大致逻辑如下</p><div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">server/middleware/cache.ts</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">default</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">defineEventHandler</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">event</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> req</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> res </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> event</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> original_res_end </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">end</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function-variable function" style="color:rgb(0, 0, 255)">end</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token operator" style="color:rgb(0, 0, 0)">...</span><span class="token plain">args</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(0, 112, 193)">any</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">// 这里的args的第一个参数就是 res.end 调用的参数，即返回给客户端的数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token builtin" style="color:rgb(0, 112, 193)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">args</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">// 最后可别忘了调用原始的 res.end，不然客户端一直处于等待状态</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">original_res_end</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">apply</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> args</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>这里所使用到的缓存库是<a href="https://github.com/isaacs/node-lru-cache" target="_blank" rel="noopener noreferrer">lru-cache</a>，其实现代码如下</p><div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">server/middleware/cache.ts</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">type</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> ServerResponse </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'h3'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> defaultContentType </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'h3'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">LRU</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'lru-cache'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> options </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  max</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">500</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  ttl</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1000</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">*</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">60</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">*</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 缓存1min</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  allowStale</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  updateAgeOnGet</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  updateAgeOnHas</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> cache </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name constant" style="color:rgb(129, 31, 63)">LRU</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">options</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">default</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">defineEventHandler</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">event</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">defaultContentType</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">event</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'text/plain; charset=utf-8'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> req</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> res </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> event</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token regex regex-delimiter">/</span><span class="token regex regex-source language-regex">^\/api\/[A-Za-z0-9].*</span><span class="token regex regex-delimiter">/</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">test</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">req</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">url </span><span class="token operator" style="color:rgb(0, 0, 0)">||</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">''</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> key </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> req</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">url</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> cached </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> cache</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">get</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">key</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">cached</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">end</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">cached</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> original_res_end </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">end</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function-variable function" style="color:rgb(0, 0, 255)">end</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token operator" style="color:rgb(0, 0, 0)">...</span><span class="token plain">args</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(0, 112, 193)">any</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> ServerResponse </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> data </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> args</span><span class="token operator" style="color:rgb(0, 0, 0)">?.</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        cache</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">set</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">key</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">original_res_end</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">apply</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> args</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>现在缓存是实现了，但所有的接口都被强行缓存 1 分钟，像有些接口（如随机图片）要是也这样设定，那就失去了这个接口的实时性了（我明明要随机，你却偏偏返回都是同一张图片）。所以就要对不同的接口进行不同的接口缓存处理，这里就可以使用到上下文 context。</p><p>定义接口代码</p><div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">server/api/test.ts</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">default</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">defineEventHandler</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">event</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line theme-code-block-highlighted-line" style="color:#000000"><span class="token plain">  event</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">context</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">cache </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> ttl</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1000</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">*</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">5</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 缓存5s</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token comment" style="color:rgb(0, 128, 0)">// ... 其他代码 ...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>定义缓存代码</p><div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">server/middleware/cache.ts</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)">// ... 其他代码 ...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">context</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">cache</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> options </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> context</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">cache</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    cache</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">set</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">key</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> options</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">else</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    cache</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">set</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">key</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>这样就可以为不同的接口，设置不同的缓存配置。（不过这样还是不够优雅，其实可以上装饰器的，但是想了想这也非 AOP 设计，于是就没尝试了）</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="异常捕获">异常捕获<a class="hash-link" href="#异常捕获" title="标题的直接链接">​</a></h3><p>这个功能主要用途是有些接口可能失效了，就需要捕获这些异常接口信息然后停止或者修改该接口。如果要在每个接口上都定义 try catch，接口数量一多将难以维护，所以需要一个服务端全局异常捕获。</p><p>不过目前 Nuxt3 还不支持捕获服务端的异常，这里是<a href="https://v3.nuxtjs.org/guide/features/error-handling/#errors-during-api-or-nitro-server-lifecycle" target="_blank" rel="noopener noreferrer">官网说明</a>。所以该功能暂时未实现，后续也有可能通过 Test 来测试接口可靠性，而不是全局捕获异常接口。</p><p>不过 Nuxt3 对客户端的错误处理做得比较好，有个<a href="https://v3.nuxtjs.org/examples/app/error-handling#error-handling" target="_blank" rel="noopener noreferrer">演示示例</a>。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="后续功能">后续功能<a class="hash-link" href="#后续功能" title="标题的直接链接">​</a></h3><p>由于 content 模块，以及 Nuxt3 后端服务的一些限制，导致一些功能就暂未实现，后续再考虑引入其他方案来实现</p><ul class="contains-task-list containsTaskList_mC6p"><li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->接口计次</li><li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->接口分类</li><li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->代码示例</li><li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->ip 白名单</li></ul><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="收集接口">收集接口<a class="hash-link" href="#收集接口" title="标题的直接链接">​</a></h3><p>就此整个项目的核心功能就已经实现完毕了，接下来要做的就是收集 api 接口，写 api 文档了。然而这部分也是最头疼的部分，因为在互联网上很难有免费的资源。</p><p>像大部分的 api 接口，如果数据来源不是自己的，名义上“免费”的，那大概率就是有限制，例如一天只能 100 条，1 分钟只能请求几次等等，而且这类接口多半是需要填写一个 app_ey 的参数。而需要登录才能获取，当然，你可以选择加钱来增加限额，那么就不再是免费的了。总之就是各种不方便</p><p>如果真想实现免费无限制，那么数据来源只能在自己身上，至于数据来源如何转化成自己的，懂得都懂好吧。</p><p>所以在本项目仅可能的收集一手文档的资源接口或是自行封装的功能接口，但也会存在一些调用别人封装过的接口，服务端的接口信息可自行在<code>server/api</code>中查看，由于一些接口的安全性而言，线上的部分接口代码并未公布，这很正常，因为我并不想泄露一些关键数据。</p><p>如果接口调用有涉及侵权相关的还请直接联系作者删除。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="部署项目">部署项目<a class="hash-link" href="#部署项目" title="标题的直接链接">​</a></h2><p>本地打包</p><div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">npm run build</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>等待打包完毕，将打包后生成的.output 文件夹放到服务器上（依赖都无需安装，.output 文件里有 node_modules），执行</p><div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">node .output/server/index.mjs</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>即可运行项目，或者也可以使用 pm2，总之和常见的 node 部署没什么差异。</p><p>此外也可部署到云提供商，像 AWS，Netlify，Vercel 等，所支持的<a href="https://v3.nuxtjs.org/guide/deploy/presets#supported-hosting-providers" target="_blank" rel="noopener noreferrer">服务商</a></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="坑点">坑点<a class="hash-link" href="#坑点" title="标题的直接链接">​</a></h2><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="打包失败">打包失败<a class="hash-link" href="#打包失败" title="标题的直接链接">​</a></h3><p>cherrio中的parse5包无法打包至生成环境，提示如下</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token constant" style="color:rgb(129, 31, 63)">WARN</span><span class="token plain">  </span><span class="token maybe-class-name">Could</span><span class="token plain"> not resolve </span><span class="token keyword module" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"parse5/lib/parser/index.js"</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">in</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">~</span><span class="token plain">\</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">pnpm</span><span class="token plain">\hast</span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain">util</span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain">raw@</span><span class="token number" style="color:rgb(9, 134, 88)">7.2</span><span class="token number" style="color:rgb(9, 134, 88)">.1</span><span class="token plain">\node_modules\hast</span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain">util</span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain">raw\lib\index</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">js</span><span class="token plain"> using exports defined </span><span class="token keyword" style="color:rgb(0, 0, 255)">in</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">~</span><span class="token plain">\parse5\</span><span class="token keyword" style="color:rgb(0, 0, 255)">package</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">json</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>我猜测是因为hast-util-raw包和cheerio的parse5冲突，而nuxt服务端的nitro在用rollup打包时没有将两者冲突部分合并，而是选择前者，这就导致生产环境下cheerio无法使用。我尝试搜索没有得到一个很好结果，而我的解决方案是降级cherrio版本至0.22.0，因为这个版本中没有引入parse5。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="版本切换">版本切换<a class="hash-link" href="#版本切换" title="标题的直接链接">​</a></h3><p>在我最终准备上线的时候，发现nuxt又有新版本了，于是我将项目从rc.4升级到rc.6，然后再次测试的时候，发现在动态路由页面切换的时候，无法正常的向后端发送请求，甚至都监听不到路由变化，相当于页面被缓存了。</p><p>其实这也侧面说明了，目前 Nuxt3 的兼容性是比较差的。</p><p>实际上还有一些，不过解决相对比较迅速，就没写上。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="总结">总结<a class="hash-link" href="#总结" title="标题的直接链接">​</a></h2><p>体验了一周的 Nuxt3，整个的开发过程不敢说特别顺利，因为存在一定的兼容和Bug。目前 Nuxt3 的目前还处于 rc 版，实际项目还得考虑上线。不过个人还是非常推荐 Nuxt 这个框架，在代码编写与开发体验上实在是太香了，不出意外后续的 web 项目都会采用 Nuxt3 来构建，期待正式版的发布。</p>]]></content:encoded>
            <category>nuxt</category>
            <category>vite</category>
            <category>vue</category>
            <category>ssr</category>
        </item>
        <item>
            <title><![CDATA[Next.js项目搭建与部署]]></title>
            <link>https://kuizuo.cn/next.js-build-and-deploy</link>
            <guid>next.js-build-and-deploy</guid>
            <pubDate>Wed, 13 Jul 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[官方文档 Getting Started | Next.js (nextjs.org)]]></description>
            <content:encoded><![CDATA[<p>官方文档 <a href="https://nextjs.org/docs/getting-started" target="_blank" rel="noopener noreferrer">Getting Started | Next.js (nextjs.org)</a></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="安装"><a href="https://nextjs.org/docs/getting-started#automatic-setup" target="_blank" rel="noopener noreferrer">安装</a><a class="hash-link" href="#安装" title="标题的直接链接">​</a></h2><div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">npx create-next-app@latest --ts</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"># or</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">yarn create next-app --typescript</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"># or</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">pnpm create next-app --ts</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>运行</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">npm run dev</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>访问 http://localhost:3000</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="项目结构">项目结构<a class="hash-link" href="#项目结构" title="标题的直接链接">​</a></h2><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220712030637300.png" alt="image-20220712030637300" class="img_ev3q"></p><table><thead><tr><th>文件</th><th>内容</th></tr></thead><tbody><tr><td>pages</td><td>页面文件</td></tr><tr><td>pages/api</td><td>api 数据接口</td></tr><tr><td>public</td><td>静态资源文件</td></tr><tr><td>styles</td><td>样式文件</td></tr><tr><td>next-env.d.ts</td><td>确保 typescript 支持</td></tr><tr><td>next.config.ts</td><td>next 配置文件</td></tr></tbody></table><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="路由">路由<a class="hash-link" href="#路由" title="标题的直接链接">​</a></h2><p>nextjs 有一个基于页面概念的文件系统路由器，存放在 pages 下<code>.js</code>, <code>.jsx</code>, <code>.ts</code>, <code>.tsx</code> 文件都将作为组件，即<strong>文件路径 → 页面路由</strong>，例如这里的 index.tsx 映射为 index，<code>pages/about.js</code> 将映射为 <code>/about</code>。</p><p>同时还支持动态路由，创建<code>pages/user/[id].tsx</code>文件，然后访问<code>user/1</code>，<code>user/2</code></p><div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">[id].tsx</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-tsx codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token imports"> useRouter </span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'next/router'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> </span><span class="token function-variable function" style="color:rgb(0, 0, 255)">User</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> router </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">useRouter</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> id </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> router</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">query</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">div</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain-text">User id:</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain-text"> </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">div</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">default</span><span class="token plain"> </span><span class="token maybe-class-name">User</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>此时访问 http://localhost:3000/user/1 便可得到 <code>User ID: 1</code></p><p>在 router 对象下没有 param 属性，都是存放在 query 参数中，例如访问 user/1?username=kuizuo，此时的 query 值为 <code>{username: 'kuizuo', id: '2'}</code></p><div class="theme-admonition theme-admonition-tip alert alert--success admonition_LlT9"><div class="admonitionHeading_tbUL"><span class="admonitionIcon_kALy"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>提示</div><div class="admonitionContent_S0QG"><p>不过这里有个比较有意思的点，如果你在上方代码中使用 console.log 打印 query 的话，在 vscode 中会打印出空对象<code>{}</code>，而在浏览器中会打印一次空对象，一次真实的 query 对象（并且打印两遍）</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220712191356587.png" alt="image-20220712191356587" class="img_ev3q"></p></div></div><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="数据渲染">数据渲染<a class="hash-link" href="#数据渲染" title="标题的直接链接">​</a></h2><p>如果你打开控制台，查看所返回的页面，你会发现响应中只有 User id:，这不就和 react 的 CSR(客户端)渲染没有区别吗，是的，确实是这样。因为上一部分的代码，并且从输出 query 也可以看的出来而不是 SSR(服务端)渲染。首先我要展示一下两者渲染的代码</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="csr-客户端渲染">CSR 客户端渲染<a class="hash-link" href="#csr-客户端渲染" title="标题的直接链接">​</a></h3><div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">[id].tsx</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-tsx codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token imports"> useEffect</span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token imports"> useState </span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'react'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token imports"> useRouter </span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'next/router'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> </span><span class="token function-variable function" style="color:rgb(0, 0, 255)">User</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> router </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">useRouter</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> id </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> router</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">query</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> setData</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">useState</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    username</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">''</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    email</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">''</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">useEffect</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token function" style="color:rgb(0, 0, 255)">fetch</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string string" style="color:rgb(163, 21, 21)">https://jsonplaceholder.typicode.com/users/</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">${</span><span class="token template-string interpolation">id</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">then</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">json</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">then</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token function" style="color:rgb(0, 0, 255)">setData</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">catch</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">err</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">div</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain-text">      </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">p</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain-text">username:</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">username</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain-text"> </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">p</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain-text">      </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">p</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain-text">email:</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">email</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain-text"> </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">p</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain-text">    </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">div</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">default</span><span class="token plain"> </span><span class="token maybe-class-name">User</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>经常写 react 的肯定对上面的代码不陌生，前端向后端发送数据请求，接受到数据后赋值给 data，然后渲染出来。因为请求数据是需要耗时的，所以在页面显示完之后，会停顿一会在显示出数据（主要是我这边没写 loadding），并且由于 id 并不是第一时间获取到的（从上面的 id）。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220712193009186.png" alt="image-20220712193009186" class="img_ev3q"></p><p>从这里来看，客户端渲染不仅要获取页面组件，还要请求数据，最终再通过 js 渲染出来</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="ssr-服务端渲染">SSR 服务端渲染<a class="hash-link" href="#ssr-服务端渲染" title="标题的直接链接">​</a></h3><p>next 中服务端渲染需要用到 getServerSideProps 函数，而后端的数据获取都是在该函数内来获取，并通过 prop 传入给前端组件中，来看实际代码</p><div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">[id].tsx</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-tsx codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> </span><span class="token function-variable function" style="color:rgb(0, 0, 255)">User</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> data </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> data</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(0, 112, 193)">any</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">div</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain-text">      </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">p</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain-text">username:</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">username</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain-text"> </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">p</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain-text">      </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">p</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain-text">email:</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">email</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain-text"> </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">p</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain-text">    </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">div</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">default</span><span class="token plain"> </span><span class="token maybe-class-name">User</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">async</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">getServerSideProps</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">context</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> query</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> id</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(0, 112, 193)">any</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> id </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> context</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">query</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 这里context.param也能获取到id</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> res </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">fetch</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string string" style="color:rgb(163, 21, 21)">https://jsonplaceholder.typicode.com/users/</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">${</span><span class="token template-string interpolation">id</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> data </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">json</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    props</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>如果从页面显示来看，确实没什么区别，但如果打开控制台就能发现诸多不同。</p><p>首先就是请求的页面，是直接包含数据，相当于返回你一个页面，而在客户端渲染则是返回一个组件，需要自己去请求数据来展示。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220712192713634.png" alt="image-20220712192713634" class="img_ev3q"></p><p>同时查看控制台中的 Fetch/XHR 的是看不到请求的数据，因为这些数据并不是由前端发送的,而是由后端发送的（故不受跨域请求的限制）。</p><p>从这就能看出客户端渲染与服务端渲染的的区别了。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="ssg-静态生成">SSG 静态生成<a class="hash-link" href="#ssg-静态生成" title="标题的直接链接">​</a></h3><p>不过还没完，还有一个静态生成，先来看看代码。</p><div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">[id].tsx</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-tsx codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> </span><span class="token function-variable function" style="color:rgb(0, 0, 255)">User</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> data </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> data</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(0, 112, 193)">any</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">div</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain-text">      </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">p</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain-text">username:</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">username</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain-text"> </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">p</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain-text">      </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">p</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain-text">email:</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">email</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain-text"> </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">p</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain-text">    </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">div</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">default</span><span class="token plain"> </span><span class="token maybe-class-name">User</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">async</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">getStaticProps</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">context</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> params</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> id</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(0, 112, 193)">any</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> id </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> context</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">params</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> res </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">fetch</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string string" style="color:rgb(163, 21, 21)">https://jsonplaceholder.typicode.com/users/</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">${</span><span class="token template-string interpolation">id</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> data </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">json</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    props</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">async</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">getStaticPaths</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    paths</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name builtin" style="color:rgb(0, 112, 193)">Array</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">20</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">fill</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">map</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">a</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> i</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> params</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> id</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token known-class-name class-name" style="color:rgb(38, 127, 153)">String</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">i </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    fallback</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'blocking'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>主要是 getServerSideProps 替换成 getStaticProps，同时增加了一个 getStaticPaths 用于生成静态页面的，而上面的 getStaticPaths 表示生成 id 1 到 20 的页面，那假设如果我访问 id 为 21 的 user 呢？由于这里设置<code>fallback: 'blocking'</code>，所以还是会走服务端渲染的那一部分。但如果设置<code>fallback: fasle</code>，访问 user/21 就会提示 404。</p><p>通俗点来说就就是生成一系列静态页面，不需要服务端处理，所以返回的速度更快，其缺点其实也比较明显，数据的任何更改都需要在服务端重新构建，而服务端渲染则是可以动态处理数据，不需要完全重建。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="isr-增量式静态生成">ISR 增量式静态生成<a class="hash-link" href="#isr-增量式静态生成" title="标题的直接链接">​</a></h3><p>不做过多介绍，详看文档 <a href="https://nextjs.org/docs/basic-features/data-fetching/incremental-static-regeneration" target="_blank" rel="noopener noreferrer">Data Fetching: Incremental Static Regeneration | Next.js (nextjs.org)</a></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="api-接口">api 接口<a class="hash-link" href="#api-接口" title="标题的直接链接">​</a></h2><p>上面的数据都是调用 <a href="http://jsonplaceholder.typicode.com/" target="_blank" rel="noopener noreferrer">JSONPlaceholder</a> 所提供的虚拟数据，在 next 中要提供数据接口的话，只需要在 pages/api 下编写即可，生成的路由规则和组件一样。例如 pages/api/hello.ts 映射为 api/hello，浏览器访问<a href="http://localhost:3000/api/hello" target="_blank" rel="noopener noreferrer">http://localhost:3000/api/hello</a> 就可以得到<code>{"name": "John Doe"}</code></p><div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">hello.ts</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-tsx codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">type</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token maybe-class-name">NextApiRequest</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token maybe-class-name">NextApiResponse</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'next'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">type</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">Data</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  name</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(0, 112, 193)">string</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">default</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">handler</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">req</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token maybe-class-name">NextApiRequest</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> res</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token maybe-class-name">NextApiResponse</span><span class="token operator" style="color:rgb(0, 0, 0)">&lt;</span><span class="token maybe-class-name">Data</span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">status</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">200</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">json</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> name</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'John Doe'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>这里的 req、res 就是同大部分 node 后端框架一样，而这里的写法与 serverless 一致（这里应该就是 serverless）。</p><p>上述是 get 请求，那 post 请求呢？无论什么 http 请求方法都将在 handler 处理，通过 req.method 来获取请求方法，要区分的话可以通过如下代码。</p><div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-tsx codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">default</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">handler</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">req</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">req</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">method</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">===</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'POST'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">// Process a POST request</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">else</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">// Handle any other HTTP method</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="写一个简单的-crud">写一个简单的 CRUD<a class="hash-link" href="#写一个简单的-crud" title="标题的直接链接">​</a></h3><p>既然知道了上述的一些作用，不妨来个熟悉的 CRUD。这里以文章 post 为例</p><p>这里数据端使用的时 sqlite，配置不做展示，只展示主要核心功能</p><div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">api/post/index.ts</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">type</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> NextApiRequest</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> NextApiResponse </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'next'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> db </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'../../../lib/db'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">default</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">handler</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">req</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> NextApiRequest</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> res</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> NextApiResponse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">try</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">switch</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">req</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">method</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword" style="color:rgb(0, 0, 255)">case</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'GET'</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        db</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">all</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string string" style="color:rgb(163, 21, 21)">select * from post</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">err</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> rows</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">status</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">200</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">json</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">rows</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword" style="color:rgb(0, 0, 255)">break</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword" style="color:rgb(0, 0, 255)">case</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'POST'</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> title</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> content </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> req</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">body</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        db</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">get</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string string" style="color:rgb(163, 21, 21)">insert into post(title, content) values(?, ?)</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">title</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> content</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">err</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> rows</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">status</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">200</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">json</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">rows</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword" style="color:rgb(0, 0, 255)">break</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">status</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">500</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">end</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">api/post/[id].ts</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">type</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> NextApiRequest</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> NextApiResponse </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'next'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> db </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'../../../lib/db'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">default</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">handler</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">req</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> NextApiRequest</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> res</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> NextApiResponse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> id </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> req</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">query</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> title</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> content </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> req</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">body</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">try</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">switch</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">req</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">method</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword" style="color:rgb(0, 0, 255)">case</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'GET'</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        db</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">get</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string string" style="color:rgb(163, 21, 21)">select * from post where id=$id</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> $id</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> id </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">err</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> rows</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">status</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">200</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">json</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">rows</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword" style="color:rgb(0, 0, 255)">break</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword" style="color:rgb(0, 0, 255)">case</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'Put'</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        db</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">get</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string string" style="color:rgb(163, 21, 21)">update post set title=?,content=? where id=?</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">title</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> content</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">err</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> rows</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">status</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">200</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">json</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">rows</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword" style="color:rgb(0, 0, 255)">case</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'DELETE'</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        db</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">get</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string string" style="color:rgb(163, 21, 21)">delete from post where id=$id</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> $id</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> id </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">err</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> rows</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">status</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">200</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">json</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">rows</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">status</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">500</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">end</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>这里为了符合 RESTFUL 风格，所以 post 下编写了两个文件，这时候请求<a href="http://localhost:3000/api/post/2" target="_blank" rel="noopener noreferrer">http://localhost:3000/api/post</a> 就能获取到所有文章数据，基本的 CRUD 也就实现了。</p><p>这里写 sql 是真滴繁琐，没使用 str 或是 typeorm 主要是不想把这个 demo 搞得太复杂，实际项目还是用上比较好。</p><p>当然这里只是作为后端 api 接口的演示，至于前端的展示与编写就和普通前端开发没啥大的区别。基本后端框架能做的，next 能做后端很多事情，更多的使用还是作为接口转发，中间件等，毕竟 Next 主要的强项还是服务端渲染的能力。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="打包部署">打包部署<a class="hash-link" href="#打包部署" title="标题的直接链接">​</a></h2><p>既然说到部署，那肯定离不开 nextjs 的母公司<a href="https://vercel.com" target="_blank" rel="noopener noreferrer">Vercel</a>了，关于 Vercel 之前也写过相关文章，关于 Vercel 就不过多介绍。</p><p>nextjs 部署到 vercel 实在简单，将项目推送到 github 仓库中，然后在 vercel 中 New Project，接着选择 nextjs 的仓库，点击 Deploy，静等部署即可。关于部署可以看这篇文章 <a href="https://kuizuo.cn/develop/Vercel%E9%83%A8%E7%BD%B2%E4%B8%AA%E4%BA%BA%E5%8D%9A%E5%AE%A2" target="_blank" rel="noopener noreferrer">Vercel 部署个人博客</a></p><p>现在你可以通过访问 <a href="https://kz-next-app-demo.vercel.app/" target="_blank" rel="noopener noreferrer">kz-next-app-demo.vercel.app</a> 来访问该项目，并尝试访问<code>/api/post</code>，<code>user/1</code>来看看。</p><p>只能说不愧是母公司。</p><p>至于其他部署？既然都用 nextjs 了，还考虑自建服务器来部署吗？</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="总结">总结<a class="hash-link" href="#总结" title="标题的直接链接">​</a></h2><p>这次的整体过程比较简单，后续应该会使用 nextjs 编写一个完整的项目（<del>也有可能是 nuxt.js</del>)。</p>]]></content:encoded>
            <category>next</category>
            <category>react</category>
            <category>ssr</category>
            <category>vercel</category>
        </item>
        <item>
            <title><![CDATA[写一个VSCode扩展]]></title>
            <link>https://kuizuo.cn/vscode-extension</link>
            <guid>vscode-extension</guid>
            <pubDate>Mon, 11 Jul 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[编写一个属于个人定制化的 VSCode 扩展，并将其发布到应用商店中]]></description>
            <content:encoded><![CDATA[<p>自从使用过 VSCode 后就再也离不开 VSCode，其轻量的代码编辑器与诸多插件让多数开发者爱不释手。同样我也不例外，一年前的我甚至还特意买本《Visual Studio Code 权威指南》的书籍，来更进一步了解与使用。</p><p>在购买这本书时就想写一个 vscode 插件（扩展），奈何当时事务繁忙加之不知做何功能，就迟迟未能动手。如今有时间了，就顺带体验下 vscode 扩展开发，并记录整个开发过程。</p><p>扩展地址：<a href="https://marketplace.visualstudio.com/items?itemName=kuizuo.vscode-extension-sample" target="_blank" rel="noopener noreferrer" title="VSCode-extension">VSCode-extension</a></p><p>开源地址：<a href="https://github.com/kuizuo/vscode-extension" target="_blank" rel="noopener noreferrer">kuizuo/vscode-extension (github.com)</a></p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220711195038039.png" alt="vscode-extension" class="img_ev3q"></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="vscode-相关">Vscode 相关<a class="hash-link" href="#vscode-相关" title="标题的直接链接">​</a></h2><p><a href="https://marketplace.visualstudio.com/vscode" target="_blank" rel="noopener noreferrer" title="vscode应用商店">vscode 应用商店</a></p><p><a href="https://code.visualstudio.com/api" target="_blank" rel="noopener noreferrer" title="vscode插件官方文档">vscode 插件官方文档</a></p><p><a href="https://github.com/microsoft/vscode-extension-samples" target="_blank" rel="noopener noreferrer" title="vscode 官方插件例子">vscode 官方插件例子</a></p><p>关于 Vscode 及其插件就不过多介绍，相信这篇文章 <a href="https://www.cnblogs.com/liuxianan/p/vscode-plugin-overview.html" target="_blank" rel="noopener noreferrer" title="VSCode插件开发全攻略（一）概览 - 我是小茗同学 - 博客园">VSCode 插件开发全攻略（一）概览 - 我是小茗同学 - 博客园</a>能告诉你 Vscode 插件的作用。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="工具准备">工具准备<a class="hash-link" href="#工具准备" title="标题的直接链接">​</a></h2><div class="theme-admonition theme-admonition-tip alert alert--success admonition_LlT9"><div class="admonitionHeading_tbUL"><span class="admonitionIcon_kALy"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>提示</div><div class="admonitionContent_S0QG"><p><strong>在开发前，建议关闭所有功能性扩展，以防止部分日志输出与调试效率</strong>。</p></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="vscode-插件脚手架">vscode 插件脚手架<a class="hash-link" href="#vscode-插件脚手架" title="标题的直接链接">​</a></h3><p>vscode 提供插件开发的脚手架 <a href="https://github.com/Microsoft/vscode-generator-code" target="_blank" rel="noopener noreferrer" title="vscode-generator-code">vscode-generator-code</a> 来生成项目结构，选择要生成的类型</p><div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-shell codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">? </span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">We</span><span class="token string" style="color:rgb(163, 21, 21)">'re constantly looking for ways to make yo better!</span><br></span><span class="token-line" style="color:#000000"><span class="token string" style="color:rgb(163, 21, 21)">May we anonymously report usage statistics to improve the tool over time?</span><br></span><span class="token-line" style="color:#000000"><span class="token string" style="color:rgb(163, 21, 21)">More info: https://github.com/yeoman/insight &amp; http://yeoman.io</span><br></span><span class="token-line" style="color:#000000"><span class="token string" style="color:rgb(163, 21, 21)">========================================================================== Yes</span><br></span><span class="token-line" style="color:#000000"><span class="token string" style="display:inline-block;color:rgb(163, 21, 21)"></span><br></span><span class="token-line" style="color:#000000"><span class="token string" style="color:rgb(163, 21, 21)">     _-----_     ╭──────────────────────────╮</span><br></span><span class="token-line" style="color:#000000"><span class="token string" style="color:rgb(163, 21, 21)">    |       |    │   Welcome to the Visual  │</span><br></span><span class="token-line" style="color:#000000"><span class="token string" style="color:rgb(163, 21, 21)">    |--(o)--|    │   Studio Code Extension  │</span><br></span><span class="token-line" style="color:#000000"><span class="token string" style="color:rgb(163, 21, 21)">   `---------´   │        generator!        │</span><br></span><span class="token-line" style="color:#000000"><span class="token string" style="color:rgb(163, 21, 21)">    ( _´U`_ )    ╰──────────────────────────╯</span><br></span><span class="token-line" style="color:#000000"><span class="token string" style="color:rgb(163, 21, 21)">    /___A___\   /</span><br></span><span class="token-line" style="color:#000000"><span class="token string" style="color:rgb(163, 21, 21)">     |  ~  |</span><br></span><span class="token-line" style="color:#000000"><span class="token string" style="color:rgb(163, 21, 21)">   __'</span><span class="token plain">.___.'__</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"> ´   </span><span class="token variable" style="color:rgb(9, 134, 88)">`</span><span class="token variable" style="color:rgb(9, 134, 88)">  </span><span class="token variable operator" style="color:rgb(0, 0, 0)">|</span><span class="token variable" style="color:rgb(9, 134, 88)">° ´ Y </span><span class="token variable" style="color:rgb(9, 134, 88)">`</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">? What </span><span class="token builtin class-name" style="color:rgb(38, 127, 153)">type</span><span class="token plain"> of extension </span><span class="token keyword" style="color:rgb(0, 0, 255)">do</span><span class="token plain"> you want to create? </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">Use arrow keys</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token plain"> New Extension </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">TypeScript</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  New Extension </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">JavaScript</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  New Color Theme</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  New Language Support</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  New Code Snippets</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  New Keymap</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  New Extension Pack</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  New Language Pack </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">Localization</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  New Web Extension </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">TypeScript</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  New Notebook Renderer </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">TypeScript</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>根据指示一步步选择，这里省略勾选过程，最终生成的项目结果如下</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_StiMqQrFCi.png" class="img_ev3q"></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="运行-vscode-插件">运行 vscode 插件<a class="hash-link" href="#运行-vscode-插件" title="标题的直接链接">​</a></h3><p>既然创建好了工程，那必然是要运行的。由于我这里选择的 ts ＋ webpack 进行开发（视情况勾选webpack），所以是需要打包，同时脚手架已经生成好了对应.vscode 的设置。只需要按下 F5 即可开始调试，这时会打开一个新的 vscode 窗口，<code>Ctrl+Shift+P</code>打开命令行，输入<code>Hello World</code>，右下角弹出提示框<code>Hello World from kuizuo-plugin!</code></p><div class="theme-admonition theme-admonition-danger alert alert--danger admonition_LlT9"><div class="admonitionHeading_tbUL"><span class="admonitionIcon_kALy"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"></path></svg></span>危险</div><div class="admonitionContent_S0QG"><p>注意: 由于是 webpack 开发，在调用堆栈中可以看到有两个进程，一个是 webpack，另一个是新开的插件窗口的，同时在该调试窗口也能查看调试输出信息。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_Yv4X32qLE5.png" class="img_ev3q"></p><p><strong>切记一定要等到第二个调试进程加载完毕</strong>（时间根据电脑性能而定），再打开命令行输入 Hello World 才会有命令，否则会提示 没有匹配命令。</p></div></div><p>至此，一个 vscode 的开发环境就已经搭建完毕，接下来就是了解项目结构，以及 vscode 插件的 api 了。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="代码解读">代码解读<a class="hash-link" href="#代码解读" title="标题的直接链接">​</a></h3><div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">extension.ts</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">*</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">as</span><span class="token plain"> vscode </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'vscode'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">activate</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">context</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> vscode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">ExtensionContext</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> disposable </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> vscode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">commands</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">registerCommand</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'kuizuo-plugin.helloWorld'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    vscode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">window</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">showInformationMessage</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'Hello World from kuizuo-plugin!'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  context</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">subscriptions</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">push</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">disposable</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">deactivate</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p><code>vscode.commands.registerCommand</code>用于注册命令，<code>kuizuo-plugin.helloWorld</code> 为命令 ID，在后续<code>package.json</code>中要与之匹配。第二个参数为一个回调函数，当触发该命令时，弹出提示框。</p><p>在 package.json 中关注 activationEvents 与 contributes</p><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">package.json</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"activationEvents"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">"onCommand:kuizuo-plugin.helloWorld"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"contributes"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"commands"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"command"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"kuizuo-plugin.helloWorld"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"title"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Hello World"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>activationEvents 激活事件，<code>onCommand:kuizuo-plugin.helloWorld</code>中<code>kuizuo-plugin</code>是插件 ID 要与 extension.ts 中的注册命令匹配，<code>helloWorld</code>则是命令标识，而 onCommand 则是监听的类型，此外还有<code>onView</code>、<code>onUri</code>、<code>onLanguage</code>等等。</p><p>contributes 则是配置那些地方来显示命令，像官方的例子中，就是在 Ctrl + Shift + P 命令行中输入 Hello World 来调用<code>kuizuo-plugin.helloWorld</code> 命令。此外还可以设置按键与菜单</p><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">package.json</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token property">"keybindings"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"command"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"kuizuo-plugin.helloWorld"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"key"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"ctrl+f10"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"mac"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"cmd+f10"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"when"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"editorTextFocus"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"menus"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"editor/context"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token property">"when"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"editorFocus"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token property">"command"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"kuizuo-plugin.helloWorld"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token property">"group"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"navigation"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>设置完毕后，可以按 Ctrl + Alt + O 或者命令行中键入 reload 来重启 vscode</p><div class="theme-admonition theme-admonition-danger alert alert--danger admonition_LlT9"><div class="admonitionHeading_tbUL"><span class="admonitionIcon_kALy"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"></path></svg></span>危险</div><div class="admonitionContent_S0QG"><p>这里也要注意，如果重启后并无生效，请查看 package.json 是否配置正确（多一个逗号都不行），或者尝试重新调试。如果还不行，那么很有可能就是代码报错，但日志输出并没有，那么在弹出的新窗口中打开开发人员工具（Ctrl+Alt+I 或帮助 → 切换开发人员工具），这里有报错相关的提示信息。</p><p>建议查看<a href="https://www.cnblogs.com/liuxianan/p/vscode-plugin-develop-tips.html" target="_blank" rel="noopener noreferrer" title="VSCode插件开发全攻略（六）开发调试技巧">VSCode 插件开发全攻略（六）开发调试技巧</a></p></div></div><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="功能">功能<a class="hash-link" href="#功能" title="标题的直接链接">​</a></h2><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="首次启动弹窗与配置项">首次启动弹窗与配置项<a class="hash-link" href="#首次启动弹窗与配置项" title="标题的直接链接">​</a></h3><p>先说首次启动弹窗的实现，要实现该功能，肯定要保证插件在 VSCode 一打开就运行，而这取决于 vscode 触发插件的时机，也就是 activationEvents，所以<code>activationEvents</code>需要设置成<code>onStartupFinished</code>。想要更高的优先级，可以选择 <code>*</code> （但官方不建议，除非其他事件无法实现的前提下），这里为了演示就使用<code>*</code>。</p><p>其实现代码主要调用 <code>vscode.window.showInformationMessage</code> 函数如下</p><div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">extension.ts</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">*</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">as</span><span class="token plain"> vscode </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'vscode'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> exec </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'child_process'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">activate</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">context</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> vscode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">ExtensionContext</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  vscode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">window</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">showInformationMessage</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'是否要打开愧怍的小站？'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'是'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'否'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'不再提示'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">then</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">result</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">result </span><span class="token operator" style="color:rgb(0, 0, 0)">===</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'是'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token function" style="color:rgb(0, 0, 255)">exec</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string string" style="color:rgb(163, 21, 21)">start 'https://kuizuo.cn'</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">else</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">result </span><span class="token operator" style="color:rgb(0, 0, 0)">===</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'不再提示'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token comment" style="color:rgb(0, 128, 0)">// 其他操作 后文会说</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>此时重启窗口，就会有如下弹窗显示</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_9oqLzZl-wE.png" class="img_ev3q"></p><p>但如果你是 mac 用户的话，你会发现无法打开，其原因是 window 下打开链接的指令是 start，而 mac 则是 open，所以需要区分不同的系统。要区分系统就可以使用 node 中的 os 模块的 platform 方法获取系统，如下（省略部分代码）</p><div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">*</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">as</span><span class="token plain"> os </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'os'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> commandLine </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> os</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">platform</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">===</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'win32'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">?</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string string" style="color:rgb(163, 21, 21)">start https://kuizuo.cn</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string string" style="color:rgb(163, 21, 21)">open https://kuizuo.cn</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token function" style="color:rgb(0, 0, 255)">exec</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">commandLine</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>当然了，当用户选择不再提示的时候，下次再打开 vscode 就别提示了，不然大概率就是卸载插件了。这里就需要设置全局参数了，在 package.json 中 contributes 设置 configuration，具体如下，注意<code>kuizuoPlugin.showTip</code> 为全局参数之一</p><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">package.json</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token property">"contributes"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"configuration"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"title"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"kuizuo-plugin"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"properties"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"kuizuoPlugin.showTip"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"type"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"boolean"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"default"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"description"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"是否在每次启动时显示欢迎提示！"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>该参数可以在设置 → 扩展中找到<code>kuizuo-plugin</code>插件来手动选择，也可以是通过 api 来修改</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_teNrxe9D9O.png" class="img_ev3q"></p><p>然后读取<code>vscode.workspace.getConfiguration().get(key)</code>和设置该参数<code>vscode.workspace.getConfiguration().update(key, value)</code></p><div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">extension.ts</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">async</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">activate</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">context</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> vscode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">ExtensionContext</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> key </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'kuizuoPlugin.showTip'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> showTip </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> vscode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">workspace</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">getConfiguration</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">get</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">key</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">showTip</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> result </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> vscode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">window</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">showInformationMessage</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'是否要打开愧怍的小站？'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'是'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'否'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'不再提示'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">result </span><span class="token operator" style="color:rgb(0, 0, 0)">===</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'是'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> commandLine </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> os</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">platform</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">===</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'win32'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">?</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string string" style="color:rgb(163, 21, 21)">start https://kuizuo.cn</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string string" style="color:rgb(163, 21, 21)">open https://kuizuo.cn</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token function" style="color:rgb(0, 0, 255)">exec</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">commandLine</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">else</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">result </span><span class="token operator" style="color:rgb(0, 0, 0)">===</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'不再提示'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token comment" style="color:rgb(0, 128, 0)">//最后一个参数，为true时表示写入全局配置，为false或不传时则只写入工作区配置</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> vscode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">workspace</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">getConfiguration</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">update</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">key</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>即便是调试状态下，重启也不会影响全局参数。最终封装完整代码查看源码，这里不再做展示了。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="右键资源管理器快捷键新建测试文件">右键资源管理器（快捷键）新建测试文件<a class="hash-link" href="#右键资源管理器快捷键新建测试文件" title="标题的直接链接">​</a></h3><p>我日常开发中写的最多的文件就是 js/ts 了，有时候就会在目录下创建 demo.js 来简单测试编写 js 代码，那么我就要点击资源管理器，然后右键新建文件，输入 demo.js。于是我想的是将该功能<strong>封装成快捷键</strong>的方式，当然右键也有<strong>新建测试文件</strong>这一选项。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_3SRybBGaF1.png" class="img_ev3q"></p><p>功能其实挺鸡肋的，也挺高不了多少效率，这里可以说<strong>为了演示和测试这个功能而实现</strong>。</p><p>总之前面这么多废话相当于铺垫了，具体还是看功能实现吧。</p><p>首先就是注册命令，具体就不解读代码了，其逻辑就是获取调用<code>vscode.window.showQuickPick</code>弹出选择框选择 js 还是 ts 文件（自定义），接着获取到其目录，判断文件是否存在，创建文件等操作。</p><div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">extension.ts</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">*</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">as</span><span class="token plain"> vscode </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'vscode'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">*</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">as</span><span class="token plain"> fs </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'fs'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">async</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">activate</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">context</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> vscode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">ExtensionContext</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> disposable </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> vscode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">commands</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">registerCommand</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'kuizuo-plugin.newFile'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">uri</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> vscode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">Uri</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    vscode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">window</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">showQuickPick</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'js'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'ts'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">then</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">item</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token operator" style="color:rgb(0, 0, 0)">!</span><span class="token plain">uri</span><span class="token operator" style="color:rgb(0, 0, 0)">?.</span><span class="token plain">fsPath</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> filename </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">${</span><span class="token template-string interpolation">uri</span><span class="token template-string interpolation punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token template-string interpolation">fsPath</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token template-string string" style="color:rgb(163, 21, 21)">/demo.</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">${</span><span class="token template-string interpolation">item</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">fs</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">existsSync</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">filename</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        vscode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">window</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">showErrorMessage</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string string" style="color:rgb(163, 21, 21)">文件</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">${</span><span class="token template-string interpolation">filename</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token template-string string" style="color:rgb(163, 21, 21)">已存在</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      fs</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">writeFile</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">filename</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">''</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        vscode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">window</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">showInformationMessage</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string string" style="color:rgb(163, 21, 21)">demo.</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">${</span><span class="token template-string interpolation">item</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token template-string string" style="color:rgb(163, 21, 21)">已创建</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        vscode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">window</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">showTextDocument</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">vscode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">Uri</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">file</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">filename</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          viewColumn</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> vscode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">ViewColumn</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">Two</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 显示在第二个编辑器窗口</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  context</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">subscriptions</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">push</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">disposable</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">deactivate</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>然后再 keybindins 中添加一条</p><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">package.json</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token property">"keybindings"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"command"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"kuizuo-plugin.newFile"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"key"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"shift+alt+n"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>然后就当我实现完功能的时候，我在想<strong>自带的新建文件是不是就是个 command？只是没有绑定快捷键？</strong> 于是我到键盘快捷方式中找到答案</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_nQu3Y8DWSw.png" class="img_ev3q"></p><p>图中的<code>explorer.newFile</code>就是资源管理器右键新建文件的命令，只是没有键绑定。所以我只需要简单的加上<code>shift + alt + n</code>即可实现我一开始想要的快捷键功能，此时再次右键资源管理器新建文件右侧就有对应的快捷键。</p><p>此时的我不知该哭该笑，折腾半天的功能其实只是设置个快捷键的事情。</p><div class="theme-admonition theme-admonition-note alert alert--secondary admonition_LlT9"><div class="admonitionHeading_tbUL"><span class="admonitionIcon_kALy"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>备注</div><div class="admonitionContent_S0QG"><p>这些命令在 vscode 中作为内置命令<a href="https://code.visualstudio.com/api/references/commands" target="_blank" rel="noopener noreferrer" title="Built-in Commands">Built-in Commands</a>。要查看 vscode 所有命令的话，也可以通过<code>vscode.commands.getCommands</code> 来获取所有命令 ID，要在插件中执行也只需要调用<code>vscode.commands.executeCommand(id)</code> </p></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="键盘快捷键光标移动">键盘快捷键（光标移动）<a class="hash-link" href="#键盘快捷键光标移动" title="标题的直接链接">​</a></h3><p>接着我就在想，既然很多 vscode 功能都是命令的形式，那是不是在插件级别就能做键盘映射，而不用让用户在 vscode 设置，很显然是可以的。只需要在 package.json 中 contributes 的 keybindings 中设置，就可以实现组合键来进行光标的移动。下面是我给出的答案</p><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">package.json</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token property">"keybindings"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"command"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"cursorUp"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"key"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"shift+alt+i"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"when"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"textInputFocus"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"command"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"cursorDown"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"key"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"shift+alt+k"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"when"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"textInputFocus"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"command"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"cursorLeft"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"key"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"shift+alt+j"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"when"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"textInputFocus"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"command"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"cursorRight"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"key"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"shift+alt+l"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"when"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"textInputFocus"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"command"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"cursorHome"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"key"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"shift+alt+h"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"when"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"textInputFocus"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"command"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"cursorEnd"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"key"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"shift+alt+;"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"when"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"textInputFocus"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p><img loading="lazy" src="https://img.kuizuo.cn/image_SnnPUABJN5.png" class="img_ev3q"></p><p>仔细看右侧来源就可以知道是没问题的，第一个为我之前设置的，而扩展则是通过上面的方法。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="自定义扩展工作台">自定义扩展工作台<a class="hash-link" href="#自定义扩展工作台" title="标题的直接链接">​</a></h3><p>在 vscode 中有几个地方可以用于扩展，具体可看<a href="https://code.visualstudio.com/api/extension-capabilities/extending-workbench#status-bar-item" target="_blank" rel="noopener noreferrer" title="Extending Workbench | Visual Studio Code Extension API">Extending Workbench | Visual Studio Code Extension API</a></p><p><img loading="lazy" src="https://code.visualstudio.com/assets/api/extension-capabilities/extending-workbench/workbench-contribution.png" class="img_ev3q"></p><ul><li><p>左侧图标（活动栏）：主要有资源管理器、搜索、调试、源代码管理、插件</p></li><li><p>编辑器右上角：代码分栏、code runner 的运行图标</p></li><li><p>底部（状态栏）：git、消息、编码等等</p></li></ul><p>在 contributes 添加 viewsContainers 与 views，注意，views 的属性要与 viewsContainers 的 id 对应。</p><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">package.json</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token property">"viewsContainers"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"activitybar"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"demo"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"title"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"愧怍"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"icon"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"public/lollipop.svg"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token property">"views"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"demo"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"view1"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"name"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"视图1"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"view2"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"name"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"视图2"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>编辑器右上角是在 menus 中设置 editor/title，图标则是对应命令下设置，不然就是显示文字</p><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">package.json</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token property">"commands"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"command"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"kuizuo-plugin.helloWorld"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"title"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Hello World"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"icon"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"light"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"public/lollipop.svg"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"dark"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"public/lollipop.svg"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token property">"menus"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"editor/title"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"when"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"resourceLangId == javascript"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"command"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"kuizuo-plugin.helloWorld"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"group"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"navigation"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>至于底部状态栏，这里借用官方例子<a href="https://github.com/microsoft/vscode-extension-samples/tree/main/statusbar-sample" target="_blank" rel="noopener noreferrer" title="vscode-extension-samples/statusbar-sample at main · microsoft/vscode-extension-samples (github.com)">vscode-extension-samples/statusbar-sample at main · microsoft/vscode-extension-samples (github.com)</a>，最终效果如下</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_yQRsMkT6f5.png" class="img_ev3q"></p><p>那个 🍭 就是所添加的图标，不过并不实际功能，这里只是作为展示。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="自定义颜色图标主题">自定义颜色、图标主题<a class="hash-link" href="#自定义颜色图标主题" title="标题的直接链接">​</a></h3><p>在 vscode 中分别有三部分的主题可以设置</p><table><thead><tr><th>主题</th><th>范围</th><th>推荐</th></tr></thead><tbody><tr><td>文件图标主题</td><td>资源管理器内的文件前的图标</td><td><a href="https://marketplace.visualstudio.com/items?itemName=PKief.material-icon-theme" target="_blank" rel="noopener noreferrer">Material Icon Theme</a></td></tr><tr><td>颜色主题</td><td>代码编辑器以及整体颜色主题</td><td><a href="https://marketplace.visualstudio.com/items?itemName=zhuangtongfa.Material-theme" target="_blank" rel="noopener noreferrer">One Dark Pro</a></td></tr><tr><td>产品图标主题</td><td>左侧的图标</td><td><a href="https://marketplace.visualstudio.com/items?itemName=antfu.icons-carbon" target="_blank" rel="noopener noreferrer">Carbon Product Icons</a></td></tr></tbody></table><p>不过关于主题美化就不做深入研究，上面所推荐的就已经足够好看，个人目前也在使用。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="代码片段">代码片段<a class="hash-link" href="#代码片段" title="标题的直接链接">​</a></h3><p>代码片段，也叫<code>snippets</code>，相信大家都不陌生，就是输入一个很简单的单词然后一回车带出来很多代码。平时大家也可以直接在 vscode 中创建属于自己的<code>snippets</code></p><p>代码片段相对比较简单，这里就简单跳过了</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="xxxlog--consolelogxxx包装">xxx.log → console.log(xxx)包装<a class="hash-link" href="#xxxlog--consolelogxxx包装" title="标题的直接链接">​</a></h3><p>功能描述：在一个变量后使用.log，即可转化为 console.log(变量)的形式就像 <code>xxx.log =&gt; console.log('xxx', xxx)</code> 有点像 idea 中的<code>.sout</code></p><p>这里我把 <a href="https://github.com/jaluik/dot-log" target="_blank" rel="noopener noreferrer">jaluik/dot-log</a> 这个插件的实现逻辑给简化了，这里先给出基本雏形</p><div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">extension.ts</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">*</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">as</span><span class="token plain"> vscode </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'vscode'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">MyCompletionItemProvider</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">implements</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">vscode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">CompletionItemProvider </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">constructor</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token comment" style="color:rgb(0, 128, 0)">// 提供代码提示的候选项</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">public</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">provideCompletionItems</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">document</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> vscode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">TextDocument</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> position</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> vscode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">Position</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> snippetCompletion </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">vscode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">CompletionItem</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'log'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> vscode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">CompletionItemKind</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">Operator</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    snippetCompletion</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">documentation </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">vscode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">MarkdownString</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'quick console.log result'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">snippetCompletion</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token comment" style="color:rgb(0, 128, 0)">// 光标选中当前自动补全item时触发动作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">public</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">resolveCompletionItem</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">item</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> vscode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">CompletionItem</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">null</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">activate</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">context</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> vscode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">ExtensionContext</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> disposable </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> vscode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">languages</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">registerCompletionItemProvider</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'html'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'javascript'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'javascriptreact'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'typescript'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'typescriptreact'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'vue'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">MyCompletionItemProvider</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token string" style="color:rgb(163, 21, 21)">'.'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 注册代码建议提示，只有当按下“.”时才触发</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  context</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">subscriptions</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">push</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">disposable</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>在 vscode 插件中通过<code>vscode.languages.registerCompletionItemProvider</code>提供像补全，代码提示等功能，第一个参数为所支持的语言，第二个参数为提供的服务<code>vscode.CompletionItemProvider</code>
这里只是封装成类的形式，目的是为了保存一些属性，例如光标位置 position，也可以传递对象形式
<code>{ provideCompletionItems, resolveCompletionItem }</code> ，第三个参数则是触发的时机。</p><p><code>provideCompletionItems</code>
需返回一个数组，成员类型为<code>vscode.CompletionItem</code>，可通过<code>new vscode.CompletionItem()</code>来创建。</p><p>当你尝试运行上述代码时，会发现在任何值后面输入<code>.</code>都会有<code>log</code>提示。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_-ZCy88xVyq.png" class="img_ev3q"></p><p>但是点击后只是满足了代码补全的功能，而选择 log 选项后所要执行的操作则是在 <code>resolveCompletionItem</code> 中实现，这里仅仅只是返回一个
null，即只有简单的补全功能，这里对整个过程进行描述（可以自行下个断点调试查看）：。</p><ol><li><p>当输入<code>.</code>时，程序进入到<code>provideCompletionItems</code>
函数内，这里可以获取到当前正在编辑的代码文档（文件名，代码内容）对应第一个参数，以及光标所在位置也就是第二个参数。还有其他参数，但这里用不到。具体可看<a href="https://code.visualstudio.com/api/references/vscode-api#CompletionItemProvider%3CT%3E" target="_blank" rel="noopener noreferrer" title="CompletionItemProvider">CompletionItemProvider</a></p></li><li><p>选择完毕后，便会进入到 resolveCompletionItem 里面，这里可以获取到用户所选的选项内容，然后执行一系列的操作。</p></li></ol><p>要做代码替换的话就需要注册文本编辑命令<code>vscode.commands.registerTextEditorCommand</code> ，内容如下</p><div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">extension.ts</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> commandId </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'kuizuo-plugin.log'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> </span><span class="token function-variable function" style="color:rgb(0, 0, 255)">commandHandler</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">editor</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> vscode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">TextEditor</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> edit</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> vscode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">TextEditorEdit</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> position</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> vscode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">Position</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> lineText </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> editor</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">document</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">lineAt</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">position</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">line</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">text</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token comment" style="color:rgb(0, 128, 0)">// match case name.log etc.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> matchVarReg </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">RegExp</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string string" style="color:rgb(163, 21, 21)">\(\[^\\s\]*\[^\'\"\`\]\).</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">${</span><span class="token template-string interpolation string" style="color:rgb(163, 21, 21)">'log'</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token template-string string" style="color:rgb(163, 21, 21)">$</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token comment" style="color:rgb(0, 128, 0)">// match case 'name'.log etc.  /(['"`])([^'"])\1.log/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> matchStrReg </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">RegExp</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string string" style="color:rgb(163, 21, 21)">\(\[\'\"\`\]\)\(\[^\'\"\`\]*\)\\1\.</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">${</span><span class="token template-string interpolation string" style="color:rgb(163, 21, 21)">'log'</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token template-string string" style="color:rgb(163, 21, 21)">$</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> matchFlag</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'var'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'str'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'var'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> text</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    key</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    quote </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"'"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    insertVal </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">''</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">text</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> key</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> lineText</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">match</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">matchVarReg</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">||</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token operator" style="color:rgb(0, 0, 0)">!</span><span class="token plain">key</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">text</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> quote</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> key</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> lineText</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">match</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">matchStrReg</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">||</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    matchFlag </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'str'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token comment" style="color:rgb(0, 128, 0)">// if matched</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">key</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> index </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> lineText</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">indexOf</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">text</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    edit</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">delete</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">vscode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">Range</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">position</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">with</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">undefined</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> index</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> position</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">with</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">undefined</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> index </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> text</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">length</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">matchFlag </span><span class="token operator" style="color:rgb(0, 0, 0)">===</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'var'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">&amp;&amp;</span><span class="token plain"> key</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">includes</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">"'"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      quote </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'"'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">// format like console.log("xxx", xxx)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">matchFlag </span><span class="token operator" style="color:rgb(0, 0, 0)">===</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'var'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token comment" style="color:rgb(0, 128, 0)">//  only console.log(xxx)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      insertVal </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">${</span><span class="token template-string interpolation string" style="color:rgb(163, 21, 21)">'console.log'</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token template-string string" style="color:rgb(163, 21, 21)">(</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">${</span><span class="token template-string interpolation">key</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token template-string string" style="color:rgb(163, 21, 21)">)</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">// if key is string format like console.log("xxx")</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">matchFlag </span><span class="token operator" style="color:rgb(0, 0, 0)">===</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'str'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      insertVal </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">${</span><span class="token template-string interpolation string" style="color:rgb(163, 21, 21)">'console.log'</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token template-string string" style="color:rgb(163, 21, 21)">(</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">${</span><span class="token template-string interpolation">quote</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">${</span><span class="token template-string interpolation">key</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">${</span><span class="token template-string interpolation">quote</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token template-string string" style="color:rgb(163, 21, 21)">)</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    edit</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">insert</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">position</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">with</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">undefined</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> index</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> insertVal</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(0, 112, 193)">Promise</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">resolve</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">context</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">subscriptions</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">push</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">vscode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">commands</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">registerTextEditorCommand</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">commandId</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> commandHandler</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p><code>registerTextEditorCommand</code>不同于<code>registerCommand</code>，它只针对编辑器的命令，例如可以删除代码中的某个片段，增加代码等等。上面的代码就是为了找到.log
前（包括.log）匹配的代码，进行正则提取，然后调用 edit.delete 删除指定范围，再调用 edit.insert
来插入要替换的代码，以此达到替换的效果。</p><p>命令注册完毕了就需要调用了，也就到了 resolveCompletionItem 的时机</p><div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">extension.ts</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">public</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">resolveCompletionItem</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">item</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> vscode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">CompletionItem</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> label </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> item</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">label</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">position </span><span class="token operator" style="color:rgb(0, 0, 0)">&amp;&amp;</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">typeof</span><span class="token plain"> label </span><span class="token operator" style="color:rgb(0, 0, 0)">===</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'string'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      item</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">command </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        command</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'kuizuo-plugin.log'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        title</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'refactor'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        arguments</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">position</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">translate</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> label</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">length </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 这里可以传递参数给该命令</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> item</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>将命令赋值给 item.command，会自动调用其 command 命令，同时把 arguments 参数传入给 command。最终达到替换的效果。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="position">Position<a class="hash-link" href="#position" title="标题的直接链接">​</a></h4><p>这里要说下 vscode 编辑器中的 Position，了解这个对代码替换、代码定位、代码高亮有很大帮助。</p><p>position 有两个属性<code>line</code>和<code>character</code>，对应的也就是行号和列号（后文以<code>line</code>和<code>character</code>
为称），<strong>*<!-- -->*</strong>和<!-- -->*<strong>*<!-- -->都是从 0 开始算起，而在 vscode 自带的状态栏提示中则是从 1 开始算起</strong>，这两者可别混淆了。</p><p>其中 position 有如下几个方法</p><p><strong>position.translate</strong></p><p>根据当前坐标计算，例如当前 position 的 line 0，character1。<code>position.translate(1, 1)</code> 得到 line
1，character 2，这不会改变远 position，这很好理解。但如果计算后得到的 line 与 character 有一个为负数则直接报错。</p><p><strong>position.with</strong></p><p>从自身创建一个新的 postion 对象</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="range">Range<a class="hash-link" href="#range" title="标题的直接链接">​</a></h4><p>知道了坐标信息，那么就可以获取范围了。可以通过 new vscode.Range() 来截取两个 position 之间的内容，得到的是一个 对象，有
start 与 end 属性，分别是传入的两个 position。</p><p>同样的 Range 和 Postion 方法都一致，这里就不多叙述了，可查看其声明文件。
知道范围就可以通过 editor 来获取范围内的代码或是 edit 来删除代码等操作。</p><p>知道了这些内容，再看上面的代码也不难理解了。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="选中变量并打印-consolelog">选中变量并打印 console.log<a class="hash-link" href="#选中变量并打印-consolelog" title="标题的直接链接">​</a></h3><p>这里在补充一个功能：选中一个变量的时候，按下快捷键在下方添加<code>console.log(变量)</code>，相关插件 <a href="https://marketplace.visualstudio.com/items?itemName=ChakrounAnas.turbo-console-log" target="_blank" rel="noopener noreferrer" title="Turbo Console Log">Turbo Console Log</a></p><p>补：只有编辑器有光标的情况下会传入当前光标属性 position，选中状态下是不会传入 postion
属性，而是要通过<code>editor.selection</code>来获取选中内容，是一个 Selection 对象。</p><div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">extension.ts</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">context</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">subscriptions</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">push</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  vscode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">commands</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">registerTextEditorCommand</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token string" style="color:rgb(163, 21, 21)">'kuizuo-plugin.insertLog'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">editor</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> vscode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">TextEditor</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> edit</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> vscode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">TextEditorEdit</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token comment" style="color:rgb(0, 128, 0)">// 获取选中代码 在其下方插入 console.log(xxx)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> selection</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> selections </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> editor</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token comment" style="color:rgb(0, 128, 0)">// 选中多个代码时</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">selections</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">length </span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token comment" style="color:rgb(0, 128, 0)">// 如果不是当行代码</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token operator" style="color:rgb(0, 0, 0)">!</span><span class="token plain">selection</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">isSingleLine</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> value </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> editor</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">document</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">getText</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">selection</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> insertVal </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">${</span><span class="token template-string interpolation">os</span><span class="token template-string interpolation punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token template-string interpolation constant" style="color:rgb(129, 31, 63)">EOL</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">${</span><span class="token template-string interpolation string" style="color:rgb(163, 21, 21)">'console.log'</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token template-string string" style="color:rgb(163, 21, 21)">('</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">${</span><span class="token template-string interpolation">value</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token template-string string" style="color:rgb(163, 21, 21)">', </span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">${</span><span class="token template-string interpolation">value</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token template-string string" style="color:rgb(163, 21, 21)">)</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      edit</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">insert</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">editor</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">selection</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">end</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> insertVal</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      editor</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">selection </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">vscode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">Selection</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">editor</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">selection</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">end</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> editor</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">selection</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">end</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 重置选中区域</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(0, 112, 193)">Promise</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">resolve</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="悬停提示">悬停提示<a class="hash-link" href="#悬停提示" title="标题的直接链接">​</a></h3><p>这里也一笔带过，具体可看 hover.ts 中的代码。只要在 json 文件中，将鼠标悬停在<code>kuizuo</code>这个词中即可触发，试试看看。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_RUIjdDI90l.png" class="img_ev3q"></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="webview">WebView<a class="hash-link" href="#webview" title="标题的直接链接">​</a></h3><p>使用 webView 可以在 vscode 内显示自定义的网页内容，丰富 vscode 功能，但所消耗的性能是肯定有的，就有可能影响 vscode
的运行速度。官方给出的建议是：</p><ul><li><p>这个功能真的需要放在<code>VSCode</code>中吗？作为单独的应用程序或网站会不会更好呢？</p></li><li><p>webview 是实现这个功能的唯一方法吗？可以使用常规 VS Code API 吗？</p></li><li><p>您的 webview 是否会带来足够的用户价值以证明其高资源成本？</p></li></ul><p>不过这里还只是作为一个演示，点击右上角的 logo 图标便可在 vscode 中打开网页。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_nVO_YmRit4.png" class="img_ev3q"></p><p>不过要注意一点。新开的 webview 的背景是对应主题颜色的背景，如果网站有黑白模式的话，那么可能会导致颜色不对，故这里设置了 webview 的背景为白色。</p><p>至于消息通信就不尝试了。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="发布">发布<a class="hash-link" href="#发布" title="标题的直接链接">​</a></h2><p>大部分常用的 vscode 插件实现就此完毕，实际上有很多 api 还没尝试过，篇幅有限，就不一一列举了，后续若有开发实际作用插件再研究。具体可自行安装尝试一番，既然要让别人安装，这里就需要介绍发布了。</p><p>这里在打包前重构下命令 ID，从 kuizuo-plugin → vscode-extension，同时把 package.json 的 name 改成了 vscode-extension-sample，因为发布的时候这个 id 必须唯一，不能与已有重名，到时候生成的为 kuizuo.vscode-extension-sample。（demo 给取了，不然我也不想起名为 sample）</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="本地打包">本地打包<a class="hash-link" href="#本地打包" title="标题的直接链接">​</a></h3><p>无论是本地打包还是发布到应用市场都需要借助<code>vsce</code>这个工具。</p><p>安装</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token function" style="color:rgb(0, 0, 255)">npm</span><span class="token plain"> i vsce -g</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>打包成<code>vsix</code>文件：</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">vsce package</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><div class="theme-admonition theme-admonition-danger alert alert--danger admonition_LlT9"><div class="admonitionHeading_tbUL"><span class="admonitionIcon_kALy"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"></path></svg></span>危险</div><div class="admonitionContent_S0QG"><p>如果使用pnpm的话，有可能会打包失败，提示：npm ERR! missing: xxxxxx</p></div></div><p>在打包时会提示一些信息，例如修改 README.md ，添加 LICENSE 等等，根据提示来操作即可。</p><p>生成好的 vsix 文件不能直接拖入安装，只能从扩展的右上角选择<code>Install from VSIX</code>安装：</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="发布到应用市场">发布到应用市场<a class="hash-link" href="#发布到应用市场" title="标题的直接链接">​</a></h3><p><strong>1、注册账号获取 token</strong></p><p>因为 Visual Studio Code 使用 <a href="https://azure.microsoft.com/services/devops/" target="_blank" rel="noopener noreferrer">Azure DevOps</a>作为其 Marketplace 服务。所以需要登录一下<a href="https://dev.azure.com/" target="_blank" rel="noopener noreferrer" title="Azure">Azure</a>。登录后，如果之前没用过的话会要求创建一个组织，默认为邮箱前缀，这里如下点击</p><p><img loading="lazy" src="https://img.kuizuo.cn/token1_JNXknLPQyJ.png" class="img_ev3q"></p><p><strong>2、新建一个 token</strong></p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220831152146541.png" alt="image-20220831152146541" class="img_ev3q"></p><p>根据图片选择，注意其中 <code>Organization</code> 选择 <code>All aaccessible organizations</code>，<code>Scopes</code> 选择：<code>Full access</code>，否则登录会失败。生成后会得到一个 token，保存它，当你关闭时便不再显示。</p><p><strong>3、创建一个发布者</strong></p><p>先使用网页版创建发布账号：<a href="https://marketplace.visualstudio.com/manage" target="_blank" rel="noopener noreferrer" title="https://marketplace.visualstudio.com/manage">https://marketplace.visualstudio.com/manage</a>填写一些基本信息，然后在使用</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">vsce login </span><span class="token operator" style="color:rgb(0, 0, 0)">&lt;</span><span class="token plain">publisher name</span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>这里的 <code>publisher name</code> 根据 package.json 中的 <code>publisher</code>，会要求你输入 <code>Personal Access Token</code>，把刚刚创建的 <code>token</code> 的值粘贴过来即可</p><p>提示
<code>The Personal Access Token verification succeeded for the publisher 'kuizuo'.</code>
就说明验证成功</p><p><strong>4、发布应用</strong></p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">vsce publish</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><div class="theme-admonition theme-admonition-warning alert alert--danger admonition_LlT9"><div class="admonitionHeading_tbUL"><span class="admonitionIcon_kALy"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"></path></svg></span>危险</div><div class="admonitionContent_S0QG"><p>这里要保证 package.json 的 name 在插件市场中唯一，否则会提示 The Extension Id already exist in the Marketplace. Please use the different Id。</p></div></div><p>运行完毕后，最终提示<code>Published kuizuo.vscode-extension-sample v1.0.0.</code> 就说明发布完毕，发布和 npm 包一样，都无需审核，但要求包名唯一。</p><p>可以在 <a href="https://marketplace.visualstudio.com/manage/publishers/kuizuo" target="_blank" rel="noopener noreferrer" title="Manage Extensions | Visual Studio Marketplace">Manage Extensions | Visual Studio Marketplace</a> 中管理已发布的插件</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_HssaMdar8f.png" class="img_ev3q"></p><p>这时在 vscode 扩展商店中搜索 <code>vscode-extension-sample</code>就能找到该插件<a href="https://marketplace.visualstudio.com/items?itemName=kuizuo.vscode-extension-sample" target="_blank" rel="noopener noreferrer" title="VSCode-extension">VSCode-extension</a>，也可以通过<code>publisher:"kuizuo"</code>来找到我的所有 vscode 插件。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220711195038039.png" alt="vscode-extension" class="img_ev3q"></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="总结">总结<a class="hash-link" href="#总结" title="标题的直接链接">​</a></h2><p>整个开发过程的体验还是非常不错的，调试和代码提示都做得特别到位。不过有一点体验不好的，是大部分的配置信息都要写在 package.json 中，而在这里就不像 ts 那样有没有很好的代码提示了。不过当你填错命令 id 的时，vscode 还会提示命令 id 不存在，而不是不知道报错点。</p><p>浅浅吐槽下：说真的 vscode 插件开发相关的文章与教程少之又少，有时候一个功能的一个 api 实现只能去查阅文档，而不像 chrome 插件，通过搜索引擎就能很快得出结果，而 vscode 插件往往得到的是推荐...但这也说明 chrome 插件开发的人远多于 vscode 插件，或者说远多于 IDE 插件的开发，也很正常，大部分编程好用的功能，已有大牛实现了对应的插件，多数开发者没有一些特别的需求完全就没必要接触 vscode 插件开发。就如我一年前就想写 vscode 插件，但却迟迟拖到现在，其原因可能就这。</p><p>不过这类应用本就如此，就是不断翻阅文档，阅读前人的代码实现，再结合自身思路以完成最终目标。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="参考文章">参考文章<a class="hash-link" href="#参考文章" title="标题的直接链接">​</a></h2><p><a href="https://www.cnblogs.com/liuxianan/p/vscode-plugin-overview.html" target="_blank" rel="noopener noreferrer" title="VSCode插件开发全攻略（一）概览 - 我是小茗同学 - 博客园 (cnblogs.com)">VSCode 插件开发全攻略（一）概览 - 我是小茗同学 - 博客园 (cnblogs.com)</a></p><p><a href="https://code.visualstudio.com/api" target="_blank" rel="noopener noreferrer">Extension API | Visual Studio Code Extension API</a></p>]]></content:encoded>
            <category>vscode</category>
            <category>plugin</category>
            <category>extension</category>
            <category>develop</category>
        </item>
        <item>
            <title><![CDATA[AutoHotkey键盘映射]]></title>
            <link>https://kuizuo.cn/autohotkey</link>
            <guid>autohotkey</guid>
            <pubDate>Fri, 08 Jul 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[当我使用笔记本的时候，每次移动光标，都要大费周章，同时由于笔记本的缘故，导致键入Home与End都需要搭配Fn功能键来实现。所以我希望在任何情况下（敲代码，写文章）都可以将某些组合键绑定为上下左右键，在代码编辑器上有键盘映射可以设置，但脱离代码编辑器就不起作用了，在window下有个神器 AutoHotkey 可以实现我想要的功能。]]></description>
            <content:encoded><![CDATA[<p>当我使用笔记本的时候，每次移动光标，都要大费周章，同时由于笔记本的缘故，导致键入Home与End都需要搭配Fn功能键来实现。所以我希望在任何情况下（敲代码，写文章）都可以将某些组合键绑定为上下左右键，在代码编辑器上有键盘映射可以设置，但脱离代码编辑器就不起作用了，在window下有个神器 <a href="https://www.autohotkey.com/" target="_blank" rel="noopener noreferrer">AutoHotkey</a> 可以实现我想要的功能。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="安装">安装<a class="hash-link" href="#安装" title="标题的直接链接">​</a></h2><p>打开<a href="https://www.autohotkey.com/" target="_blank" rel="noopener noreferrer">官网</a>，点击Download，安装即可。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="使用">使用<a class="hash-link" href="#使用" title="标题的直接链接">​</a></h2><p>安装完成后，右键新建会AutoHotKey Srcipt后缀为ahk。例如创建demo.ahk，其内容如下</p><div class="language-ahk codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-ahk codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">&lt;+&lt;!I::Send {Up} </span><br></span><span class="token-line" style="color:#000000"><span class="token plain">&lt;+&lt;!K::Send {Down} </span><br></span><span class="token-line" style="color:#000000"><span class="token plain">&lt;+&lt;!J::Send {Left} </span><br></span><span class="token-line" style="color:#000000"><span class="token plain">&lt;+&lt;!L::Send {Right} </span><br></span><span class="token-line" style="color:#000000"><span class="token plain">&lt;+&lt;!H::Send {Home} </span><br></span><span class="token-line" style="color:#000000"><span class="token plain">&lt;+&lt;!;::Send {End} </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>然后保存双击该文件，即可运行autohotkey，此时打开任意文本，键入<kbd>Shift</kbd> + <kbd>Ctrl</kbd> + <!-- -->[HIJKL;]<!-- --> 就可以看到光标上下左右移动。</p><p>这里对上面语法进行讲解</p><table><thead><tr><th>键名</th><th>热键标识</th></tr></thead><tbody><tr><td>Ctrl</td><td>^</td></tr><tr><td>Shift</td><td>+</td></tr><tr><td>Alt</td><td>!</td></tr><tr><td>Win</td><td>#</td></tr></tbody></table><p>如果要针对左右Ctrl或Shfit只需要在前面添加<code>&lt;</code> <code>&gt;</code> 。<code>::</code>则作为映射关系，左边的按键作用于何种指令，而右侧则是左侧按键所对应的指令，这里的指令相对简单，只是发送键盘上下左右的关系，指令还可以实现信息框MsgBox 启动应用等等。具体还有更多键盘与鼠标热键详情可在AutoHotkey Help手册中查看，非常详细，不过是英文。</p><p>具体要映射的快捷键可自行发挥，但要切记不建议与常用快捷键冲突，例如上面为何是IJKL而不是WASD，其原因会导致快捷键冲突。</p><p>此外AutoHotkey不仅能做键盘映射，实现宏定义，一键启动任务也不成问题，篇幅有限，就不做过多演示，有兴趣可自行研究。</p>]]></content:encoded>
            <category>工具</category>
            <category>keyMap</category>
        </item>
        <item>
            <title><![CDATA[浅谈个人学习方式]]></title>
            <link>https://kuizuo.cn/learning-style</link>
            <guid>learning-style</guid>
            <pubDate>Fri, 10 Jun 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[临近考试周，又要开始准备复习，顺带总结下自己平常的学习方式与一些感慨。]]></description>
            <content:encoded><![CDATA[<p>临近考试周，又要开始准备复习，顺带总结下自己平常的学习方式与一些感慨。</p><p>我个人主要的两种学习方式，<strong>主动学习</strong>与<strong>被动学习</strong></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="主动学习-">主动学习 ✍<a class="hash-link" href="#主动学习-" title="标题的直接链接">​</a></h2><p>通常来说，主动学习往往是一件痛苦的事情。就如考试周，平常的课该去在课堂上睡觉，该不去的在宿舍睡觉，到考试周，一学期的课没听，但一想到不复习就有可能面临挂科，或多或少都会复习。考试摆烂，挂科惨淡。</p><p>除了上面是会导致坏结果而去学习，那么还有一种则是与之相反，也就是所需，所感兴趣的去学习。</p><p>例如我想要实现一个酷炫功能，或者是一个需求时，而其中需要的知识点便会去了解与学习。</p><p>对于前者而言，其过程并不舒服，甚至可以说是逼自己学习不喜欢的东西，通常我是不如不学的，即便学了在以后也难以记起，除非不学的结果比较严重（如挂科）。而后者情况便不同，兴趣是最好的老师，甚至都不需要借助外界因素去激励，便能有一个很好的学习成果。</p><p>如果没有兴趣或需求的情况下，那么主动学习一定要定制一系列的目标，如果没有明确的目标，学习将会显得十分迷茫。我有很多时候便是这样，想去主动去学习诸多技术栈，不知从何下手。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="被动学习-">被动学习 📘<a class="hash-link" href="#被动学习-" title="标题的直接链接">​</a></h2><p>其实可以说是利用业余时间学习的一个方式，首先我会想我一天主要做的事情（通常是与学习无关），比如刷各个平台（b 站，抖音）的视频，刷知乎，qq 群闲聊等等，这里只是以我一天的大部分日常举例。</p><p>此事不妨关注一些与学习类的账号，包括但不限于加入一些技术交流群， up 主，公众号，博主等等，当你每次刷这类平台时，系统很自然就会给你推送相关内容，比方说 b 站，我日常会在上面刷一些鬼畜视频，生活娱乐视频，但也会关注一些技术类的账号，在娱乐的同时，还能不经意间刷到一些编程知识（知乎，微信公众号同理），这送上门的知识不香吗？</p><p>再比如 watch 一些开源项目，订阅一些博客文章，定时推送Hacker News周刊等等，在他们发布一些重要内容的时候能及时通知到你。虽然这样每天邮箱时常处于未读状态，但如果打开某一条邮箱查看其中的内容，说不定又是一次不错的收获。</p><p>当然，这样学习肯定有一定弊端。首先所摄取的知识过于笼统，一般都是由别人推荐的，甚至有可能会浪费你人生中的几分钟，因为这些知识点可能你已经掌握了，或者这些知识确实没什么干货。其次所获取到的知识往往是整个知识面的冰上一角，或者是某些新型技术，但想要深入去学习还是得按上面的主动学习。</p><p>被动学习主要的作用能让你在不学习的状态下，还能获取相对应的知识。听起来可能觉得很卷，无时无刻的在学习，但我认为在娱乐中学习往往不会显得像主动学习那般有种疲惫感。</p><p>我在被动学习中就间接了解到许多的前沿的技术栈，以及了解到许多之前没使用过的语言、框架特性，而这些都是直接送上门的知识点，而我要做的只是关注一些账号，订阅一些文章或站点，而不用自己去茫茫知识海洋中去寻求。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="两者的权衡">两者的权衡<a class="hash-link" href="#两者的权衡" title="标题的直接链接">​</a></h2><p>我时常处于这类被动学习状态，因为我对很多技术点都很感兴趣，但又不知道从何下手，而当我刷到我所感兴趣的东西时，我才会开始转为主动学习。之所以会出现这样的学习状态转型，有很大一部分是因为<strong>兴趣感已经没有一开始所学的那么强烈，甚至可以说有些许乏味</strong>。</p><p>在一开始接触时，我是抱着强烈的兴趣感去学的，处于一种非常积极的主动学习状态，当时所获取的知识是无法用现在同等时间所堪比。然而在兴趣感消散，这种状态都为浮云。主动学习的频率减弱，每天都在做着与学习无关的事情，这期间与知识没有任何的往来。</p><p>直到将每天所要做的事情，间接的转为被动学习的方式，至少有在学习，而不是在停步，即便是行走 1 厘米，那也是米。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="总结">总结<a class="hash-link" href="#总结" title="标题的直接链接">​</a></h2><p>最好是对感兴趣的方面学习，这样即有动力去学习，有不会感到厌烦，并且兴趣是能陪伴很久的，也往往能坚持下去。</p><p>无论是任何事情在任何时候下都应该保持的是一种不断坚持的状态，打游戏也好，学习也好。</p><p>一段时间不打游戏，手感生疏，再次接触就没状态。
一段时间不学知识，容易忘记，再次使用就没印象。</p><p>大部分人都是如此，可谁又不希望保持一种不断坚持的状态。毕竟不是每个人都有充裕的个人资源与时间资源，很多时候这些资源并不是由自己分配的，有可能是亲朋好友，也有可能是上司老板，最有可能是生活所迫。。。</p><p><strong>唯愿此生，岁月静好</strong></p>]]></content:encoded>
            <category>随笔</category>
            <category>杂谈</category>
        </item>
        <item>
            <title><![CDATA[Vercel部署Serverless]]></title>
            <link>https://kuizuo.cn/vercel-deploy-serverless</link>
            <guid>vercel-deploy-serverless</guid>
            <pubDate>Thu, 12 May 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[使用 Vercel 部署 serverless 过程记录]]></description>
            <content:encoded><![CDATA[<p>Vercel 除了能部署静态站点外，还能运行 Serverless Functions，也是本次的主题</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="创建接口">创建接口<a class="hash-link" href="#创建接口" title="标题的直接链接">​</a></h2><blockquote><p>To deploy Serverless Functions without any additional configuration, you can put files with extensions matching <a href="https://vercel.com/docs/concepts/functions/supported-languages" target="_blank" rel="noopener noreferrer">supported languages</a> and exported functions in the <code>/api</code> directory at your project's root.</p></blockquote><p>vercel 约定在目录下 api 下创建接口路径，这里创建 api/hello.js 文件，当然也支持 ts 以及 ESmodule 写法</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">api/hello.js</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword module" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">default</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">handler</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">request</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> response</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> name </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> request</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">query</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  response</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">status</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">200</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">send</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string string" style="color:rgb(163, 21, 21)">Hello </span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">${</span><span class="token template-string interpolation">name</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token template-string string" style="color:rgb(163, 21, 21)">!</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>此时通过<code>vc --prod</code>生产环境部署后，在浏览器请求 vercel 提供的二级域名/api/hello?name=vercel 便可得到文本<code>Hello vercel</code>，而其函数写法与 express 类似</p><p>接口信息可以在 Functions 中查看</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220512155341109.png" alt="image-20220512155341109" class="img_ev3q"></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="使用-typescript">使用 typescript<a class="hash-link" href="#使用-typescript" title="标题的直接链接">​</a></h3><p>不过上面是使用 js 写法，vercel 更推荐<a href="https://vercel.com/docs/concepts/functions/serverless-functions/supported-languages#using-typescript" target="_blank" rel="noopener noreferrer">使用 TypeScript</a></p><p>安装 <code>@vercel/node</code></p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">npm i </span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token constant" style="color:rgb(129, 31, 63)">D</span><span class="token plain"> @vercel</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain">node</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>将上面的 hello.js 改为 hello.ts，内容为</p><div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">api/hello.ts</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">type</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> VercelRequest</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> VercelResponse </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'@vercel/node'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">default</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">request</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> VercelRequest</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> response</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> VercelResponse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> name </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> request</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">query</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  response</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">status</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">200</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">send</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string string" style="color:rgb(163, 21, 21)">Hello </span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">${</span><span class="token template-string interpolation">name</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token template-string string" style="color:rgb(163, 21, 21)">!</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>此外还可以使用其他语言，这里为 Vercel 所支持的<a href="https://vercel.com/docs/concepts/functions/serverless-functions/supported-languages#supported-languages:" target="_blank" rel="noopener noreferrer">语言</a></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="开发环境">开发环境<a class="hash-link" href="#开发环境" title="标题的直接链接">​</a></h3><p>上面创建的例子是在生产环境下进行的，vercel 官方非常贴心的提供了 vercel dev 来用于开发环境（本地调试）。</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">vercel dev</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>执行后，将会默认开启 3000 端口来启动服务，此时访问 http://localhost:3000/api/hello 就可调用该接口</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="verceljson">vercel.json<a class="hash-link" href="#verceljson" title="标题的直接链接">​</a></h2><p>在根目录创建<a href="https://vercel.com/docs/project-configuration" target="_blank" rel="noopener noreferrer">vercel.json</a>，用于设置 Vercel 项目配置 ，其配置结构与 Nextjs 的 next.config.js 大体一致。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="headers">headers<a class="hash-link" href="#headers" title="标题的直接链接">​</a></h3><p>vercel 允许响应携带自定义的协议头，例如设置允许跨域的协议头。</p><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">vercel.json</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"headers"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"source"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"/(.*)"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"headers"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token property">"key"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Access-Control-Allow-Origin"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token property">"value"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"*"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token property">"key"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Access-Control-Allow-Headers"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token property">"value"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"content-type"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token property">"key"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Access-Control-Allow-Methods"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token property">"value"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"DELETE,PUT,POST,GET,OPTIONS"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="rewrites">rewrites<a class="hash-link" href="#rewrites" title="标题的直接链接">​</a></h3><p>Vercel 支持路由重写功能，因此我们可以实现反向代理。</p><p>例如将前缀为/proxy 的所有请求都代理到 <a href="http://127.0.0.1:5000%EF%BC%8C%E5%85%B6%E5%86%99%E6%B3%95%E5%A6%82%E4%B8%8B" target="_blank" rel="noopener noreferrer">http://127.0.0.1:5000，其写法如下</a></p><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">vercel.json</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"rewrites"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token property">"source"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"/proxy/:match*"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"destination"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"http://127.0.0.1:5000/:match*"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>请求<code>/proxy/hello</code> 将会请求到 <code>http://127.0.0.1:5000/hello</code>（不带有<code>/proxy</code>）</p><div class="theme-admonition theme-admonition-caution alert alert--warning admonition_LlT9"><div class="admonitionHeading_tbUL"><span class="admonitionIcon_kALy"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>警告</div><div class="admonitionContent_S0QG"><p>注意无法代理前缀为/api 的接口，即使设置了也无效。</p></div></div><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="redirects-和-rewrites-区别">redirects 和 rewrites 区别<a class="hash-link" href="#redirects-和-rewrites-区别" title="标题的直接链接">​</a></h4><p>除了 rewrites 还有一个 redirects，也就是重定向，response 返回 3xx 的状态码和 location 头信息。</p><p>而 rewrites 重写内部转发了请求，地址栏不会发生改变，并且状态码由转发的请求决定。</p><p>并且 redirects 是先被调用的，而 rewrites 是后被调用的。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="functions">functions<a class="hash-link" href="#functions" title="标题的直接链接">​</a></h3><p>可以设置指定接口分配的内存以及最大执行时间。默认下</p><ul><li>Memory: 1024 MB (1 GB)</li><li>Maximum Execution Duration: 5s (Hobby), 15s (Pro), or 30s (Enterprise)</li></ul><p>个人用户接口超时时间最长为 5 秒。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="部署-node-项目">部署 Node 项目<a class="hash-link" href="#部署-node-项目" title="标题的直接链接">​</a></h2><p>可以使用 vercel.json 配置来覆盖 vercel 默认行为，也就能使用 Vercel 部署 Node 项目。</p><p>假设要部署一个 Express 项目，则配置如下</p><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">vercel.json</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"builds"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"src"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"app.js"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"use"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"@vercel/node"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>安装 <code>@vercel/node</code>包</p><div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-shell codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token function" style="color:rgb(0, 0, 255)">npm</span><span class="token plain"> i @vercel/node -D</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>然后运行 vercel，而不是<del>vercel --prod</del></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="部署-nestjs">部署 Nest.js<a class="hash-link" href="#部署-nestjs" title="标题的直接链接">​</a></h3><p>这里有个部署 Nest.js 项目的教程 <a href="https://juejin.cn/post/7023690214803505166" target="_blank" rel="noopener noreferrer">基于 Vercel+Github Action 部署 Nest.js 项目 - 掘金 (juejin.cn)</a></p><p>其 vercel.json 如下</p><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">vercel.json</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"builds"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"src"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"dist/main.js"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"use"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"@vercel/node"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"routes"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"src"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"/(.*)"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"dest"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"dist/main.js"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>然后执行 vercel --prod（因为 nest 项目需要 build 打包）</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="最后">最后<a class="hash-link" href="#最后" title="标题的直接链接">​</a></h2><p>Vercel 十分良心，为个人用户提供了免费的爱好者计划，每个月提供 100G 流量，构建时间是 100 小时，50 个根域名绑定。</p>]]></content:encoded>
            <category>vercel</category>
            <category>serverless</category>
        </item>
        <item>
            <title><![CDATA[使用Github Action自动化部署]]></title>
            <link>https://kuizuo.cn/use-github-action-to-auto-deploy</link>
            <guid>use-github-action-to-auto-deploy</guid>
            <pubDate>Wed, 11 May 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[如果有写过项目的经历，就免不了将代码上传到服务器上，安装依赖，然后输入启动命令的步骤。但是有的项目往往需要经常性的改动，如果还是照着上面的方式进行部署的话。先不说这样操作的效率，操作个几次就想罢工了。并且上面这样操作的往往容易误操作。而 Github Actions 正是该问题的良药。]]></description>
            <content:encoded><![CDATA[<p>如果有写过项目的经历，就免不了将代码上传到服务器上，安装依赖，然后输入启动命令的步骤。但是有的项目往往需要经常性的改动，如果还是照着上面的方式进行部署的话。先不说这样操作的效率，操作个几次就想罢工了。并且上面这样操作的往往容易误操作。而 Github Actions 正是该问题的良药。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="介绍">介绍<a class="hash-link" href="#介绍" title="标题的直接链接">​</a></h2><p>Github Actions 是 Github 提供的免费自动化构建实现，特别适用于持续集成和持续交付的场景，它具备自动化完成许多不同任务的能力，例如构建、测试和部署等等。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="概念">概念<a class="hash-link" href="#概念" title="标题的直接链接">​</a></h2><p>在进行操作前，先对 Github Actions 基础知识进行补充，具体可查看 <a href="https://www.ruanyifeng.com/blog/2019/09/getting-started-with-github-actions.html" target="_blank" rel="noopener noreferrer">GitHub Actions 入门教程 阮一峰</a></p><p>可以在 <a href="https://github.com/marketplace?type=actions" target="_blank" rel="noopener noreferrer">GitHub Marketplace · Actions to improve your workflow</a> 中找到所有的 Actions。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="实例将-vite-项目发布到-github-pages">实例：将 VIte 项目发布到 GitHub Pages<a class="hash-link" href="#实例将-vite-项目发布到-github-pages" title="标题的直接链接">​</a></h2><p>第一步：创建一个 Vite 工程，可在<a href="https://cn.vitejs.dev/guide/#scaffolding-your-first-vite-project" target="_blank" rel="noopener noreferrer">官网</a>中查看如何安装</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">pnpm create vite</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>选择对应的项目名（vite-project）与模板（vue-ts）</p><p>第二步：打开<code>package.json</code>文件，加一个<code>homepage</code>字段，表示该应用发布后的根目录（参见<a href="https://create-react-app.dev/docs/deployment#building-for-relative-paths" target="_blank" rel="noopener noreferrer">官方文档</a>）。</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token string-property property">"homepage"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"https://[username].github.io/vite-project"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>上面代码中，将<code>[username]</code>替换成你的 GitHub 用户名。</p><p>第三步：在这个仓库的<code>.github/workflows</code>目录，生成一个 workflow 文件，名字可以随便取，这个示例是<code>ci.yml</code>。</p><p>workflow 文件如下</p><div class="language-yml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yml codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> Build and Deploy</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token key atrule">on</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token key atrule">push</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token key atrule">branches</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain"> master</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token key atrule">jobs</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token key atrule">build-and-deploy</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token key atrule">runs-on</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> ubuntu</span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">latest</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token key atrule">steps</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> Checkout</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token key atrule">uses</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> actions/checkout@v3</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> Install and Build</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token key atrule">run</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">|</span><span class="token scalar string" style="color:rgb(163, 21, 21)"></span><br></span><span class="token-line" style="color:#000000"><span class="token scalar string" style="color:rgb(163, 21, 21)">          yarn install</span><br></span><span class="token-line" style="color:#000000"><span class="token scalar string" style="color:rgb(163, 21, 21)">          yarn run build</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> Deploy</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token key atrule">uses</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> peaceiris/actions</span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">gh</span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">pages@v3</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token key atrule">with</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token key atrule">personal_token</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> secrets.ACCESS_TOKEN </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token key atrule">publish_dir</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> ./dist</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>上面这个 workflow 文件的要点如下</p><ol><li>整个流程在<code>master</code>分支发生<code>push</code>事件时触发。</li><li>只有一个<code>job</code>，运行在虚拟机环境<code>ubuntu-latest</code>。</li><li>第一步是获取源码，使用的 action 是<code>actions/checkout</code>。</li><li>第二步是安装依赖与构建，<code>yarn install</code>和<code>yarn run build</code></li><li>第三步是部署到 Github Page 上，使用的 action 是 <a href="https://github.com/marketplace/actions/github-pages-action" target="_blank" rel="noopener noreferrer">peaceiris/actions-gh-pages@v3</a>。其中需要设置 secrets.ACCESS_TOKEN</li></ol><p>第四步：将项目上传置 Github 仓库中，</p><p>该 peaceiris/actions-gh-pages 支持三种 Token，这里使用 personal_token，其生成教程在<a href="https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token" target="_blank" rel="noopener noreferrer">官方文档</a>中有详细图文，这里就不贴其生成的图了。<strong>不过记得权限过期以及勾选上 workflow</strong></p><div class="theme-admonition theme-admonition-tip alert alert--success admonition_LlT9"><div class="admonitionHeading_tbUL"><span class="admonitionIcon_kALy"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Tip</div><div class="admonitionContent_S0QG"><p>token 只会在生成的时候显示一次，如需要再次显示，则可以点击，但使用此令牌的任何脚本或应用程序都需要更新！</p></div></div><p>然后在<strong>Settings -&gt; Secrets -&gt; Actions 中 New repository secret</strong>中便可添加 secret。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220511122017247.png" alt="image-20220511122017247" class="img_ev3q"></p><p>这时候只要一调用 git push，就会触发对应的 workflows 文件配置。点击 Actions 便可看到 jobs 工作。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220511122420135.png" alt="image-20220511122420135" class="img_ev3q"></p><p>此时访问<a href="https://kuizuo.github.io/vite-project%E5%B0%B1%E5%8F%AF%E5%91%88%E7%8E%B0vite%E9%A1%B9%E7%9B%AE%EF%BC%88%E4%B8%8D%E8%BF%87%E6%88%91%E5%B7%B2%E7%BB%8F%E6%8A%8A%E4%BB%93%E5%BA%93%E7%BB%99%E5%85%B3%E9%97%AD%E4%BA%86%EF%BC%89%EF%BC%8C%E4%BD%86%E8%BF%9B%E5%85%A5%E4%BC%9A%E7%99%BD%E5%B1%8F%EF%BC%8C%E6%8E%A7%E5%88%B6%E5%8F%B0%E6%8F%90%E7%A4%BA" target="_blank" rel="noopener noreferrer">https://kuizuo.github.io/vite-project就可呈现vite项目（不过我已经把仓库给关闭了），但进入会白屏，控制台提示</a></p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220511122914534.png" alt="image-20220511122914534" class="img_ev3q"></p><p>很显然，需要静态资源请求的路径错了，正确的应该是<a href="https://kuizuo.github.io/vite-project/assets/index.2435d274.js%EF%BC%8C%E6%A0%B9%E6%8D%AEVite%E4%B8%AD%E7%9A%84%5B%E6%9E%84%E5%BB%BA%E7%94%9F%E4%BA%A7%E7%89%88%E6%9C%AC%5D(https://www.vitejs.net/guide/build.html#public-base-path)" target="_blank" rel="noopener noreferrer">https://kuizuo.github.io/vite-project/assets/index.2435d274.js，根据Vite中的[构建生产版本](https://www.vitejs.net/guide/build.html#public-base-path)</a> 通过命令行参数 <code>--base=/vite-project/</code></p><p>稍加操作在 Install and Build 加上 base 参数</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain"> name</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token maybe-class-name">Install</span><span class="token plain"> and </span><span class="token maybe-class-name">Build</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token literal-property property">run</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          yarn install</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          yarn run build </span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token plain">base</span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token regex regex-delimiter">/</span><span class="token regex regex-source language-regex">vite-project</span><span class="token regex regex-delimiter">/</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>git push 后，稍等片刻再次访问便可得到如下页面</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220511125536189.png" alt="image-20220511125536189" class="img_ev3q"></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="ftp发布到自有服务器上">FTP发布到自有服务器上<a class="hash-link" href="#ftp发布到自有服务器上" title="标题的直接链接">​</a></h2><p>那么现在在 Github Page 上搭建好了，但还要将编译后的文件还可以通过 FTP 协议添加自己的服务器上，这里我就以我的博客为例。</p><p>在服务器中开启 FTP，并添加一个用户名,密码以及根目录(这里我问选择为项目目录)</p><p>workflow 要做的就是新建一个 steps，这里选用 <a href="https://github.com/SamKirkland/FTP-Deploy-Action" target="_blank" rel="noopener noreferrer">FTP-Deploy-Action</a>，以下是我的完整配置内容</p><div class="language-yml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yml codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> FTP Deploy</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token key atrule">on</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">push</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token key atrule">jobs</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token key atrule">build-and-deploy</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token key atrule">runs-on</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> ubuntu</span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">latest</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token key atrule">steps</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> Checkout</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token key atrule">uses</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> actions/checkout@v3</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> Use Node.js 16</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token key atrule">uses</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> actions/setup</span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">node@v3</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token key atrule">with</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token key atrule">node-version</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'16.x'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> Build Project</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token key atrule">run</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">|</span><span class="token scalar string" style="color:rgb(163, 21, 21)"></span><br></span><span class="token-line" style="color:#000000"><span class="token scalar string" style="color:rgb(163, 21, 21)">          yarn install</span><br></span><span class="token-line" style="color:#000000"><span class="token scalar string" style="color:rgb(163, 21, 21)">          yarn run build</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> FTP Deploy</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token key atrule">uses</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> SamKirkland/FTP</span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">Deploy</span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">Action@4.0.0</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token key atrule">with</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token key atrule">server</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> secrets.ftp_server </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token key atrule">username</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> secrets.ftp_user </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token key atrule">password</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> secrets.ftp_pwd </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token key atrule">local-dir</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> ./build/</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token key atrule">server-dir</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> ./</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>相信第一个实例中的 workflow 应该已经明白了，其中 ftp_server，ftp_user，ftp_pwd 都是私密信息，所以需要 New repository secret 设置这三个变量。</p><p>但由于 build 下存在大量文件夹与文件，所以 FTP 速度上传速度堪忧，最终耗时 17 minutes 38.4 seconds。这里只是作为 FTP 演示。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="scp发布到自有服务器上">SCP发布到自有服务器上<a class="hash-link" href="#scp发布到自有服务器上" title="标题的直接链接">​</a></h2><p>FTP 传输文件着实过慢，所以可以通过 SCP 的方式来传输文件，这里用到了<a href="https://github.com/marketplace/actions/ssh-deploy" target="_blank" rel="noopener noreferrer">ssh deploy · Actions</a>，以下是示例</p><div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> ci</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token key atrule">on</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token key atrule">push</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token key atrule">branches</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain"> main</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token key atrule">jobs</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token key atrule">build-and-deploy</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token key atrule">runs-on</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> ubuntu</span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">latest</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token key atrule">steps</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> Checkout</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token key atrule">uses</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> actions/checkout@v3</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> Use Node.js 16</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token key atrule">uses</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> actions/setup</span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">node@v3</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token key atrule">with</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token key atrule">node-version</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'16.x'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> Build Project</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token key atrule">run</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">|</span><span class="token scalar string" style="color:rgb(163, 21, 21)"></span><br></span><span class="token-line" style="color:#000000"><span class="token scalar string" style="color:rgb(163, 21, 21)">          yarn install</span><br></span><span class="token-line" style="color:#000000"><span class="token scalar string" style="color:rgb(163, 21, 21)">          yarn run build</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> SSH Deploy</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token key atrule">uses</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> easingthemes/ssh</span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain">deploy@v2.2.11</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token key atrule">env</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token key atrule">SSH_PRIVATE_KEY</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> secrets.PRIVATE_KEY </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token key atrule">ARGS</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'-avzr --delete'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token key atrule">SOURCE</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'build'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token key atrule">REMOTE_HOST</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> secrets.REMOTE_HOST </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token key atrule">REMOTE_USER</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'root'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token key atrule">TARGET</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'/www/wwwroot/blog'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>其中 <strong>PRIVATE_KEY</strong> 为服务器SSH登录的私钥，<strong>REMOTE_HOST</strong> 就是服务器的ip地址。当然，这些参数也都作为私密信息，也是要通过New repository secret来设置的。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="总结">总结<a class="hash-link" href="#总结" title="标题的直接链接">​</a></h2><p>从上面的演示便可看出 Github Actions 的强大，但其实我挺早之前就了解到它能做这些事情，但迟迟没有动手尝试一番，因为这些自动化操作用人工也是能完成的。也许当时的我认为，用人工所花费的时间远比自动化操作的学习时间来的长，可又随着自己的个人应用增加，每次都需要手动发布，而此时前者的时间已远远大于后者，所以才会想去学习。</p><p>明知该技术是一定会接触的，为何不趁现在去了解学习呢？</p>]]></content:encoded>
            <category>github</category>
            <category>git</category>
        </item>
        <item>
            <title><![CDATA[Vercel部署个人博客]]></title>
            <link>https://kuizuo.cn/vercel-deploy-blog</link>
            <guid>vercel-deploy-blog</guid>
            <pubDate>Wed, 11 May 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[使用 Vercel 部署个人博客过程记录，简单方便、访问快、免费部署。]]></description>
            <content:encoded><![CDATA[<p><img loading="lazy" src="https://img.kuizuo.cn/image-20220511170700075.png" alt="image-20220511170700075" class="img_ev3q"></p><div class="theme-admonition theme-admonition-tip alert alert--success admonition_LlT9"><div class="admonitionHeading_tbUL"><span class="admonitionIcon_kALy"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>观前提醒</div><div class="admonitionContent_S0QG"><p><a href="https://vercel.com/" target="_blank" rel="noopener noreferrer">Vercel</a> 部署静态资源网站极其<strong>简单方便</strong>，并且有可观的<strong>访问速度</strong>，最主要的是<strong>免费部署</strong>。</p><p>如果你还没有尝试的话，强烈建议去使用一下。</p></div></div><p><a href="https://zhuanlan.zhihu.com/p/452654619" target="_blank" rel="noopener noreferrer">vercel 介绍</a></p><p>与之相似的产品 <a href="https://netlify.com" target="_blank" rel="noopener noreferrer">Netfily</a>，如果你想部署私有化，推荐 <a href="https://coolify.io" target="_blank" rel="noopener noreferrer">Coolify</a></p><p>如果你想搭建一个类似这样的站点，不妨参考我的 <a href="/docs/docusaurus-guides">Docusaurus 主题魔改</a></p><div class="theme-admonition theme-admonition-danger alert alert--danger admonition_LlT9"><div class="admonitionHeading_tbUL"><span class="admonitionIcon_kALy"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"></path></svg></span>DNS 污染</div><div class="admonitionContent_S0QG"><p>由于某些原因，vercel.app 被 DNS 污染（即被墙），目前在国内已经无法打开，除非你有自己的域名，通过 CNAME 解析访问你的域名。</p><p><strong>因此想要在国内访问，建议不要使用 Vercel 部署了，最好选用 Netlify。</strong></p></div></div><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="注册账号">注册账号<a class="hash-link" href="#注册账号" title="标题的直接链接">​</a></h2><p>进入 <a href="https://vercel.com" target="_blank" rel="noopener noreferrer">Vercel</a> 官网，先去注册一个账号，建议注册一个 <a href="https://github.com/" target="_blank" rel="noopener noreferrer">Github</a> 账号后，使用 Github 账号来登录 Vercel。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="部署网站">部署网站<a class="hash-link" href="#部署网站" title="标题的直接链接">​</a></h2><p>进入 <a href="https://vercel.com/dashboard" target="_blank" rel="noopener noreferrer">Dashboard</a></p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220511170233559.png" alt="image-20220511170233559" class="img_ev3q"></p><p>点击 <a href="https://vercel.com/new" target="_blank" rel="noopener noreferrer">New Project</a></p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220511165902993.png" alt="image-20220511165902993" class="img_ev3q"></p><p>这里可以从已有的 git repository 中导入，也可以选择一个模板。</p><p>这里登录我的 Github 账号选择仓库，然后点击 blog 仓库旁的 Import 即可。当然，你也可以直接拉取我的仓库，仓库地址：<a href="https://github.com/kuizuo/blog" target="_blank" rel="noopener noreferrer">kuizuo/blog</a></p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220511165513526.png" alt="image-20220511165513526" class="img_ev3q"></p><p>点击 Deploy，然后静等网站安装依赖以及部署，稍后将会出现下方页面。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220511170700075.png" alt="image-20220511170700075" class="img_ev3q"></p><p>此时网站已经成功搭建完毕了，点击图片即可跳转到 vercel 所提供的二级域名访问。</p><p>是不是极其简单？<strong>甚至不需要你输入任何命令，便可访问构建好的网站。</strong></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="自定义域名">自定义域名<a class="hash-link" href="#自定义域名" title="标题的直接链接">​</a></h2><p>如果有自己的域名，还可以在 vercel 中进行设置。</p><p>首先进入 blog 的控制台，在 Settings -&gt; Domains 添加域名。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220511171144240.png" alt="image-20220511171144240" class="img_ev3q"></p><p>接着提示域名需要 DNS 解析到 vercel 提供的记录值</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220511171359148.png" alt="image-20220511171359148" class="img_ev3q"></p><p>登录所在的域名服务商，根据 Vercel 提供的记录值 cname.vercel-dns.com，添加两条记录</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220511172741663.png" alt="image-20220511172741663" class="img_ev3q"></p><p>此时回到 Vercel，可以看到记录值成功生效。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220511172027570.png" alt="image-20220511172027570" class="img_ev3q"></p><p>此时访问自己的域名，同样也能访问到页面，同时还有可观的访问速度。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="自动颁发-ssl-证书">自动颁发 SSL 证书<a class="hash-link" href="#自动颁发-ssl-证书" title="标题的直接链接">​</a></h3><p>默认状态下，Vercel 将会颁发并自动更新 SSL 证书。（着实方便，不用自己手动去申请证书，配置证书）</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220511172240999.png" alt="image-20220511172240999" class="img_ev3q"></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="持续集成ci持续部署cd">持续集成（CI）/持续部署（CD）<a class="hash-link" href="#持续集成ci持续部署cd" title="标题的直接链接">​</a></h2><blockquote><p>To update your Production Deployment, push to the "main" branch.</p></blockquote><p>当主分支有代码被推送，Vercel 将会重新拉取代码，并重新构建进行单元测试与部署（构建速度可观）</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220511173442694.png" alt="image-20220511173442694" class="img_ev3q"></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="serverless">Serverless<a class="hash-link" href="#serverless" title="标题的直接链接">​</a></h2><p>同时 vercel 还支持 serverless，也就是说，不仅能部署静态站点，还能部署后端服务，不过肯定有一定的限制。</p><p><a href="/vercel-deploy-serverless">Vercel 部署 Serverless</a></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="edge-functions">Edge Functions<a class="hash-link" href="#edge-functions" title="标题的直接链接">​</a></h2><p>翻译过来叫边缘函数，你可以理解为在 Vercel 的 CDN 上运行的函数，可以在 Vercel 的 CDN 上运行代码，而不需要在服务器上运行。</p><p>由于这类函数和静态资源一样，都通过 CDN 分发，因此它们的执行速度非常快。</p><p>官网介绍：<a href="https://vercel.com/docs/concepts/functions/edge-functions" target="_blank" rel="noopener noreferrer">Edge Functions</a></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="vercel-cli">Vercel CLI<a class="hash-link" href="#vercel-cli" title="标题的直接链接">​</a></h2><p>有时候并不想登录网页，然后新建项目，选择仓库，拉取部署，而是希望直接在项目下输入命令来完成部署。vercel 自然肯定提供相对应的脚手架 <strong><a href="https://vercel.com/docs/cli" target="_blank" rel="noopener noreferrer">CLI</a></strong> 供开发者使用。</p><p>安装</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">npm i </span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain">g vercel</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>在项目根目录中输入</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">vercel </span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token plain">prod</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>第一次将进行登录授权，选择对应平台，将会自动打开浏览器完成授权，接着将会确认一些信息，一般默认回车即可，下为执行结果</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token maybe-class-name">Vercel</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">CLI</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">24.2</span><span class="token number" style="color:rgb(9, 134, 88)">.1</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">?</span><span class="token plain"> </span><span class="token known-class-name class-name" style="color:rgb(38, 127, 153)">Set</span><span class="token plain"> up and deploy “</span><span class="token constant" style="color:rgb(129, 31, 63)">F</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain">\</span><span class="token maybe-class-name">Project</span><span class="token plain">\</span><span class="token maybe-class-name">React</span><span class="token plain">\online</span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain">tools”</span><span class="token operator" style="color:rgb(0, 0, 0)">?</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token constant" style="color:rgb(129, 31, 63)">Y</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain">n</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> y</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">?</span><span class="token plain"> </span><span class="token maybe-class-name">Which</span><span class="token plain"> scope </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">do</span><span class="token plain"> you want to deploy to</span><span class="token operator" style="color:rgb(0, 0, 0)">?</span><span class="token plain"> kuizuo</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">?</span><span class="token plain"> </span><span class="token maybe-class-name">Link</span><span class="token plain"> to existing project</span><span class="token operator" style="color:rgb(0, 0, 0)">?</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">y</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token constant" style="color:rgb(129, 31, 63)">N</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> n</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">?</span><span class="token plain"> </span><span class="token maybe-class-name">What’s</span><span class="token plain"> your project’s name</span><span class="token operator" style="color:rgb(0, 0, 0)">?</span><span class="token plain"> online</span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain">tools</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">?</span><span class="token plain"> </span><span class="token maybe-class-name">In</span><span class="token plain"> which directory is your code located</span><span class="token operator" style="color:rgb(0, 0, 0)">?</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token maybe-class-name">Auto</span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain">detected </span><span class="token maybe-class-name">Project</span><span class="token plain"> </span><span class="token function maybe-class-name" style="color:rgb(0, 0, 255)">Settings</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token maybe-class-name">Create</span><span class="token plain"> </span><span class="token maybe-class-name">React</span><span class="token plain"> </span><span class="token maybe-class-name">App</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain"> </span><span class="token maybe-class-name">Build</span><span class="token plain"> </span><span class="token maybe-class-name">Command</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> react</span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain">scripts build</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain"> </span><span class="token maybe-class-name">Output</span><span class="token plain"> </span><span class="token maybe-class-name">Directory</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> build</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain"> </span><span class="token maybe-class-name">Development</span><span class="token plain"> </span><span class="token maybe-class-name">Command</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> react</span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain">scripts start</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">?</span><span class="token plain"> </span><span class="token maybe-class-name">Want</span><span class="token plain"> to override the settings</span><span class="token operator" style="color:rgb(0, 0, 0)">?</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">y</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token constant" style="color:rgb(129, 31, 63)">N</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> n</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">🔗  </span><span class="token maybe-class-name">Linked</span><span class="token plain"> to kuizuo12</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain">online</span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token function" style="color:rgb(0, 0, 255)">tools</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">created </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">vercel</span><span class="token plain"> and added it to </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">gitignore</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">🔍  </span><span class="token maybe-class-name">Inspect</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> https</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain">vercel</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">com</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain">kuizuo12</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain">online</span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain">tools</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain">6t8Vt8rG3waGVHTKU7ZzJuGc6Hoq </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">2s</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">✅  </span><span class="token maybe-class-name">Production</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> https</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain">online</span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain">tools</span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain">phi</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">vercel</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">app</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">copied to clipboard</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">2m</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">📝  </span><span class="token maybe-class-name">Deployed</span><span class="token plain"> to production</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain"> </span><span class="token property-access maybe-class-name">Run</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string string" style="color:rgb(163, 21, 21)">vercel --prod</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token plain"> to overwrite </span><span class="token function" style="color:rgb(0, 0, 255)">later</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">https</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain">vercel</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">link</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain">2F</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token property-access">💡</span><span class="token plain">  </span><span class="token maybe-class-name">To</span><span class="token plain"> change the domain or build command</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> go to https</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain">vercel</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">com</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain">kuizuo12</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain">online</span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain">tools</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain">settings</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>执行完毕后，将会在根目录创建.vercel 文件夹，其中 project.json 中存放 orgId 和 projectId，下面将会用到。此时在<a href="https://vercel.com/dashboard" target="_blank" rel="noopener noreferrer">dashboard</a>中也能看到该项目被部署了。</p><p>不过这样部署上去的代码，并不会连接 git 仓库，需要到控制台中选择仓库即可。</p><p>如果想在 github actions 中使用，则新建一个 steps，设置好对应的变量。</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain"> name</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token maybe-class-name">Deploy</span><span class="token plain"> to </span><span class="token maybe-class-name">Vercel</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"> &nbsp; &nbsp; &nbsp;  run</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> npx vercel </span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token plain">token $</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token constant" style="color:rgb(129, 31, 63)">VERCEL_TOKEN</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token plain">prod</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"> &nbsp; &nbsp; &nbsp;  env</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  </span><span class="token constant" style="color:rgb(129, 31, 63)">VERCEL_TOKEN</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> secrets</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token constant" style="color:rgb(129, 31, 63)">VERCEL_TOKEN</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  </span><span class="token constant" style="color:rgb(129, 31, 63)">VERCEL_PROJECT_ID</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> secrets</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token constant" style="color:rgb(129, 31, 63)">VERCEL_PROJECT_ID</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  </span><span class="token constant" style="color:rgb(129, 31, 63)">VERCEL_ORG_ID</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> secrets</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token constant" style="color:rgb(129, 31, 63)">VERCEL_ORG_ID</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>还有一个 VERCEL_TOKEN 需要到 <a href="https://vercel.com/account/tokens" target="_blank" rel="noopener noreferrer">Vercel Settings Tokens</a> 新建一个 Token。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="总结">总结<a class="hash-link" href="#总结" title="标题的直接链接">​</a></h2><p>没什么好总结，直接上手使用，相信你会爱上 Vercel，以及他旗下的产品，<a href="https://github.com/vercel/next.js" target="_blank" rel="noopener noreferrer">Next.js</a> 和 <a href="https://github.com/vercel/turbo" target="_blank" rel="noopener noreferrer">Turbo</a> 等等。</p>]]></content:encoded>
            <category>vercel</category>
            <category>blog</category>
        </item>
        <item>
            <title><![CDATA[kz-admin后台管理系统]]></title>
            <link>https://kuizuo.cn/kz-admin</link>
            <guid>kz-admin</guid>
            <pubDate>Sun, 08 May 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[基于 NestJs + TypeScript + TypeORM + Redis + MySql + Vben Admin 编写的一款前后端分离的权限管理系统]]></description>
            <content:encoded><![CDATA[<p>当时初学 Web 开发的时候，除了写一个网页博客外，第二个选择无非就是一个后台管理系统，可以应用于多种需要数据管理类项目中。</p><p>基于<strong>NestJs + TypeScript + TypeORM + Redis + MySql + Vben Admin</strong>编写的一款前后端分离的权限管理系统</p><p>演示地址：<a href="https://admin.kuizuo.cn" target="_blank" rel="noopener noreferrer">KzAdmin</a> 管理员账号：admin 密码：123456</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220505171231754.png" alt="image-20220505171231754" class="img_ev3q"></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="前端">前端<a class="hash-link" href="#前端" title="标题的直接链接">​</a></h2><p><strong>基于<a href="https://vvbin.cn/doc-next/" target="_blank" rel="noopener noreferrer">Vben Admin</a>开发，使用 Vue3、Vite、TypeScript 等最新技术栈，内置常用功能组件、权限验证、动态路由。</strong></p><p>仓库地址：<a href="https://github.com/kuizuo/kz-vue-admin" target="_blank" rel="noopener noreferrer">https://github.com/kuizuo/kz-vue-admin</a></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="项目结构"><a href="https://vvbin.cn/doc-next/guide/#%E7%9B%AE%E5%BD%95%E8%AF%B4%E6%98%8E" target="_blank" rel="noopener noreferrer">项目结构</a><a class="hash-link" href="#项目结构" title="标题的直接链接">​</a></h3><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">├── build </span><span class="token comment" style="color:rgb(0, 128, 0)"># 打包脚本相关</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   ├── config </span><span class="token comment" style="color:rgb(0, 128, 0)"># 配置文件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   ├── generate </span><span class="token comment" style="color:rgb(0, 128, 0)"># 生成器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   ├── script </span><span class="token comment" style="color:rgb(0, 128, 0)"># 脚本</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   └── vite </span><span class="token comment" style="color:rgb(0, 128, 0)"># vite配置</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├── mock </span><span class="token comment" style="color:rgb(0, 128, 0)"># mock文件夹</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├── public </span><span class="token comment" style="color:rgb(0, 128, 0)"># 公共静态资源目录</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├── src </span><span class="token comment" style="color:rgb(0, 128, 0)"># 主目录</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   ├── api </span><span class="token comment" style="color:rgb(0, 128, 0)"># 接口文件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   ├── assets </span><span class="token comment" style="color:rgb(0, 128, 0)"># 资源文件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   │   ├── icons </span><span class="token comment" style="color:rgb(0, 128, 0)"># icon sprite 图标文件夹</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   │   ├── images </span><span class="token comment" style="color:rgb(0, 128, 0)"># 项目存放图片的文件夹</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   │   └── svg </span><span class="token comment" style="color:rgb(0, 128, 0)"># 项目存放svg图片的文件夹</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   ├── components </span><span class="token comment" style="color:rgb(0, 128, 0)"># 公共组件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   ├── design </span><span class="token comment" style="color:rgb(0, 128, 0)"># 样式文件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   ├── directives </span><span class="token comment" style="color:rgb(0, 128, 0)"># 指令</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   ├── enums </span><span class="token comment" style="color:rgb(0, 128, 0)"># 枚举/常量</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   ├── hooks </span><span class="token comment" style="color:rgb(0, 128, 0)"># hook</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   │   ├── component </span><span class="token comment" style="color:rgb(0, 128, 0)"># 组件相关hook</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   │   ├── core </span><span class="token comment" style="color:rgb(0, 128, 0)"># 基础hook</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   │   ├── event </span><span class="token comment" style="color:rgb(0, 128, 0)"># 事件相关hook</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   │   ├── setting </span><span class="token comment" style="color:rgb(0, 128, 0)"># 配置相关hook</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   │   └── web </span><span class="token comment" style="color:rgb(0, 128, 0)"># web相关hook</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   ├── layouts </span><span class="token comment" style="color:rgb(0, 128, 0)"># 布局文件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   │   ├── default </span><span class="token comment" style="color:rgb(0, 128, 0)"># 默认布局</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   │   ├── iframe </span><span class="token comment" style="color:rgb(0, 128, 0)"># iframe布局</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   │   └── page </span><span class="token comment" style="color:rgb(0, 128, 0)"># 页面布局</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   ├── locales </span><span class="token comment" style="color:rgb(0, 128, 0)"># 多语言</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   ├── logics </span><span class="token comment" style="color:rgb(0, 128, 0)"># 逻辑</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   ├── main.ts </span><span class="token comment" style="color:rgb(0, 128, 0)"># 主入口</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   ├── router </span><span class="token comment" style="color:rgb(0, 128, 0)"># 路由配置</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   ├── settings </span><span class="token comment" style="color:rgb(0, 128, 0)"># 项目配置</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   │   ├── componentSetting.ts </span><span class="token comment" style="color:rgb(0, 128, 0)"># 组件配置</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   │   ├── designSetting.ts </span><span class="token comment" style="color:rgb(0, 128, 0)"># 样式配置</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   │   ├── encryptionSetting.ts </span><span class="token comment" style="color:rgb(0, 128, 0)"># 加密配置</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   │   ├── localeSetting.ts </span><span class="token comment" style="color:rgb(0, 128, 0)"># 多语言配置</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   │   ├── projectSetting.ts </span><span class="token comment" style="color:rgb(0, 128, 0)"># 项目配置</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   │   └── siteSetting.ts </span><span class="token comment" style="color:rgb(0, 128, 0)"># 站点配置</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   ├── store </span><span class="token comment" style="color:rgb(0, 128, 0)"># 数据仓库</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   ├── utils </span><span class="token comment" style="color:rgb(0, 128, 0)"># 工具类</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   └── views </span><span class="token comment" style="color:rgb(0, 128, 0)"># 页面</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├── </span><span class="token builtin class-name" style="color:rgb(38, 127, 153)">test</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)"># 测试</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│   └── server </span><span class="token comment" style="color:rgb(0, 128, 0)"># 测试用到的服务</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│       ├── api </span><span class="token comment" style="color:rgb(0, 128, 0)"># 测试服务器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│       ├── upload </span><span class="token comment" style="color:rgb(0, 128, 0)"># 测试上传服务器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">│       └── websocket </span><span class="token comment" style="color:rgb(0, 128, 0)"># 测试ws服务器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├── types </span><span class="token comment" style="color:rgb(0, 128, 0)"># 类型文件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├── vite.config.ts </span><span class="token comment" style="color:rgb(0, 128, 0)"># vite配置文件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">└── windi.config.ts </span><span class="token comment" style="color:rgb(0, 128, 0)"># windcss配置文件</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="启动项目">启动项目<a class="hash-link" href="#启动项目" title="标题的直接链接">​</a></h3><p>建议使用 pnpm 包管理器来管理 node 项目，使用<code>npm install -g pnpm</code>即可安装。</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token function" style="color:rgb(0, 0, 255)">pnpm</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">install</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token function" style="color:rgb(0, 0, 255)">pnpm</span><span class="token plain"> run dev</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>运行结果</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">  vite v2.9.5 dev server running at:</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token plain"> Network:  https://192.168.184.1:3100/</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token plain"> Local:    https://localhost:3100/</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  ready </span><span class="token keyword" style="color:rgb(0, 0, 255)">in</span><span class="token plain"> 5057ms.</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><blockquote><p>注: 开发环境下首次载入项目会稍慢(Vite 在动态解析依赖)</p></blockquote><p>更多关于前端项目规范可直接参考 <a href="https://vvbin.cn/doc-next/guide/introduction.html" target="_blank" rel="noopener noreferrer">Vben Admin 文档 </a>，非常详细了。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="后端">后端<a class="hash-link" href="#后端" title="标题的直接链接">​</a></h2><p><strong>基于 NestJs + TypeScript + TypeORM + Redis + MySql 编写的前后端分离权限管理系统</strong></p><p>仓库地址：<a href="https://github.com/kuizuo/kz-nest-admin" target="_blank" rel="noopener noreferrer">https://github.com/kuizuo/kz-nest-admin</a></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="项目结构-1"><a href="https://blog.si-yee.com/sf-admin-cli/nest/usage.html#%E7%9B%AE%E5%BD%95%E7%BB%93%E6%9E%84%E8%AF%B4%E6%98%8E" target="_blank" rel="noopener noreferrer">项目结构</a><a class="hash-link" href="#项目结构-1" title="标题的直接链接">​</a></h3><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">─setup-swagger.ts </span><span class="token comment" style="color:rgb(0, 128, 0)"># Swaager文档配置</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">─main.ts </span><span class="token comment" style="color:rgb(0, 128, 0)"># 主入口</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">─config </span><span class="token comment" style="color:rgb(0, 128, 0)"># 配置文件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">─shared</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">─redis </span><span class="token comment" style="color:rgb(0, 128, 0)"># redisModule</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">─redis.module.ts</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">─redis.interface.ts</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">─redis.constants.ts</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">─shared.module.ts</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">─services </span><span class="token comment" style="color:rgb(0, 128, 0)"># 全局通用Provider</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">─app.module.ts</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">─mission</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">─mission.module.ts</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">─mission.decorator.ts </span><span class="token comment" style="color:rgb(0, 128, 0)"># 任务装饰器，所有任务都需要定义该装饰器，否则无法运行</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">─jobs </span><span class="token comment" style="color:rgb(0, 128, 0)"># 后台定时任务定义</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">─common </span><span class="token comment" style="color:rgb(0, 128, 0)"># 系统通用定义</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">─dto </span><span class="token comment" style="color:rgb(0, 128, 0)"># 通用DTO定义</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">─contants</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">─error-code.contants.ts </span><span class="token comment" style="color:rgb(0, 128, 0)"># 系统错误码定义</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">─decorator.contants.ts </span><span class="token comment" style="color:rgb(0, 128, 0)"># 装饰器常量</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">─filters </span><span class="token comment" style="color:rgb(0, 128, 0)"># 通用过滤器定义</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">─interceptors </span><span class="token comment" style="color:rgb(0, 128, 0)"># 通用拦截器定义</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">─decorators </span><span class="token comment" style="color:rgb(0, 128, 0)"># 通用装饰器定义</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">─exceptions </span><span class="token comment" style="color:rgb(0, 128, 0)"># 系统内置通用异常定义</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">─class </span><span class="token comment" style="color:rgb(0, 128, 0)"># Class Model 不使用Interface定义，使用Interface无法让Swagger识别</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">─modules</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">─admin</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">─core </span><span class="token comment" style="color:rgb(0, 128, 0)"># 核心功能</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">─interceptors </span><span class="token comment" style="color:rgb(0, 128, 0)"># 后台管理拦截器定义</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">─decorators </span><span class="token comment" style="color:rgb(0, 128, 0)"># 后台管理注解定义</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">─provider </span><span class="token comment" style="color:rgb(0, 128, 0)"># 后台管理提供者定义</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">─guards </span><span class="token comment" style="color:rgb(0, 128, 0)"># 后台管理守卫定义</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">─system </span><span class="token comment" style="color:rgb(0, 128, 0)"># 系统模块定义</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">─account </span><span class="token comment" style="color:rgb(0, 128, 0)"># 用户账户模块定义</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">─login </span><span class="token comment" style="color:rgb(0, 128, 0)"># 登录模块定义</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">─admin.module.ts </span><span class="token comment" style="color:rgb(0, 128, 0)"># 后台管理模块</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">─admin.constants.ts </span><span class="token comment" style="color:rgb(0, 128, 0)"># 后台管理模块通用常量</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">─admin.interface.ts </span><span class="token comment" style="color:rgb(0, 128, 0)"># Admin通用interface定义</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">─ws </span><span class="token comment" style="color:rgb(0, 128, 0)"># Socket模块</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">─entities </span><span class="token comment" style="color:rgb(0, 128, 0)"># TypeORM 实体文件定义</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="启动项目-1">启动项目<a class="hash-link" href="#启动项目-1" title="标题的直接链接">​</a></h3><p>依赖安装与执行打包命令前端与后端一致，但需要提前修改.env.development 中数据库相关配置，并执行 sql/init.sql 来初始化数据。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="实现">实现<a class="hash-link" href="#实现" title="标题的直接链接">​</a></h3><p>项目中大部分的目录结构设计参照与<a href="https://github.com/hackycy/sf-nest-admin" target="_blank" rel="noopener noreferrer">sf-nest-admin</a>，但主要为了贴合自我的代码风格修改部分数据字段名，接口方法，接口响应格式等等。</p><p>同时对于大部分这类后台管理的 demo，通常都会定义用户，角色，菜单，部门。而我将部门相关代码删除，因为对于我后续项目大概率用不上这些部分，然后删了一些不相关的模块，主要写的这套模板还是用作自己后续的管理类项目。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="用户-角色-权限">用户-角色-权限<a class="hash-link" href="#用户-角色-权限" title="标题的直接链接">​</a></h4><p>这套系统中最为重要的一部分便是权限管理，不过在这套后台管理系统中这里的权限与菜单共用，前端路由渲染菜单，后端鉴权。后文的菜单表也就作为权限表而言。</p><p>在这三张表中关系如下（这里使用外键与数据库模型为例，实际项目并未用到外键，也不推荐使用）</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220508235534026.png" alt="image-20220508235534026" class="img_ev3q"></p><p>用户-角色 与 角色-权限都采用的多对多的关系，即新创建一个表用于映射两表关系。这些都属于 mysql 基础，不做过多赘述。</p><p>在权限管理中，最为重要的便是权限表了，由于这套后台管理系统中还涉及到前端的左侧菜单，所以将这里的 permission 表替换为 menu 表，字段 permission 表示权限值。数据库中的 menu 表如下</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220508234343594.png" alt="image-20220508234343594" class="img_ev3q"></p><p>对于主要字段介绍：</p><ul><li><p><strong>parent</strong>：对于有父子关系的表，会创建一个 parent_id(这里为 parent)字段用于表示父节点，无则为顶级节点。</p></li><li><p><strong>permission</strong>：权限标识，根据后端接口而定，比如新增用户的 url 为<code>sys/user/add</code>，那么权限标识通常将/替换成:，也就是<code>sys:user:add</code>（主要防止和接口的 url 混淆）。</p></li><li><p><strong>type</strong>：0 目录 1 菜单(前端组件) 2 权限，由于是菜单与权限混用，所以用 type 来区分。</p></li><li><p><strong>icon</strong>：左侧菜单图标</p></li><li><p><strong>order_no</strong>：左侧菜单排序</p></li><li><p><strong>component</strong>：组件，目录为 LAYOUT，菜单则为对应组件，权限则无</p></li></ul><p>有了这些数据，要做的是将他们拼接为<strong>前端菜单管理</strong>，<strong>根据角色获取所有菜单</strong>，<strong>根据用户的所有权限</strong>的树结构数据。</p><h5 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="前端菜单管理">前端菜单管理<a class="hash-link" href="#前端菜单管理" title="标题的直接链接">​</a></h5><p>获取所有的菜单列表数据，通过递归生成对应的菜单树结构，具体递归代码在<code>src/modules/core/permission/index.ts</code>中的<code>generatorMenu</code>方法中。</p><p>具体拼接数据过多，可自行打开控制台(F12)-&gt;网络 到菜单管理页中获取数据可得，这里便不做展示（后文拼接数据同理）。</p><h5 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="根据角色获取所有菜单">根据角色获取所有菜单<a class="hash-link" href="#根据角色获取所有菜单" title="标题的直接链接">​</a></h5><p>首先根据用户 id 找到该用户的所有角色 id，然后通过联表找到角色 id 所对应的菜单数据。</p><div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token comment" style="color:rgb(0, 128, 0)">/**</span><br></span><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)">   * 根据角色获取所有菜单</span><br></span><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)">   */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">async</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">getMenus</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">uid</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(0, 112, 193)">number</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(0, 112, 193)">Promise</span><span class="token operator" style="color:rgb(0, 0, 0)">&lt;</span><span class="token builtin" style="color:rgb(0, 112, 193)">string</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> roleIds </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">roleService</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">getRoleIdByUser</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">uid</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> menus</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> SysMenu</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token function" style="color:rgb(0, 0, 255)">includes</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">roleIds</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">rootRoleId</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      menus </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">menuRepository</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">find</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> order</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> orderNo</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'ASC'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">else</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      menus </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">menuRepository</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">createQueryBuilder</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'menu'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">innerJoinAndSelect</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'sys_role_menu'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'role_menu'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'menu.id = role_menu.menu_id'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">andWhere</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'role_menu.role_id IN (:...roldIds)'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> roldIds</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> roleIds </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">orderBy</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'menu.order_no'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'ASC'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">getMany</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> menuList </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">generatorRouters</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">menus</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> menuList</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>同样<code>generatorRouters</code>函数也在<code>src/modules/core/permission/index.ts</code>中。</p><h5 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="根据用户的所有权限">根据用户的所有权限<a class="hash-link" href="#根据用户的所有权限" title="标题的直接链接">​</a></h5><p>与上例一样，不过这里主要获取的是 permission 字段，所以在条件上添加了<code>menu.type = 2</code>与<code>menu.permission IS NOT NULL</code>，将 permission 拼接为一个数组。</p><div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token comment" style="color:rgb(0, 128, 0)">/**</span><br></span><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)">   * 获取当前用户的所有权限</span><br></span><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)">   */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">async</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">getPerms</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">uid</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(0, 112, 193)">number</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(0, 112, 193)">Promise</span><span class="token operator" style="color:rgb(0, 0, 0)">&lt;</span><span class="token builtin" style="color:rgb(0, 112, 193)">string</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> roleIds </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">roleService</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">getRoleIdByUser</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">uid</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> permission</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(0, 112, 193)">any</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> result</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(0, 112, 193)">any</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">null</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token function" style="color:rgb(0, 0, 255)">includes</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">roleIds</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">rootRoleId</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      result </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">menuRepository</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">find</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        permission</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">Not</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token function" style="color:rgb(0, 0, 255)">IsNull</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        type</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">2</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">else</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      result </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">menuRepository</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">createQueryBuilder</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'menu'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">innerJoinAndSelect</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'sys_role_menu'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'role_menu'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'menu.id = role_menu.menu_id'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">andWhere</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'role_menu.role_id IN (:...roldIds)'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> roldIds</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> roleIds </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">andWhere</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'menu.type = 2'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">andWhere</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'menu.permission IS NOT NULL'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">getMany</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token operator" style="color:rgb(0, 0, 0)">!</span><span class="token function" style="color:rgb(0, 0, 255)">isEmpty</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">result</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      result</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">forEach</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">e</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        permission </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">concat</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">permission</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> e</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">permission</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">split</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">','</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      permission </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">uniq</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">permission</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> permission</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>permission 的值如</p><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">"sys:user:add"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"sys:user:delete"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"sys:user:update"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"sys:user:list"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"sys:user:info"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>然后在 auth.guard.ts 守卫中获取 permission，然后每次请求需要鉴权的接口时，将权限标识转为接口 url，判断是否包含该 url，不包含则无访问权限。</p><p>在<a href="https://admin.kuizuo.cn/#/system/menu" target="_blank" rel="noopener noreferrer">菜单管理页</a>中可操作菜单，具体可自测。</p><p>至此，菜单表的数据被拆分为这 3 部分数据，以实现权限管理，动态路由的目的。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="其他文档">其他文档<a class="hash-link" href="#其他文档" title="标题的直接链接">​</a></h4><p>你可以访问 <a href="https://admin.kuizuo.cn/swagger-ui" target="_blank" rel="noopener noreferrer" title="https://admin.kuizuo.cn/swagger-ui">https://admin.kuizuo.cn/swagger-ui</a> 来查看kz-admin的Swagger文档</p><p>json格式为 <a href="https://admin.kuizuo.cn/swagger-ui/json" target="_blank" rel="noopener noreferrer" title="https://admin.kuizuo.cn/swagger-ui/json">https://admin.kuizuo.cn/swagger-ui/json</a>，用于导入ApiFox中。</p><p>ApiFox在线链接: <a href="https://www.apifox.cn/apidoc/shared-7a07def2-5b82-4c71-bf57-915514f61f25" target="_blank" rel="noopener noreferrer" title="https://www.apifox.cn/apidoc/shared-7a07def2-5b82-4c71-bf57-915514f61f25">https://www.apifox.cn/apidoc/shared-7a07def2-5b82-4c71-bf57-915514f61f25</a> 访问密码: kz-admin</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="写后感">写后感<a class="hash-link" href="#写后感" title="标题的直接链接">​</a></h2><p>其实一年多前我就想写一套相对完善的后台管理系统的模板，供自己后续的一些项目中使用。然而迟迟没有动手写套模板，而是不断根据业务需求，修修改改写了一套乱七八糟的代码，以至于维护的时候究极痛苦。就在不久前正好也用到，然而也是把之前写的屎山一样的代码拿来修改。</p><p><strong>我所遇到的问题：项目结构乱，代码风格乱，维护代码极其折磨</strong></p><p>所以今年寒假于是准备完善这套模板，然而当时只是创建完工程结构，到现在才正式把功能实现以及测试相关，部署搞定。说真的，非常拖延，甚至都快让我放弃写这个模板的打算。但拖也对我有一定的好处，为什么这么说？因为当时有这个想法时，市面上关于这套技术栈的实现还很少，而等我寒假再去搜索相关实现的时候，却有相关开源的代码，而这便可供我学习，使项目更加完善。</p><p>回顾整体项目的编写过程，所花费的时间可能一个月不到，甚至更少，但往往就是各种各样的拖延导致项目逾期，或者是学习某个技术栈。难以将精力集中起来完成任务，至于原因，也许是目标过于庞大，或许是日常生活中的各种琐事，不过我想多半是自我的懒惰。</p>]]></content:encoded>
            <category>project</category>
            <category>admin</category>
            <category>vue</category>
            <category>nest</category>
        </item>
        <item>
            <title><![CDATA[关于开源许可证]]></title>
            <link>https://kuizuo.cn/about-open-source-license</link>
            <guid>about-open-source-license</guid>
            <pubDate>Thu, 05 May 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[虽然知道开源有个许可证 LICENSE，但一直没给自己写的一些开源项目选择开源许可证。于是准备系统了解一下开源许可证，以及如何为 Github 项目添加 LICENSE。]]></description>
            <content:encoded><![CDATA[<p>虽然知道开源有个许可证 LICENSE，但一直没给自己写的一些开源项目选择开源许可证。于是准备系统了解一下开源许可证，以及如何为 Github 项目添加 LICENSE。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="osiopen-source-initiative">OSI(Open Source Initiative)<a class="hash-link" href="#osiopen-source-initiative" title="标题的直接链接">​</a></h3><p>即开发源代码组织，是一个旨在推动开源软件发展的非盈利组织。可以在 <a href="https://opensource.org/licenses/alphabetical" target="_blank" rel="noopener noreferrer">Open Source Initiative</a> 中查看所有的开源协议。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="开源许可证">开源许可证<a class="hash-link" href="#开源许可证" title="标题的直接链接">​</a></h2><p>关于开源许可证的简单区别</p><p><img loading="lazy" src="https://www.ruanyifeng.com/blogimg/asset/201105/bg2011050101.png" alt="img" class="img_ev3q"></p><p>至于如何选择，下图更加通俗易懂</p><p><img loading="lazy" src="https://img.kuizuo.cn/2019-04-29-072557.png" alt="快速选择协议" class="img_ev3q"></p><p>其中开源许可证可分为两大类</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="宽松式permissive许可证">宽松式（permissive）许可证<a class="hash-link" href="#宽松式permissive许可证" title="标题的直接链接">​</a></h3><p>宽松式许可证（permissive license）是最基本的类型，对用户几乎没有限制。用户可以修改代码后闭源。</p><p>它有三个基本特点。</p><p><strong>（1）没有使用限制</strong></p><p>用户可以使用代码，做任何想做的事情。</p><p><strong>（2）没有担保</strong></p><p>不保证代码质量，用户自担风险。</p><p><strong>（3）披露要求（notice requirement）</strong></p><p>用户必须披露原始作者。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="常见许可证">常见许可证<a class="hash-link" href="#常见许可证" title="标题的直接链接">​</a></h4><p>常见的宽松式许可证有四种。它们都允许用户任意使用代码，区别在于要求用户遵守的条件不同。</p><p><strong>（1）BSD（二条款版）</strong></p><p>分发软件时，必须保留原始的许可证声明。</p><p><strong>（2） BSD（三条款版）</strong></p><p>分发软件时，必须保留原始的许可证声明。不得使用原始作者的名字为软件促销。</p><p><strong>（3）MIT</strong></p><p>分发软件时，必须保留原始的许可证声明，与 BSD（二条款版）基本一致。</p><p><strong>（4）Apache 2</strong></p><p>分发软件时，必须保留原始的许可证声明。凡是修改过的文件，必须向用户说明该文件修改过；没有修改过的文件，必须保持许可证不变。</p><p>不难看出这类许可证要求相对宽松，市面上大部分的开源项目主要以 MIT 和 Apache 两者为主。使用 MIT 协议开源项目如 vue，react，bootstrap，vscode，electron，axios，terminal 等等，作为大多数开发者而言，MIT 无法是最好的选择。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="copyleft-许可证">Copyleft 许可证<a class="hash-link" href="#copyleft-许可证" title="标题的直接链接">​</a></h3><p>Copyleft 是<a href="https://www.ruanyifeng.com/blog/2005/03/post_112.html" target="_blank" rel="noopener noreferrer">理查德·斯托曼</a>发明的一个词，作为 Copyright （版权）的反义词。</p><p>Copyright 直译是"复制权"，这是版权制度的核心，意为不经许可，用户无权复制。作为反义词，Copyleft 的含义是不经许可，用户可以随意复制。</p><p>但是，它带有前提条件，比宽松式许可证的限制要多。</p><blockquote><ul><li>如果分发二进制格式，必须提供源码</li><li>修改后的源码，必须与修改前保持许可证一致</li><li>不得在原始许可证以外，附加其他限制</li></ul></blockquote><p>上面三个条件的核心就是：修改后的 Copyleft 代码不得闭源。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="常见许可证-1">常见许可证<a class="hash-link" href="#常见许可证-1" title="标题的直接链接">​</a></h4><p>常见的 Copyleft 许可证也有四种（对用户的限制从最强到最弱排序）。</p><p><strong>（1）Affero GPL (AGPL)</strong></p><p>如果云服务（即 SAAS）用到的代码是该许可证，那么云服务的代码也必须开源。</p><p><strong>（2）GPL</strong></p><p>如果项目包含了 GPL 许可证的代码，那么整个项目都必须使用 GPL 许可证。</p><p><strong>（3）LGPL</strong></p><p>如果项目采用动态链接调用该许可证的库，项目可以不用开源。</p><p><strong>（4）Mozilla（MPL）</strong></p><p>只要该许可证的代码在单独的文件中，新增的其他文件可以不用开源。</p><blockquote><p>参考文章</p><p><a href="https://www.ruanyifeng.com/blog/2017/10/open-source-license-tutorial.html" target="_blank" rel="noopener noreferrer">开源许可证教程 - 阮一峰的网络日志 (ruanyifeng.com)</a></p><p><a href="https://www.ruanyifeng.com/blog/2011/05/how_to_choose_free_software_licenses.html" target="_blank" rel="noopener noreferrer">如何选择开源许可证？ - 阮一峰的网络日志 (ruanyifeng.com)</a></p><p><a href="https://juejin.cn/post/6844903925863153672" target="_blank" rel="noopener noreferrer">五分钟看懂开源协议</a></p></blockquote><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="github-项目添加-license">Github 项目添加 LICENSE<a class="hash-link" href="#github-项目添加-license" title="标题的直接链接">​</a></h2><p>Github 官方专门制作了一个网站 <a href="https://choosealicense.com/" target="_blank" rel="noopener noreferrer">Choose a License</a> 帮助大家选择合适的开源，License。中文版也有 <a href="https://choosealicense.rustwiki.org/" target="_blank" rel="noopener noreferrer">选择一个开源许可证</a>。不过我更推荐下面在 Github 仓库页中来新增 LICENSE。</p><p>在仓库页中，Add file-&gt; Create new file</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220505190634653.png" alt="image-20220505190634653" class="img_ev3q"></p><p>输入 LICENSE（建议大写），右侧将会弹出 Choose a license template，这里我选择 MIT 协议</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220505190758791.png" alt="image-20220505190758791" class="img_ev3q"></p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220505191409696.png" alt="image-20220505191409696" class="img_ev3q"></p><p>点击 Review and submit，此时就会回到添加文件的地方，并且自动为你填写好 Message，接着点击 Commit new file 即可</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220505200951047.png" alt="image-20220505200951047" class="img_ev3q"></p><p>整个许可证内容如下</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token constant" style="color:rgb(129, 31, 63)">MIT</span><span class="token plain"> </span><span class="token maybe-class-name">License</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token function maybe-class-name" style="color:rgb(0, 0, 255)">Copyright</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">c</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">2022</span><span class="token plain"> kuizuo</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token maybe-class-name">Permission</span><span class="token plain"> is hereby granted</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> free </span><span class="token keyword" style="color:rgb(0, 0, 255)">of</span><span class="token plain"> charge</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> to any person obtaining a copy</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">of</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token plain"> software and associated documentation </span><span class="token function" style="color:rgb(0, 0, 255)">files</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">the </span><span class="token string" style="color:rgb(163, 21, 21)">"Software"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> to deal</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">in</span><span class="token plain"> the </span><span class="token maybe-class-name">Software</span><span class="token plain"> without restriction</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> including without limitation the rights</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">to use</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> copy</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> modify</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> merge</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> publish</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> distribute</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> sublicense</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> and</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain">or sell</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">copies </span><span class="token keyword" style="color:rgb(0, 0, 255)">of</span><span class="token plain"> the </span><span class="token maybe-class-name">Software</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> and to permit persons to whom the </span><span class="token maybe-class-name">Software</span><span class="token plain"> is</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">furnished to </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">do</span><span class="token plain"> so</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> subject to the following conditions</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token maybe-class-name">The</span><span class="token plain"> above copyright notice and </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token plain"> permission notice shall be included </span><span class="token keyword" style="color:rgb(0, 0, 255)">in</span><span class="token plain"> all</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">copies or substantial portions </span><span class="token keyword" style="color:rgb(0, 0, 255)">of</span><span class="token plain"> the </span><span class="token maybe-class-name">Software</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token constant" style="color:rgb(129, 31, 63)">THE</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">SOFTWARE</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">IS</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">PROVIDED</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"AS IS"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">WITHOUT</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">WARRANTY</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">OF</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">ANY</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">KIND</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">EXPRESS</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">OR</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token constant" style="color:rgb(129, 31, 63)">IMPLIED</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">INCLUDING</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">BUT</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">NOT</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">LIMITED</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">TO</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">THE</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">WARRANTIES</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">OF</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">MERCHANTABILITY</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token constant" style="color:rgb(129, 31, 63)">FITNESS</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">FOR</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">A</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">PARTICULAR</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">PURPOSE</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">AND</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">NONINFRINGEMENT</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">IN</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">NO</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">EVENT</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">SHALL</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">THE</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token constant" style="color:rgb(129, 31, 63)">AUTHORS</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">OR</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">COPYRIGHT</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">HOLDERS</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">BE</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">LIABLE</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">FOR</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">ANY</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">CLAIM</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">DAMAGES</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">OR</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">OTHER</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token constant" style="color:rgb(129, 31, 63)">LIABILITY</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">WHETHER</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">IN</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">AN</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">ACTION</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">OF</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">CONTRACT</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">TORT</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">OR</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">OTHERWISE</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">ARISING</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">FROM</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token constant" style="color:rgb(129, 31, 63)">OUT</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">OF</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">OR</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">IN</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">CONNECTION</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">WITH</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">THE</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">SOFTWARE</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">OR</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">THE</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">USE</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">OR</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">OTHER</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">DEALINGS</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">IN</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">THE</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token constant" style="color:rgb(129, 31, 63)">SOFTWARE</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>再次刷新便可看到效果</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220505201138476.png" alt="image-20220505201138476" class="img_ev3q"></p>]]></content:encoded>
            <category>open-source</category>
            <category>git</category>
        </item>
        <item>
            <title><![CDATA[代码备份方案]]></title>
            <link>https://kuizuo.cn/code-backup</link>
            <guid>code-backup</guid>
            <pubDate>Mon, 02 May 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[前段时间因为笔记本不在身边，导致一些本地磁盘代码数据没法直接同步过来。于是就准备把这些年写的代码重新整理一下，谈谈常用备份手段以及我的最佳手段]]></description>
            <content:encoded><![CDATA[<p>前段时间因为笔记本不在身边，导致一些本地磁盘代码数据没法直接同步过来。于是就准备把这些年写的代码重新整理一下，谈谈常用备份手段以及我的<a href="#%E6%9C%80%E4%BD%B3%E5%AE%9E%E7%8E%B0">最佳手段</a></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="备份手段">备份手段<a class="hash-link" href="#备份手段" title="标题的直接链接">​</a></h2><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="本地硬盘">本地硬盘<a class="hash-link" href="#本地硬盘" title="标题的直接链接">​</a></h3><p>大多数代码的存储方式，方便存取，我通常会新建一个驱动器 <strong>代码 (F:)</strong> 来将所有代码放在此处，可能还会自备一个移动硬盘来存储代码。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="优点">优点<a class="hash-link" href="#优点" title="标题的直接链接">​</a></h4><p>无需网络，保存时间久，<strong>读写数据快</strong>。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="缺点">缺点<a class="hash-link" href="#缺点" title="标题的直接链接">​</a></h4><p>数据同步不方便，难以做到跨端跨设备共享。万一硬盘出了点问题，代码将难以恢复。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="网盘">网盘<a class="hash-link" href="#网盘" title="标题的直接链接">​</a></h3><p>例如某度网盘，Onedrive 等等，这类备份通常有一定的限制，例如下载限速严重，空间限制，保存期限等等，具体以实际使用网盘为例。</p><p>在某度网盘中，选择你的想备份的文件夹，是可以做到文件夹自动备份，但对于你项目中的依赖文件（例如 Node 的 node_module）那不小的空间也将备份，但有文件夹数量以及大小限制，如下图，这里只是简单一提，不作为备用手段。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220502153823417.png" alt="image-20220502153823417" class="img_ev3q"></p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="优点-1">优点<a class="hash-link" href="#优点-1" title="标题的直接链接">​</a></h4><p>相比本地硬盘而已，<strong>网盘更易分享</strong>，在其他设备中只需要登录网盘账号或访问网盘所分享的链接。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="缺点-1">缺点<a class="hash-link" href="#缺点-1" title="标题的直接链接">​</a></h4><p>有些免费的网盘，必然有一定的限制，例如空间限制，下载限制，远不如本地硬盘。如果不付费的话，体验效果堪忧。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="代码托管平台">代码托管平台<a class="hash-link" href="#代码托管平台" title="标题的直接链接">​</a></h3><p>代码托管平台有很多，例如 Github、Gitee 等等，甚至可以自建一个像 GItLab 的代码托管平台。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="优点-2">优点<a class="hash-link" href="#优点-2" title="标题的直接链接">​</a></h4><p><strong>代码实时性强</strong>，并且基于 Git 版本管理工具可以很方便查看代码的历史操作，对于项目类的而言非常方便。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="缺点-2">缺点<a class="hash-link" href="#缺点-2" title="标题的直接链接">​</a></h4><p>对于一些公有项目而言，一些私密信息（密码）不易于上传，在其他设备拉取代码就不存在这部分数据。同时<strong>对于大量代码就束手无策</strong>。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="最佳实现">最佳实现<a class="hash-link" href="#最佳实现" title="标题的直接链接">​</a></h2><p>介绍完上面的几种代码备份手段，各自都有优缺点，至于如何选择就因人而异，这里就说说我是如何备份代码的。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="全部代码">全部代码<a class="hash-link" href="#全部代码" title="标题的直接链接">​</a></h3><p>对于全部代码而言，肯定是多备份远优于不备份的。所以我通常会在本地电脑硬盘中备份两份代码，一份就正常放在固态硬盘上，另一份则放在机械硬盘，同时再备份一份代码在网盘上。</p><p>但机械硬盘与网盘的备份时间一致，都是定期或阶段性的备份（甚至可能会忘记备份），所以这种对代码的实时性要求不高，通常这类代码为学习代码以及工具类相关代码。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="项目代码">项目代码<a class="hash-link" href="#项目代码" title="标题的直接链接">​</a></h3><p>对于项目代码而言，我是毫不犹豫的选择代码托管平台，使用到版本管理工具 Git，可以很好的查看代码的全部历史记录以及修改追踪能力。易于维护的同时，代码分享与同步也比网盘来的高效。设置好.gitignore 也不会将非必要的文件（依赖文件，打包后的文件，生产环境下的配置文件）上传上去。而 Github 便是我最好的选择，里面存放了或多或少的开源与私有项目，每次在其他设备上只需要登录 github，然后 clone 项目，便可开始 coding。</p><p><strong>通常来说备份项目代码就已经足够了，毕竟这类代码往往会有一定的价值性。</strong></p><div class="theme-admonition theme-admonition-caution alert alert--warning admonition_LlT9"><div class="admonitionHeading_tbUL"><span class="admonitionIcon_kALy"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>警告</div><div class="admonitionContent_S0QG"><p>但这还不够，因为放在别人的网站上的代码，万一人家网站停用，或者是你的代码有点风险给你代码仓库封了，那么这时候你想找回代码都无法找回！所以为了做好备份代码的万全准备，一般是推荐搭建私有 git 服务，然后自动同步 github 的账号下的所有仓库。</p></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="文章笔记备份">文章笔记备份<a class="hash-link" href="#文章笔记备份" title="标题的直接链接">​</a></h3><p>除了代码备份外，此外笔记也十分重要，毕竟有时候自己写的代码，自己甚至都不一定明白。对于文章数据以及笔记，我通常会使用云端协作平台，这类产品有 wolai，notion，语雀等等，不过我个人还是相对倾向于使用 <a href="https://www.wolai.com/" target="_blank" rel="noopener noreferrer">wolai</a>。可多端设备查看，实时编辑等等，体验还算 ok。</p><p>此外一些博客文章，就会同步在<a href="https://kuizuo.cn/" target="_blank" rel="noopener noreferrer">个人博客</a>以及<a href="https://juejin.im/user/1565318510545901/activities" target="_blank" rel="noopener noreferrer">掘金</a>上，当然博客的静态站点的代码仓库也是存放在<a href="https://github.com/kuizuo/blog" target="_blank" rel="noopener noreferrer">Github</a>上。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="不必要的代码不要备份">不必要的代码不要备份<a class="hash-link" href="#不必要的代码不要备份" title="标题的直接链接">​</a></h3><p>其实对于很多代码都没备份的必要，例如我在安卓学习的时候，涉及到的刷机包（少说 2 个 g），以及各种 apk。完全可以直接备份其下载地址，而不是选择备份。</p><p>像临时用脚手架创建的工程文件或是下载别人的代码，这类通常就临时使用（甚至不会再打开第二次），完全没有必要备份理由。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="请压缩后在备份">请压缩后在备份<a class="hash-link" href="#请压缩后在备份" title="标题的直接链接">​</a></h3><p>如果不压缩文件夹，备份时将逐个读取文件特别耗时，同时压缩完代码还可以节省一定的空间。也许在一开始备份时会相对麻烦，但在上传与下载以及多次备份时就一举两便。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="最后">最后<a class="hash-link" href="#最后" title="标题的直接链接">​</a></h2><p><strong>永远不要嫌备份麻烦，当你辛辛苦苦写的代码丢失时，那才是真正的麻烦。</strong></p><p><strong>养成定期备份代码的习惯，因为你永远不知道什么突发情况会导致代码丢失。</strong></p>]]></content:encoded>
            <category>随笔</category>
            <category>code</category>
        </item>
        <item>
            <title><![CDATA[搭建GitLab代码管理仓库]]></title>
            <link>https://kuizuo.cn/gitlab-code-management-environment</link>
            <guid>gitlab-code-management-environment</guid>
            <pubDate>Fri, 15 Apr 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[image-20220414235645607]]></description>
            <content:encoded><![CDATA[<p><img loading="lazy" src="https://img.kuizuo.cn/image-20220414235645607.png" alt="image-20220414235645607" class="img_ev3q"></p><p>我只要有代码的项目，都会放到 Github 上，无论公开还是私有项目。一是相当于在云端备份了一份代码，二是可以很方便的分享给别人。但对于私有项目而言存放在别人那总归不好，而且Github 时常会出现无法访问的情况（即使搭了梯子）。所以就打算搭建一个私有的仓库，基于<a href="https://gitlab.com/" target="_blank" rel="noopener noreferrer">GitLab</a>。</p><p>可以访问 <a href="https://gitlab.kuizuo.cn/kuizuo" target="_blank" rel="noopener noreferrer">kuizuo · GitLab</a> 来查看搭建效果。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="页面概览">页面概览<a class="hash-link" href="#页面概览" title="标题的直接链接">​</a></h2><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220415013028002.png" alt="image-20220415013028002" class="img_ev3q"></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="前提">前提<a class="hash-link" href="#前提" title="标题的直接链接">​</a></h2><p>一台服务器，系统 Linux，内存 &gt;=4g</p><p>我的轻量应用服务器配置如下</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220414210129510.png" alt="image-20220414210129510" class="img_ev3q"></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="搭建">搭建<a class="hash-link" href="#搭建" title="标题的直接链接">​</a></h2><p>服务器我选择安装<a href="https://www.bt.cn/new/index.html" target="_blank" rel="noopener noreferrer">宝塔面板</a>，对于个人项目，还是很推荐安装的，集成了一些软件商店，包括本次的主角，同时提供可视化页面操作，能省下很多敲命令的时间，<del>同时也会增加忘记命令的记忆</del>。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="安装-gitlab">安装 GitLab<a class="hash-link" href="#安装-gitlab" title="标题的直接链接">​</a></h3><p>进入宝塔面板，点击软件商店，找到<strong>GitLab 最新社区版</strong>，点击安装</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220414204808143.png" alt="image-20220414204808143" class="img_ev3q"></p><p>实测等了 8 分钟，安装完毕即可查看 GitLab 的访问地址，账号密码。默认端口号 8099，记得在防火墙开放下该端口</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220414213002293.png" alt="image-20220414213002293" class="img_ev3q"></p><p>进入访问地址就可以看到 GitLab 的登录页面了。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="修改密码">修改密码<a class="hash-link" href="#修改密码" title="标题的直接链接">​</a></h3><p><a href="https://docs.gitlab.com/ee/security/reset_user_password.html#reset-the-root-password" target="_blank" rel="noopener noreferrer">Reset a user's password | GitLab</a></p><p>进入控制台（进入要稍等一段时间）</p><div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">sudo gitlab-rails console</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>显示页面如下</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">root@</span><span class="token constant" style="color:rgb(129, 31, 63)">VM</span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token number" style="color:rgb(9, 134, 88)">4</span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token number" style="color:rgb(9, 134, 88)">5</span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain">centos </span><span class="token operator" style="color:rgb(0, 0, 0)">~</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"># sudo gitlab</span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain">rails console</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"> </span><span class="token literal-property property">Ruby</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain">         ruby </span><span class="token number" style="color:rgb(9, 134, 88)">2.7</span><span class="token number" style="color:rgb(9, 134, 88)">.5</span><span class="token function" style="color:rgb(0, 0, 255)">p203</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">2021</span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token number" style="color:rgb(9, 134, 88)">11</span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token number" style="color:rgb(9, 134, 88)">24</span><span class="token plain"> revision f69aeb8314</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">x86_64</span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain">linux</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"> </span><span class="token literal-property property">GitLab</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain">       </span><span class="token number" style="color:rgb(9, 134, 88)">14.9</span><span class="token number" style="color:rgb(9, 134, 88)">.3</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">ec11aba56f1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">FOSS</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"> </span><span class="token maybe-class-name">GitLab</span><span class="token plain"> </span><span class="token maybe-class-name">Shell</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">13.24</span><span class="token number" style="color:rgb(9, 134, 88)">.0</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"> </span><span class="token literal-property property">PostgreSQL</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain">   </span><span class="token number" style="color:rgb(9, 134, 88)">12.7</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"> booted </span><span class="token keyword" style="color:rgb(0, 0, 255)">in</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">29</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">71s </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token maybe-class-name">Loading</span><span class="token plain"> production </span><span class="token function" style="color:rgb(0, 0, 255)">environment</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token maybe-class-name">Rails</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">6.1</span><span class="token number" style="color:rgb(9, 134, 88)">.4</span><span class="token number" style="color:rgb(9, 134, 88)">.6</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token function" style="color:rgb(0, 0, 255)">irb</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">main</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token number" style="color:rgb(9, 134, 88)">001</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>输入如下代码</p><div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">u=User.find(1)</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">u.password='a12345678'</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">u.password_confirmation = 'a12345678'</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">u.save!</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>输出结果</p><div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">irb(main):001:0&gt; u=User.find(1)</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">=&gt; #&lt;User id:1 @root&gt;</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">irb(main):002:0&gt; u.password='a12345678'</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">=&gt; "a12345678"</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">irb(main):003:0&gt; u.password_confirmation = 'a12345678'</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">=&gt; "a12345678"</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">irb(main):004:0&gt; u.save!</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">=&gt; true</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">irb(main):005:0&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>最后输入<code>exit</code>退出控制台，然后输入下方代码重启 gitlab，密码就设置完毕了</p><div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">gitlab-ctl restart</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><div class="theme-admonition theme-admonition-info alert alert--info admonition_LlT9"><div class="admonitionHeading_tbUL"><span class="admonitionIcon_kALy"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>信息</div><div class="admonitionContent_S0QG"><p>若重启或修改端口等操作后出现 502 错误，您可能需要等待 3-5 分钟才能正常访问 GitLab</p></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="修改语言">修改语言<a class="hash-link" href="#修改语言" title="标题的直接链接">​</a></h3><p>点击右上角的头像-&gt;Preferences 进入到设置，找到语言设置为简体中文，然后点击左小角的 Save changes。刷新网页语言就设置完毕了</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220414215528543.png" alt="image-20220414215528543" class="img_ev3q"></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="配置https">配置HTTPS<a class="hash-link" href="#配置https" title="标题的直接链接">​</a></h3><p>gitlab内部集成了letsencrypt，因此，这里只需要启用letsencrypt，并进行一些必要的配置</p><p>打开/opt/gitlab/etc/gitlab.rb.template，修改以下内容</p><ol><li><p>在32行左右，将external_url前面的#删掉，并在单引号中填写gitlab服务器的https地址，例如<a href="https://gitlab.kuizuo.cn" target="_blank" rel="noopener noreferrer">https://gitlab.kuizuo.cn</a></p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain"> external_url </span><span class="token string" style="color:rgb(163, 21, 21)">'https://gitlab.kuizuo.cn'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></li><li><p>gitlab默认占用nginx80端口，所以需要更改下</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">nginx</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'listen_port'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">8100</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></li><li><p>在2434行左右（可通过搜索letsencrypt定位），修改下面几项</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">letsencrypt</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'enable'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token plain"> #删除前面的#号，并将值修改为</span><span class="token boolean">true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">letsencrypt</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'contact_emails'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'kuizuo12@gmail.com'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> #删除前面的#号</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain">修改为自己的邮箱</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">letsencrypt</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'auto_renew'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token plain"> #删除前面的#号  自动更新</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></li></ol><p>然后重载配置（需要一点时间）</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">gitlab</span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain">ctl reconfigure</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>然后重启gitlab使配置生效</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">gitlab</span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain">ctl restart</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>gitlab就会通过letsencrypt自动签发免费的HTTPS证书，等证书签发成功，就可以通过上面指定的域名访问代码仓库了。</p><p><strong>其实也可以在nginx创建一个站点，然后该站点配置ssl，通过反向代理到127.0.0.1:8099 也是能实现配置HTTPS的。（推荐）</strong></p><div class="theme-admonition theme-admonition-danger alert alert--danger admonition_LlT9"><div class="admonitionHeading_tbUL"><span class="admonitionIcon_kALy"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"></path></svg></span>危险</div><div class="admonitionContent_S0QG"><p>如果上面的操作的话，可能会导致gitlab的nginx无法启动（原因应该是修改了gitlab自带的nginx服务，或者与自带的冲突）。修改<code>/opt/gitlab/sv/nginx/run</code></p><div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">exec chpst -P /opt/gitlab/embedded/sbin/nginx -p /var/opt/gitlab/nginx</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"># 改为</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">exec chpst -P /opt/gitlab/embedded/sbin/gitlab-web -p /var/opt/gitlab/nginx</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>重启gitlab</p><div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">gitlab-ctl start</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></div></div><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="管理中心">管理中心<a class="hash-link" href="#管理中心" title="标题的直接链接">​</a></h2><p>点击左上角的菜单选择管理员，可在管理中心设置GitLab的相关设置。例如</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="禁止注册">禁止注册<a class="hash-link" href="#禁止注册" title="标题的直接链接">​</a></h3><p>在设置-&gt;通用-&gt;注册限制，取消勾选 <strong>已启动注册功能</strong>，这样就可以禁止注册（页面无注册按钮）。当然也可以允许，然后需要批准以及确认邮箱。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220415004207174.png" alt="image-20220415004207174" class="img_ev3q"></p><p>在概览-&gt;用户中可以查看相关用户信息。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220415012817311.png" alt="image-20220415012817311" class="img_ev3q"></p><p>至于其他设置自行研究了。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="创建项目">创建项目<a class="hash-link" href="#创建项目" title="标题的直接链接">​</a></h2><p>点击新建项目，这里就导入我的 blog 项目。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220414220221480.png" alt="image-20220414220221480" class="img_ev3q"></p><p>选择 Github 后，会提示使用 GitHub 身份验证，这里需要拿到 Github 的<a href="https://github.com/settings/tokens" target="_blank" rel="noopener noreferrer">Token</a></p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220414220333437.png" alt="image-20220414220333437" class="img_ev3q"></p><p>访问<a href="https://github.com/settings/tokens%EF%BC%8C%E6%96%B0%E5%BB%BA%E4%B8%80%E4%B8%AAToken%EF%BC%8C%E9%80%89%E6%8B%A9token%E6%9C%89%E6%95%88%E6%9C%9F%EF%BC%8C%E4%BB%A5%E5%8F%8A%E7%9B%B8%E5%85%B3%E6%9D%83%E9%99%90%EF%BC%88%E6%88%91%E8%BF%99%E8%BE%B9%E9%80%89%E6%8B%A9%E5%85%A8%E9%80%89%EF%BC%8Ctoken%E4%B8%8D%E8%BF%87%E6%9C%9F%EF%BC%89" target="_blank" rel="noopener noreferrer">https://github.com/settings/tokens，新建一个Token，选择token有效期，以及相关权限（我这边选择全选，token不过期）</a></p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220414220507016.png" alt="image-20220414220507016" class="img_ev3q"></p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220414220738714.png" alt="image-20220414220738714" class="img_ev3q"></p><p>生成完毕后复制该 Token 到 GitLab 上，就可以看到该 Github 账号下的所有仓库了，这里我选择 blog 进行导入（导入需要一点时间）。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220414220858379.png" alt="image-20220414220858379" class="img_ev3q"></p><p>导入完毕后与原仓库无特别区别</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220414224639573.png" alt="image-20220414224639573" class="img_ev3q"></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="自动同步项目">自动同步项目<a class="hash-link" href="#自动同步项目" title="标题的直接链接">​</a></h3><p>点击项目中设置-&gt;仓库，找到镜像仓库。在 Git 仓库 URL 中填写格式如下</p><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)">// 原仓库git</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token literal-property property">https</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain">github</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">com</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain">kuizuo</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain">blog</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// 在https://后加上username@</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token literal-property property">https</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain">kuizuo@github</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">com</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain">kuizuo</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain">blog</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>密码为上面的 Token（如果忘记的话，可以在 Github 的 Token 页中 Regenerate token），如下图所示</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220414232028397.png" alt="image-20220414232028397" class="img_ev3q"></p><hr><p>基本上github能实现的操作gitlab也都能实现。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="其他功能">其他功能<a class="hash-link" href="#其他功能" title="标题的直接链接">​</a></h2><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="web-ide在线编辑代码">Web IDE（在线编辑代码）<a class="hash-link" href="#web-ide在线编辑代码" title="标题的直接链接">​</a></h3><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220415001914123.png" alt="image-20220415001914123" class="img_ev3q"></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="运行状态">运行状态<a class="hash-link" href="#运行状态" title="标题的直接链接">​</a></h2><p>放几张图</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220414233435739.png" alt="image-20220414233435739" class="img_ev3q"></p><p>输入 top 命令，按 M 按内存排序。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220414233416223.png" alt="image-20220414233416223" class="img_ev3q"></p><p>还是挺吃内存的，毕竟安装的时候就要求 4g 内存以上。</p><p>有个轻量级的项目管理器 <a href="https://github.com/go-gitea/gitea" target="_blank" rel="noopener noreferrer">gitea</a> 不妨也是一种选择，但功能上没有Gitlab这么丰富。</p><p>对于自建git服务的选择，这里有篇文章推荐阅读 <a href="https://zhuanlan.zhihu.com/p/486410391" target="_blank" rel="noopener noreferrer">自建 Git 服务器：Gitea 与 Gitlab 部署踩坑经历与对比总结 - 知乎 (zhihu.com)</a></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="总结">总结<a class="hash-link" href="#总结" title="标题的直接链接">​</a></h2><p>其实回到一开始的问题，既然Github有可能访问不了，为啥不要迁移到国内的<a href="https://gitee.com/" target="_blank" rel="noopener noreferrer">Gitee</a>上。</p><p><del>除了瞎玩瞎折腾外</del>，对于一些公司而言，他们不一定会使用这类开源的代码托管平台，而是自建一个像GitLab这样的代码仓库管理系统。此外别人的东西，多半都会有一定的限制，例如项目成员数量等等，所以才会有这次的尝试，整体体验感觉可玩性很大。</p>]]></content:encoded>
            <category>git</category>
            <category>gitlab</category>
        </item>
        <item>
            <title><![CDATA[vite+vue3搭建uniapp开发环境]]></title>
            <link>https://kuizuo.cn/vite-vue3-build-uniapp-environment</link>
            <guid>vite-vue3-build-uniapp-environment</guid>
            <pubDate>Sun, 27 Mar 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[使用 vite vue3 搭建 uniapp 开发环境]]></description>
            <content:encoded><![CDATA[<p><img loading="lazy" src="https://img.kuizuo.cn/uniapp.png" alt="uniapp" class="img_ev3q"></p><p>最近想搞个移动端或小程序的 Vue3 项目，所以选择跨端开发平台就显得十分重要。在业内主要有两个跨端开发平台，Taro 与 uniapp，但 uniapp 貌似对 vue3 的支持不是特别友好。所以让我在 Taro 和 uniapp 之间抉择了一段时间，最终还是尝试选择相对熟悉的 uniapp 来进行开发。</p><div class="theme-admonition theme-admonition-caution alert alert--warning admonition_LlT9"><div class="admonitionHeading_tbUL"><span class="admonitionIcon_kALy"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>前排提醒</div><div class="admonitionContent_S0QG"><p>目前 uniapp 对 Vue3 的支持还处于 alpha 版，即开发阶段，大概率是会遇到很多问题的。</p></div></div><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="开发环境搭建">开发环境搭建<a class="hash-link" href="#开发环境搭建" title="标题的直接链接">​</a></h2><p>建议安装 HBuilderX，主要是 uni cli 在 APP 平台仅支持生成离线打包的 wgt 资源包，不支持云端打包生成 apk/ipa，并且也不便配置一些打包后的参数。</p><p>这里建议安装 Alpha 版，后文会说明缘由。</p><div class="theme-admonition theme-admonition-caution alert alert--warning admonition_LlT9"><div class="admonitionHeading_tbUL"><span class="admonitionIcon_kALy"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>注意</div><div class="admonitionContent_S0QG"><p>在 HBuilderX 正式版中是无法直接创建 Vue3 项目的，而 Alpha 版有 Vue2 和 3 可供选择，但创建的自带的模板大部分的写法还是 vue2 的写法（无 setup 语法糖），所以这时候要么改代码自建，要么使用官方所提供的 <a href="https://uniapp.dcloud.io/worktile/CLI.html#%E5%88%9B%E5%BB%BA%E5%B7%A5%E7%A8%8B" target="_blank" rel="noopener noreferrer">Vue3 模板</a></p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220327000608783.png" alt="image-20220327000608783" class="img_ev3q"></p></div></div><div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain"># 创建以 javascript 开发的工程</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">npx degit dcloudio/uni-preset-vue#vite my-vue3-project</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"># 创建以 typescript 开发的工程</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">npx degit dcloudio/uni-preset-vue#vite-ts my-vue3-project</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>当然，有可能会下载失败，可以直接访问 <a href="https://gitee.com/dcloud/uni-preset-vue/repository/archive/vite-ts.zip" target="_blank" rel="noopener noreferrer">gitee</a>下载模板。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="项目结构">项目结构<a class="hash-link" href="#项目结构" title="标题的直接链接">​</a></h2><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token plain"> src</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token plain"> </span><span class="token maybe-class-name">App</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">vue</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token plain"> env</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">d</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">ts</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token plain"> main</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">ts</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token plain"> manifest</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">json</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token plain"> pages</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">json</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token plain"> uni</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">scss</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token plain"> pages</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">   </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token plain"> index</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">       </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token plain"> index</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">vue</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">static</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token plain"> logo</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">png</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token plain"> index</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">html</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">package</span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain">lock</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">json</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">package</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">json</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token plain"> postcss</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">config</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">js</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token plain"> tsconfig</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">json</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token plain"> vite</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">config</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">ts</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>下载完毕，开始安装依赖，接着就可以开始测试了。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="运行编译">运行编译<a class="hash-link" href="#运行编译" title="标题的直接链接">​</a></h2><p>在运行之前，首先将<strong>vuex</strong>包给移除，不然将会有如下提示，总之就是不推荐使用的意思，而且要使用状态管理也推荐使用 pinia。所以执行 <code>yarn remove vuex</code> 吧</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">node</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token number" style="color:rgb(9, 134, 88)">26968</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token constant" style="color:rgb(129, 31, 63)">DEP0148</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token maybe-class-name">DeprecationWarning</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token maybe-class-name">Use</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">of</span><span class="token plain"> deprecated folder mapping </span><span class="token string" style="color:rgb(163, 21, 21)">"./"</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">in</span><span class="token plain"> the </span><span class="token string" style="color:rgb(163, 21, 21)">"exports"</span><span class="token plain"> field module resolution </span><span class="token keyword" style="color:rgb(0, 0, 255)">of</span><span class="token plain"> the </span><span class="token keyword" style="color:rgb(0, 0, 255)">package</span><span class="token plain"> at </span><span class="token constant" style="color:rgb(129, 31, 63)">F</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain">\</span><span class="token maybe-class-name">Uniapp</span><span class="token plain">\my</span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain">vue3</span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain">project1\node_modules\vuex\</span><span class="token keyword" style="color:rgb(0, 0, 255)">package</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">json</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token property-access maybe-class-name">Update</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">package</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">json</span><span class="token plain"> to use a subpath pattern like </span><span class="token string" style="color:rgb(163, 21, 21)">"./*"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="h5">H5<a class="hash-link" href="#h5" title="标题的直接链接">​</a></h3><p>运行编译都正常</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="app">APP<a class="hash-link" href="#app" title="标题的直接链接">​</a></h3><p>使用<code>npm run dev:app</code>后就会发现，终端一直卡在如下界面无法继续。（后面测试发现，除了 H5 能正常运行，其他都会卡住）</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">编译器版本：</span><span class="token number" style="color:rgb(9, 134, 88)">3.4</span><span class="token number" style="color:rgb(9, 134, 88)">.3</span><span class="token plain">（vue3）</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">请注意运行模式下，因日志输出、sourcemap 以及未压缩源码等原因，性能和包体积，均不及发行模式</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">。</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">正在编译中</span><span class="token spread operator" style="color:rgb(0, 0, 0)">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">vite v2</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token number" style="color:rgb(9, 134, 88)">8.6</span><span class="token plain"> building </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">for</span><span class="token plain"> development</span><span class="token spread operator" style="color:rgb(0, 0, 0)">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token constant" style="color:rgb(129, 31, 63)">DONE</span><span class="token plain">  </span><span class="token maybe-class-name">Build</span><span class="token plain"> complete</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain"> </span><span class="token property-access maybe-class-name">Watching</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">for</span><span class="token plain"> changes</span><span class="token spread operator" style="color:rgb(0, 0, 0)">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">ready </span><span class="token keyword" style="color:rgb(0, 0, 255)">in</span><span class="token plain"> 1554ms</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>然后呢？？？</p><p>算了，就用 HBuilderX 的 cli 先运行到手机或模拟器，然后后打开 app 的时候提示如下错误，点击忽略后发现应用无法正常运行。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220326224649953.png" alt="image-20220326224649953" class="img_ev3q"></p><p>查看了下我本地的 HBuilderX 版本是正式版 v3.3.13，而该 Vue3 的模板的 Alpha 版 v3.4.3</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220326225748608.png" alt="image-20220326225748608" class="img_ev3q"></p><p>好家伙，官方提供的模板都直接使用 Alpha 版，无奈只好点击 <a href="https://ask.dcloud.net.cn/article/35627" target="_blank" rel="noopener noreferrer">查看详情</a> 后问题解决办法。最终测试后，建议是使用最新版，即 Alpha 版本，于是替换了本地正式版的 HbuilderX，应用便能正常运行了。</p><p>既然开发环境下能正常运行，那就试下打包。由于 uniapp 打包安卓应用只能打包成 APP 资源，要打包成 apk，要么创建一个 Android Studio 工程，然后将 APP 资源放入并打包成 apk，要么使用云打包（而云打包又是只有 HBuilder 才有的功能）。如果本地没有 Android Studio 相关环境，建议还是使用云打包（简单方便），这里就不演示下打包过程了。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="小程序">小程序<a class="hash-link" href="#小程序" title="标题的直接链接">​</a></h3><p>这里只测试了微信小程序，在上面 app 的处理完之后，微信小程序也是正常运行，不过至于与上面 Vue3 模板和 HbuilderX 正式版有无关系我就不得而知了，也懒得重装测试了。不过猜测应该与上面无关，毕竟是与手机的 SDK 有关。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="组件库">组件库<a class="hash-link" href="#组件库" title="标题的直接链接">​</a></h2><p>uniapp 官方中提供了一个 uni-ui 的组件库，但有一个 uniapp 相对知名的组件库 uview，并且相对前者来说更易上手实用，但当我尝试用 HBuilderX 导入时，却出现下方提示。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220327002827115.png" alt="image-20220327002827115" class="img_ev3q"></p><p>很显然，uview 并不支持 vue3，但在社区中找到了份同时支持 Vue3.0 和 Vue2.0 的<a href="https://ext.dcloud.net.cn/plugin?name=vk-uview-ui" target="_blank" rel="noopener noreferrer">uView</a>，但测试后最终已失败告终。</p><p>在社区中也搜到了 <a href="https://ext.dcloud.net.cn/plugin?id=556" target="_blank" rel="noopener noreferrer">ThorUI 组件库</a> 但貌似需要会员收费，果断放弃且没有测试。</p><p>然后想到 Taro 中还有 nutui，于是我便开始尝试了一下，不出所料，支持 Vue3 组件库，肯定是支持的。演示如下</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220327005629618.png" alt="image-20220327005629618" class="img_ev3q"></p><p>但很遗憾，这里的支持也只是局限于 h5 开发。官方也有声明只能开发 h5</p><blockquote><p>@nutui/nutui@next 基于 Vue3 视觉风格 JD APP 10.0 规范 ，只能开发 h5
@nutui/nutui-taro 基于 Vue3 视觉风格 JD APP 10.0 规范 ，必须基于 taro + vue3 框架 进行开发多端（多端指一套代码 部署多端环境 微信小程序 h5、等第三方小程序）</p></blockquote><p>而且想要多端开发，也必须基于 taro + vue3 框架，所以在 uniapp 上的 app 与小程序上自然无法运行（已测试）</p><p>所以说一开始在 uniapp 和 taro 中的选择中，为啥不使用 Taro 呢？而且还支持 Vue3（相比 uniapp 而言）？</p><p>最终组件库的选择是 uniapp 官方的 uni-ui。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="使用-vscode-开发">使用 VSCode 开发<a class="hash-link" href="#使用-vscode-开发" title="标题的直接链接">​</a></h2><p>HBuilder 给我代码编写体验并不友好，所以将 uniapp 的项目转 vscode 进行开发，并且使用到 npm 包。</p><p>首先创建一个 vite+vue3 项目（或者使用一开始介绍的官方提供的 Vue3 模板，主要是有 cli，需要自行在安装），然后将原 src 目录给删除，替换成 uniapp 创建的项目根目录。但还需要做以下操作</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="安装-sass">安装 sass<a class="hash-link" href="#安装-sass" title="标题的直接链接">​</a></h3><p>vite 要支持 sass 只需要安装 sass 的依赖即可</p><div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">npm install sass</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="允许-js-文件">允许 js 文件<a class="hash-link" href="#允许-js-文件" title="标题的直接链接">​</a></h3><p>由于使用了 ts，如果项目中存在 js 文件，将会警告，可以在 tsconfig.json 中添加<code>"allowJs": true</code>即可</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="组件语法提示">组件语法提示<a class="hash-link" href="#组件语法提示" title="标题的直接链接">​</a></h3><div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">npm i @dcloudio/uni-helper-json @types/uni-app @types/html5plus -D</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>但发现对于 uni-ui 组件库的代码提示并不友好，大概率是需要局部引用组件，我这里并未使用<a href="https://www.npmjs.com/package/@dcloudio/uni-ui" target="_blank" rel="noopener noreferrer">npm 包</a>的方式导入，而是采用官方的 uni_modules，不过组件库的代码提示的问题不是很大，查阅文档即可解决。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="导入代码块">导入代码块<a class="hash-link" href="#导入代码块" title="标题的直接链接">​</a></h3><p><a href="https://github.com/zhetengbiji/uniapp-snippets-vscode" target="_blank" rel="noopener noreferrer">uni-app 代码块（vscode） (github.com)</a></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="找不到模块appvue或其相应的类型声明">找不到模块“./App.vue”或其相应的类型声明<a class="hash-link" href="#找不到模块appvue或其相应的类型声明" title="标题的直接链接">​</a></h3><p>在 src 目录下创建<code>env.d.ts</code>文件，填入以下内容即可</p><div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)">/// &lt;reference types="vite/client" /&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">declare</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">module</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'*.vue'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> DefineComponent </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'vue'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token comment" style="color:rgb(0, 128, 0)">// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> component</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> DefineComponent</span><span class="token operator" style="color:rgb(0, 0, 0)">&lt;</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(0, 112, 193)">any</span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">default</span><span class="token plain"> component</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>然后就是把一些<code>#ifndef VUE3</code>不是 vue3 的代码块，以及部分 js 文件改写成 ts 文件即可。这里把我修改后的模板上传到 github 上，有需要的可自行下载：<a href="https://github.com/kuizuo/vite-vue3-uniapp" target="_blank" rel="noopener noreferrer">kuizuo/vite-vue3-uniapp (github.com)</a></p><p>如果不想使用官方的 vue3 模板，这里也有篇文章介绍如何迁移</p><p><a href="https://zhuanlan.zhihu.com/p/268206071" target="_blank" rel="noopener noreferrer">迁移 HbuilderX 的 uniapp 项目到主流的前端 IDE 开发（支持 VS Code 等编辑器/IDE）</a></p><p>不过最终如果要在 app 或小程序端运行，还是得打开 HBuilder。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="总结">总结<a class="hash-link" href="#总结" title="标题的直接链接">​</a></h2><p>整个过程下来，其实还是 uniapp 对 Vue3 支持不够友好，加上生态没能及时更新。并且官方提供的 Vue3 模板也存在一定问题。</p><p>但最终还是使用 uniapp 来进行开发，一是对 Vue3 足够了解加上使用过 uniapp，二是 Taro 对 Vue3 是支持了，但是又该如何编译成 App 这是我主要需求的，最主要还是不想踩一遍 Taro 的坑了。</p>]]></content:encoded>
            <category>vue</category>
            <category>vite</category>
            <category>uniapp</category>
            <category>develop</category>
        </item>
        <item>
            <title><![CDATA[去除typescript代码类型]]></title>
            <link>https://kuizuo.cn/remove-ts-code-type</link>
            <guid>remove-ts-code-type</guid>
            <pubDate>Thu, 24 Mar 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[在短时间内有一个需求，原项目代码是 js，而我手里头的功能代码是 ts 的，需要将其合并。]]></description>
            <content:encoded><![CDATA[<p>在<strong>短时间</strong>内有一个需求，原项目代码是 js，而我手里头的功能代码是 ts 的，需要将其合并。</p><p>按照以往，我通常会将 js 改写成 ts，但时间方面有限，就采取js的方式。<strong>因此希望将 ts 代码转换为存 js 代码</strong>，只需要把 ts 中的类型直接删除即可，也就是标题所表明的意思。以下在线转化工具能够做到。</p><p><a href="https://transform.tools/typescript-to-javascript" target="_blank" rel="noopener noreferrer">TypeScript to plain JavaScript (transform.tools)</a></p><p>可以肯定的是 ts 有选项能够去除类型，于是这次就准备深入了解 TypeScript 的编译配置，也顺带复习一下 tsconfig.json 的相关参数。</p><p><strong>毕竟会写代码，不会编译可就...</strong></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="安装-typescript">安装 TypeScript<a class="hash-link" href="#安装-typescript" title="标题的直接链接">​</a></h2><p>要编写 ts 代码，肯定要先安装其工具</p><div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">npm i -g typescript ts-node</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>其中<code>typescript</code>自带的 tsc 命令并不能直接运行 typescript 代码，而<code>ts-node</code>可以直接运行 ts 代码的能力，省去编译阶段。</p><p>但不代表<code>ts-node</code>等于 ts 版的 Node.js，本质上 Node.js 只是 JavaScript 的运行时环境，而 Deno 确实可以直接运行 TypeScript。</p><p>不过本次的主题不在 ts-node 与 deno，而在于将 TypeScript 代码编译到 JavaScript 代码。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="简单测试">简单测试<a class="hash-link" href="#简单测试" title="标题的直接链接">​</a></h2><p>安装完毕，编写一个<code>demo.ts</code>的文件，在里面编写如下代码</p><div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">demo.ts</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> add </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">a</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(0, 112, 193)">number</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> b</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(0, 112, 193)">number</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(0, 112, 193)">number</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> a </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> b</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> c </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">add</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">2</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>使用命令 <code>tsc demo.ts</code>，将会在同级目录下生成<code>demo.js</code>，内容如下（默认是 ES5 标准）</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">demo.js</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">var</span><span class="token plain"> </span><span class="token function-variable function" style="color:rgb(0, 0, 255)">add</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">a</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> b</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> a </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> b</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">var</span><span class="token plain"> c </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">add</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">2</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="tsconfigjson">tsconfig.json<a class="hash-link" href="#tsconfigjson" title="标题的直接链接">​</a></h2><p>可以发现上面转化的代码是 ES5 标准的，然而现在都已经步入到 ES6 阶段了，同时如果有大量 ts 文件需要编译，将十分繁琐，所以就有了 tsconfig.json 用于描述将 <strong>TypeScript</strong> 转为 <strong>JavaScript</strong> 代码的配置文件。</p><p>终端使用<code>tsc --init</code>，会在目录下生成 tsconfig.json 文件，默认配置如下（已删除原注释）。</p><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">tsconfig.json</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"compilerOptions"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"target"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"es5"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 编译</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"module"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"commonjs"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 模块导入与导出</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"esModuleInterop"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 支持合成模块的默认导入</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"forceConsistentCasingInFileNames"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 看不懂</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"strict"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 严格模式</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"skipLibCheck"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 跳过.d.ts</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>假设我要编译 ES6 语法的，只需要将 es5 改为 es6，然后在终端输入<code>tsc</code>，生成的 js 代码就是 es6 规范的代码。</p><div class="theme-admonition theme-admonition-info alert alert--info admonition_LlT9"><div class="admonitionHeading_tbUL"><span class="admonitionIcon_kALy"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>信息</div><div class="admonitionContent_S0QG"><p>如果想要单纯的取出 ts 的类型，可以设置<code>"target": "ESNext"</code>，除了 ts 的一些特殊标准，如 enum，那么生成的 js 代码基本就是原 ts 代码移除类型的代码。（基本上就已经满足了我一开始的需求）</p></div></div><p>更多配置 =&gt; <a href="https://www.typescriptlang.org/tsconfig" target="_blank" rel="noopener noreferrer">TypeScript: TSConfig Reference - Docs on every TSConfig option (typescriptlang.org)</a></p><p>更多相关 TS 编译配置和使用说明可以通过 <code>tsc -h</code> 查看。</p><p>这里有份 <a href="https://juejin.cn/post/7039583726375796749#heading-22" target="_blank" rel="noopener noreferrer">tsconfig.json 全解析</a> 内容如下</p><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">tsconfig.json</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"compilerOptions"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">/* 基本选项 */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"target"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"es6"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 指定 ECMAScript 目标版本: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"module"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"commonjs"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 指定使用模块: 'commonjs', 'amd', 'system', 'umd' or 'es2015'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"lib"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 指定要包含在编译中的库文件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"allowJs"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 允许编译 javascript 文件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"checkJs"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 报告 javascript 文件中的错误</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"jsx"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"preserve"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 指定 jsx 代码的生成: 'preserve', 'react-native', or 'react'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"declaration"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 生成相应的 '.d.ts' 文件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"declarationDir"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"./dist/types"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 生成的 '.d.ts' 文件保存文件夹</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"sourceMap"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 生成相应的 '.map' 文件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"outFile"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"./"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 将输出文件合并为一个文件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"outDir"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"./dist"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 指定输出目录</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"rootDir"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"./"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 用来控制输出目录结构 --outDir.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"removeComments"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 删除编译后的所有的注释</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"noEmit"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 不生成输出文件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"importHelpers"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 从 tslib 导入辅助工具函数</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"isolatedModules"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 将每个文件做为单独的模块 （与 'ts.transpileModule' 类似）.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">/* 严格的类型检查选项 */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"strict"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 启用所有严格类型检查选项</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"noImplicitAny"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 在表达式和声明上有隐含的 any类型时报错</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"strictNullChecks"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 启用严格的 null 检查</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"noImplicitThis"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 当 this 表达式值为 any 类型的时候，生成一个错误</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"alwaysStrict"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 以严格模式检查每个模块，并在每个文件里加入 'use strict'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">/* 额外的检查 */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"noUnusedLocals"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 有未使用的变量时，抛出错误</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"noUnusedParameters"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 有未使用的参数时，抛出错误</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"noImplicitReturns"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 并不是所有函数里的代码都有返回值时，抛出错误</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"noFallthroughCasesInSwitch"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 报告switch语句的fallthrough错误。（即，不允许switch的case语句贯穿）</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">/* 模块解析选项 */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"moduleResolution"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"node"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 选择模块解析策略： 'node' (Node.js) or 'classic' (TypeScript pre-1.6)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"baseUrl"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"./"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 用于解析非相对模块名称的基础目录</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"paths"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 模块名到基于 baseUrl 的路径映射的列表</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"rootDirs"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 根文件夹列表，其组合内容表示项目运行时的结构内容</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"typeRoots"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 包含类型声明的文件列表</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"types"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 需要包含的类型声明文件名列表</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"allowSyntheticDefaultImports"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 允许从没有设置默认导出的模块中默认导入。</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"esModuleInterop"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 支持合成模块的默认导入</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">/* Source Map Options */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"sourceRoot"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"./"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 指定调试器应该找到 TypeScript 文件而不是源文件的位置</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"mapRoot"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"./"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 指定调试器应该找到映射文件而不是生成文件的位置</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"inlineSourceMap"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 生成单个 soucemaps 文件，而不是将 sourcemaps 生成不同的文件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"inlineSources"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 将代码与 sourcemaps 生成到一个文件中，要求同时设置了 --inlineSourceMap 或 --sourceMap 属性</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">/* 其他选项 */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"experimentalDecorators"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 启用装饰器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"emitDecoratorMetadata"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 为装饰器提供元数据的支持</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token comment" style="color:rgb(0, 128, 0)">/* 指定编译文件或排除指定编译文件 */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"include"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">"src/**/*"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"exclude"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">"node_modules"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"**/*.spec.ts"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"files"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">"index.ts"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"test.ts"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token comment" style="color:rgb(0, 128, 0)">// 从另一个配置文件里继承配置</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"extends"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"@tsconfig/recommended"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token comment" style="color:rgb(0, 128, 0)">// 让 IDE 在保存文件的时候根据 tsconfig.json 重新生成文件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"compileOnSave"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 支持这个特性需要Visual Studio 2015， TypeScript 1.8.4 以上并且安装 atom-typescript 插件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="常用配置">常用配置<a class="hash-link" href="#常用配置" title="标题的直接链接">​</a></h2><p>原本想自己总结一遍，但刷到了下面这篇文章，总结的太好了，以至于我都不是很想再写一遍主要的配置 🤩</p><p><a href="https://juejin.cn/post/7039583726375796749#heading-4" target="_blank" rel="noopener noreferrer">会写 TypeScript 但你真的会 TS 编译配置吗？ - 掘金 (juejin.cn)</a></p><p>话虽说，但一些主要的功能还是得写一下</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="配置别名">配置别名<a class="hash-link" href="#配置别名" title="标题的直接链接">​</a></h3><p>在一些项目中经常能看到导入模块不是使用相对路径<code>./</code>，而是像<code>@/</code>，其中@表示 src，也就是项目的原代码目录下，也就是路径别名。要实现这样的配置，项目的脚手架肯定是需要修改的。这里我就以 vite 为例。</p><div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">vite.config.ts</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> defineConfig </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'vite'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> resolve </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'path'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">default</span><span class="token plain"> defineConfig </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    resolve</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        alias</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token string-property property">"@"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">resolve</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">__dirname</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'src'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 路径别名</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        extensions</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'.js'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'.json'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'.ts'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 使用路径别名时想要省略的后缀名</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">// ...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">tsconfig.json</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"compilerOptions"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"baseUrl"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"."</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 必写，用于设置解析非相对模块名称的基本目录</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"paths"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"@/*"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">"src/*"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 用于设置模块名到基于baseUrl的路径映射</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">// ...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="支持合成默认导入">支持合成默认导入<a class="hash-link" href="#支持合成默认导入" title="标题的直接链接">​</a></h3><p>在使用 ESM（ES module） 编写代码的时候，引入 CJS（CommonJS）的模块，通常需要写成 <code>import * as React from 'react'</code>的形式，若写成 <code>import React from 'react'</code> 将会提示 <strong>模块“"http"”没有默认导出</strong>。，如果将<code>esModuleInterop</code>设置为 true，同时<code>allowSyntheticDefaultImports</code> 也会自动设置为 true，则可以写成后者的形式。</p><p>这里有篇文章详细的说明缘由 <a href="https://zhuanlan.zhihu.com/p/148081795" target="_blank" rel="noopener noreferrer">esModuleInterop 到底做了什么？</a></p><blockquote><p>所以，尽量不要用 default 导出。 ——借评论区的一条评论</p></blockquote><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="声明浏览器全局对象-api">声明浏览器全局对象 API<a class="hash-link" href="#声明浏览器全局对象-api" title="标题的直接链接">​</a></h3><p>在代码中使用到浏览器的对象，如 window、document，这些对于<strong>TypeScript Complier</strong> 来说是不能识别。可以通过在 lib 字段中设置<code>"DOM"</code></p><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"compilerOptions"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"target"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"ES5"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"lib"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">"ES5"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"ES6"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"DOM"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="声明文件">声明文件<a class="hash-link" href="#声明文件" title="标题的直接链接">​</a></h3><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"compilerOptions"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"declaration"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 生成相应的`.d.ts`文件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"declarationDir"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"./dist/types"</span><span class="token plain"> 生成的 '.d.ts' 文件保存文件夹</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>]]></content:encoded>
            <category>javascript</category>
            <category>typescript</category>
        </item>
        <item>
            <title><![CDATA[搭建Electron+Vue3开发环境]]></title>
            <link>https://kuizuo.cn/electron-vue3-development-environment</link>
            <guid>electron-vue3-development-environment</guid>
            <pubDate>Thu, 17 Mar 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[搭建 Electron Vue3 的开发环境，用于编写跨平台应用]]></description>
            <content:encoded><![CDATA[<p><img loading="lazy" src="https://img.kuizuo.cn/image-20220316204205165.png" alt="image-20220316204205165" class="img_ev3q"></p><p>之前用 electron-vue 写过一个半成品的桌面端应用，但是是基于 Vue2 的，最近又想重写点桌面端应用，想要上 Vue3+TypeScript，于是便有了这篇文章总结下具体的搭建过程。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="vue-cli">Vue Cli<a class="hash-link" href="#vue-cli" title="标题的直接链接">​</a></h2><p>Vue CLI 有一个插件<code>vue-cli-plugin-electron-builder</code>，可以非常方便的搭建 electron 环境。</p><div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">npm i @vue/cli -g</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">vue create my-app</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>根据自己项目的需求选择对应的依赖（例如 Babel，TS，Vuex 等等）</p><div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">Vue CLI v5.0.3</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">? Please pick a preset: Manually select features</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">? Check the features needed for your project: Babel, TS, Vuex, CSS Pre-processors, Linter</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">? Choose a version of Vue.js that you want to start the project with 3.x</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">? Use class-style component syntax? Yes</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)? Yes</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default): Sass/SCSS (with dart-sass)</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">? Pick a linter / formatter config: Prettier</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">? Pick additional lint features: Lint on save</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">? Where do you prefer placing config for Babel, ESLint, etc.? In package.json</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">? Save this as a preset for future projects? No</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">Vue CLI v5.0.3</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">✨  Creating project in F:\Electron\my-app.</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">🗃  Initializing git repository...</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">⚙️  Installing CLI plugins. This might take a while...</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="安装-vue-cli-plugin-electron-builder">安装 vue-cli-plugin-electron-builder<a class="hash-link" href="#安装-vue-cli-plugin-electron-builder" title="标题的直接链接">​</a></h3><p><a href="https://nklayman.github.io/vue-cli-plugin-electron-builder/" target="_blank" rel="noopener noreferrer">Vue CLI Plugin Electron Builder (nklayman.github.io)</a></p><div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">cd my-app</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">vue add electron-builder</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>安装过程中会提示你选择 Electron 的版本，选择最新版本即可</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="启动项目">启动项目<a class="hash-link" href="#启动项目" title="标题的直接链接">​</a></h3><div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">npm run electron:serve</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>参考文章：<a href="https://juejin.cn/post/6983843979133468708" target="_blank" rel="noopener noreferrer">Electron + Vue3 开发跨平台桌面应用【从项目搭建到打包完整过程】 - 掘金 (juejin.cn)</a></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="坑">坑<a class="hash-link" href="#坑" title="标题的直接链接">​</a></h3><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">error  </span><span class="token keyword" style="color:rgb(0, 0, 255)">in</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain">src</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain">background</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">ts</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token maybe-class-name">Module</span><span class="token plain"> build </span><span class="token function" style="color:rgb(0, 0, 255)">failed</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain">node_modules</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain">ts</span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain">loader</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain">index</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">js</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token known-class-name class-name" style="color:rgb(38, 127, 153)">TypeError</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> loaderContext</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">getOptions</span><span class="token plain"> is not a </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>我测试的时候，<code>@vue/cli-plugin-typescript</code>版本为<code>~5.0.0</code>，就会导致编译类型出错，将 package.json 中改为<code>"@vue/cli-plugin-typescript": "~4.5.15"</code>，即可正常运行（但还是会有 DeprecationWarning）</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="vite">Vite<a class="hash-link" href="#vite" title="标题的直接链接">​</a></h2><p>上面是使用 Vue Cli 脚手架进行开发，如果想上 Vite 的话，就需要用 Vite 来构建项目，然后安装 electron 的相关依赖。</p><p>这个不是作为重点，因为很多大佬都已经写了现成的模板，完全可以自行借鉴学习，就贴几个阅读过的几篇文章</p><p><a href="https://dev.to/brojenuel/vite-vue-3-electron-5h4o" target="_blank" rel="noopener noreferrer">Vite + Vue 3 + electron + TypeScript - DEV Community</a></p><p><a href="https://zhuanlan.zhihu.com/p/424202065" target="_blank" rel="noopener noreferrer">2021 年最前卫的跨平台开发选择！vue3 + vite + electron - 知乎 (zhihu.com)</a></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="现成的模板">现成的模板<a class="hash-link" href="#现成的模板" title="标题的直接链接">​</a></h3><p>均可在 github 上搜索到</p><ul><li><p><a href="https://github.com/caoxiemeihao/vite-react-electron" target="_blank" rel="noopener noreferrer">vite-react-electron</a> (推荐)</p></li><li><p><a href="https://github.com/caoxiemeihao/electron-vue-vite" target="_blank" rel="noopener noreferrer">electron-vue-vite</a> (推荐)</p></li><li><p><a href="https://github.com/cawa-93/vite-electron-builder" target="_blank" rel="noopener noreferrer">vite-electron-builder</a></p></li></ul><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="electron-vite-脚手架推荐">electron-vite 脚手架（推荐）<a class="hash-link" href="#electron-vite-脚手架推荐" title="标题的直接链接">​</a></h3><p>当然也可以使用脚手架，可选择 React 与 Vue，实际上也就是创建上面的前两个模板</p><div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">npm create electron-vite</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="现有项目使用-electron">现有项目使用 electron<a class="hash-link" href="#现有项目使用-electron" title="标题的直接链接">​</a></h2><p>TODO...</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="总结">总结<a class="hash-link" href="#总结" title="标题的直接链接">​</a></h2><p>因为 Electron 本质上还是一个浏览器，无论是 Vue 还是 React 开发也好，在传统网页开发的时候都有对应的调试地址，如<a href="http://127.0.0.1:3000%EF%BC%8C%E8%80%8Celectron%E7%9A%84%E5%81%9A%E6%B3%95%E6%97%A0%E9%9D%9E%E5%B0%B1%E6%98%AF%E5%BC%80%E5%90%AF%E4%B8%80%E4%B8%AA%E6%B5%8F%E8%A7%88%E5%99%A8%EF%BC%8C%E7%84%B6%E5%90%8E%E5%92%8C%E6%AD%A3%E5%B8%B8%E7%9A%84%E7%BD%91%E9%A1%B5%E5%BC%80%E5%8F%91%E4%B8%80%E6%A0%B7%EF%BC%8C%E5%B9%B6%E6%8F%90%E4%BE%9B%E6%A1%8C%E9%9D%A2%E7%AB%AF%E7%9A%84api%E4%BD%BF%E7%94%A8%E3%80%82" target="_blank" rel="noopener noreferrer">http://127.0.0.1:3000，而electron的做法无非就是开启一个浏览器，然后和正常的网页开发一样，并提供桌面端的api使用。</a></p><p>目前社区两大 Vue+Electron 的脚手架主要是<a href="https://github.com/SimulatedGREG/electron-vue" target="_blank" rel="noopener noreferrer">electron-vue</a>和<a href="https://github.com/nklayman/vue-cli-plugin-electron-builder" target="_blank" rel="noopener noreferrer">vue-cli-plugin-electron-builder</a>，更多 electron 的开源项目都遵循着前者的项目结构，像上面的模板也就是。</p><p>以上就是我所使用 Vue3 来开发 Electron 的环境搭建过程，总体来说从 Electron 除了应用体积过大，对于前端开发者来说是非常友好的，既然环境配置完，那么现在就可以开始好好的编写桌面端应用了。</p>]]></content:encoded>
            <category>electron</category>
            <category>vue</category>
            <category>vite</category>
        </item>
        <item>
            <title><![CDATA[SSE 服务器发送事件]]></title>
            <link>https://kuizuo.cn/sse-server-send-event</link>
            <guid>sse-server-send-event</guid>
            <pubDate>Wed, 16 Mar 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[先放一张 gif 图展示下效果]]></description>
            <content:encoded><![CDATA[<p>先放一张 gif 图展示下效果</p><p><img loading="lazy" src="https://img.kuizuo.cn/sse.gif" alt="sse" class="img_ev3q"></p><p>实现上面这个效果之前，先补充点前置知识</p><p>众所周知，在 HTTP 协议中，服务器无法向浏览器推送信息，可以使用 WebSocket 来实现两者双向通信。而在这里所要介绍的是 SSE（Server-Sent Events），在浏览器向服务器请求后，服务器每隔一段时间向客户端发送流数据（是单向的），来实现接收服务器的数据，例如在线视频播放，和像上面所演示的效果。</p><p><img loading="lazy" src="https://www.ruanyifeng.com/blogimg/asset/2017/bg2017052702.jpg" alt="img" class="img_ev3q"></p><p>关于 SSE 标准文档 <a href="https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events" target="_blank" rel="noopener noreferrer">MDN 文档</a></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="优点">优点<a class="hash-link" href="#优点" title="标题的直接链接">​</a></h3><ul><li>SSE 使用 HTTP 协议，现有的服务器软件都支持。WebSocket 是一个独立协议。</li><li>SSE 属于轻量级，使用简单；WebSocket 协议相对复杂。</li><li>SSE 默认支持断线重连，WebSocket 需要自己实现。</li><li>SSE 一般只用来传送文本，二进制数据需要编码后传送，WebSocket 默认支持传送二进制数据。</li><li>SSE 支持自定义发送的消息类型。</li></ul><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="服务器实现">服务器实现<a class="hash-link" href="#服务器实现" title="标题的直接链接">​</a></h2><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="数据格式">数据格式<a class="hash-link" href="#数据格式" title="标题的直接链接">​</a></h3><p>服务器向浏览器发送的 SSE 数据，必须是 UTF-8 编码的文本，具有如下的 HTTP 头信息。</p><div class="language-http codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-http codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">Content-Type: text/event-stream; charset=utf-8</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">Cache-Control: no-cache</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">Connection: keep-alive</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>使用 Node 实现的代码如下</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">var</span><span class="token plain"> http </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">require</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'http'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">http</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">createServer</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">req</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">var</span><span class="token plain"> fileName </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'.'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> req</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">url</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">fileName </span><span class="token operator" style="color:rgb(0, 0, 0)">===</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'./stream'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">writeHead</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">200</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token string-property property">'Content-Type'</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'text/event-stream'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token string-property property">'Cache-Control'</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'no-cache'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token literal-property property">Connection</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'keep-alive'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token string-property property">'Access-Control-Allow-Origin'</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'*'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">write</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'retry: 10000\n'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">write</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'event: connecttime\n'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">write</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'data: '</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">Date</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'\n\n'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">write</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'data: '</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">Date</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'\n\n'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      interval </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">setInterval</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">write</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'data: '</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">Date</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'\n\n'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1000</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      req</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">connection</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">addListener</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token string" style="color:rgb(163, 21, 21)">'close'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token function" style="color:rgb(0, 0, 255)">clearInterval</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">interval</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">listen</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">8844</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'127.0.0.1'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>通过 node server.js 运行服务端，此时浏览器访问 <a href="http://127.0.0.1:8844/stream" target="_blank" rel="noopener noreferrer">http://127.0.0.1:8844/stream</a> 得到的效果就是开头的 gif 所演示的。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="客户端-api">客户端 API<a class="hash-link" href="#客户端-api" title="标题的直接链接">​</a></h2><p>像上面是直接向服务器请求，浏览器有<code>EventSource</code>对象，比如监听 SSE 连接，以及主动关闭 SSE 连接，具体的演示代码如下</p><div class="language-html codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-html codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token doctype punctuation" style="color:rgb(4, 81, 165)">&lt;!</span><span class="token doctype doctype-tag">DOCTYPE</span><span class="token doctype"> </span><span class="token doctype name">html</span><span class="token doctype punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">html</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">head</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">meta</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">charset</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">utf-8</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">/&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">meta</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">name</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">viewport</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">content</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">width=device-width</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">/&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">title</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain">JS Bin</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">title</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">head</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">body</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">div</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">id</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">example</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">div</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">script</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">      </span><span class="token script language-javascript keyword" style="color:rgb(0, 0, 255)">var</span><span class="token script language-javascript"> source </span><span class="token script language-javascript operator" style="color:rgb(0, 0, 0)">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript keyword" style="color:rgb(0, 0, 255)">new</span><span class="token script language-javascript"> </span><span class="token script language-javascript class-name" style="color:rgb(38, 127, 153)">EventSource</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token script language-javascript string" style="color:rgb(163, 21, 21)">'http://127.0.0.1:8844/stream'</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">      </span><span class="token script language-javascript keyword" style="color:rgb(0, 0, 255)">var</span><span class="token script language-javascript"> div </span><span class="token script language-javascript operator" style="color:rgb(0, 0, 0)">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript dom variable" style="color:rgb(9, 134, 88)">document</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token script language-javascript method function property-access" style="color:rgb(0, 0, 255)">getElementById</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token script language-javascript string" style="color:rgb(163, 21, 21)">'example'</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">      source</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token script language-javascript method-variable function-variable method function property-access" style="color:rgb(0, 0, 255)">onopen</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:rgb(0, 0, 0)">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript keyword" style="color:rgb(0, 0, 255)">function</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token script language-javascript parameter">event</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">        div</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token script language-javascript property-access">innerHTML</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:rgb(0, 0, 0)">+=</span><span class="token script language-javascript"> </span><span class="token script language-javascript string" style="color:rgb(163, 21, 21)">'&lt;p&gt;Connection open ...&lt;/p&gt;'</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">      </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">      source</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token script language-javascript method-variable function-variable method function property-access" style="color:rgb(0, 0, 255)">onerror</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:rgb(0, 0, 0)">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript keyword" style="color:rgb(0, 0, 255)">function</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token script language-javascript parameter">event</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">        div</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token script language-javascript property-access">innerHTML</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:rgb(0, 0, 0)">+=</span><span class="token script language-javascript"> </span><span class="token script language-javascript string" style="color:rgb(163, 21, 21)">'&lt;p&gt;Connection close.&lt;/p&gt;'</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">      </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">      source</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token script language-javascript method function property-access" style="color:rgb(0, 0, 255)">addEventListener</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">        </span><span class="token script language-javascript string" style="color:rgb(163, 21, 21)">'connecttime'</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">        </span><span class="token script language-javascript keyword" style="color:rgb(0, 0, 255)">function</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token script language-javascript parameter">event</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">          div</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token script language-javascript property-access">innerHTML</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:rgb(0, 0, 0)">+=</span><span class="token script language-javascript"> </span><span class="token script language-javascript string" style="color:rgb(163, 21, 21)">'&lt;p&gt;Start time: '</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:rgb(0, 0, 0)">+</span><span class="token script language-javascript"> event</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token script language-javascript property-access">data</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:rgb(0, 0, 0)">+</span><span class="token script language-javascript"> </span><span class="token script language-javascript string" style="color:rgb(163, 21, 21)">'&lt;/p&gt;'</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">        </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">        </span><span class="token script language-javascript boolean">false</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">      </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">      source</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token script language-javascript method-variable function-variable method function property-access" style="color:rgb(0, 0, 255)">onmessage</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:rgb(0, 0, 0)">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript keyword" style="color:rgb(0, 0, 255)">function</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token script language-javascript parameter">event</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">        div</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token script language-javascript property-access">innerHTML</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:rgb(0, 0, 0)">+=</span><span class="token script language-javascript"> </span><span class="token script language-javascript string" style="color:rgb(163, 21, 21)">'&lt;p&gt;Ping: '</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:rgb(0, 0, 0)">+</span><span class="token script language-javascript"> event</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token script language-javascript property-access">data</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:rgb(0, 0, 0)">+</span><span class="token script language-javascript"> </span><span class="token script language-javascript string" style="color:rgb(163, 21, 21)">'&lt;/p&gt;'</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">      </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">    </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">script</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">body</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">html</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>并且由于是调用浏览器 API，在开发者工具的网络面板上还能看到对应的 EventStream，像下面这样</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220316134321431.png" alt="image-20220316134321431" class="img_ev3q"></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="参考链接">参考链接<a class="hash-link" href="#参考链接" title="标题的直接链接">​</a></h2><blockquote><p><a href="https://developer.mozilla.org/zh-CN/docs/Web/API/Server-sent_events/Using_server-sent_events" target="_blank" rel="noopener noreferrer">使用服务器发送事件 - Web API 接口参考 | MDN (mozilla.org)</a></p><p><a href="https://www.ruanyifeng.com/blog/2017/05/server-sent_events.html" target="_blank" rel="noopener noreferrer">Server-Sent Events 教程 - 阮一峰的网络日志 (ruanyifeng.com)</a></p></blockquote>]]></content:encoded>
            <category>http</category>
        </item>
        <item>
            <title><![CDATA[在线工具]]></title>
            <link>https://kuizuo.cn/online-tools</link>
            <guid>online-tools</guid>
            <pubDate>Wed, 16 Mar 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[基于 React 与 MUI 组件库搭建在线工具网站]]></description>
            <content:encoded><![CDATA[<p><img loading="lazy" alt="愧怍在线工具" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABH8AAAIWCAMAAAD53tEYAAAAQlBMVEX///+/v8QOIDmmpare3d4ZhXvg9P/z+v/29vZVbNZtaXLq6en/7s2t3P3pwINukc6Xtum8glFVs+qtddcwTaF/KDRXtTwxAAAbx0lEQVR42uzdDVujOBSG4cawlJLwUZz//1s33wRKLc4lwdHn3l2nVgvoLO91zgltLxcAAAAAAAAAAAAAAAAAAAAAOEEj2zenlQ2/DQDlVCF8QgRV/EYAFLJIH5dA/E4AFCl+3jZQAgE4nnjbJPjNADij+qECAlDA21NSxH+EIIwAfLnF6PnPchnMhc/oAkiSQAC+1nXZfYnlLEj68DEf5Sjk3gBq3ut442o/dPkXxTjfnOaPoRWcv6hv18/+LGFPYSN6eNz5F9Oy/vQx3t0B6fhD9+ZGP5739+/2re+jP7bWkPZDe6s5N3C8pl0FjquCUjmUlT/mxusAer9l6ktlQkSEz7pFSBjK3e2/PJm8SXyKTOtwMdtq7He7c0WZPQ21u7t2+72mkzrsQNn88Vu/7sqSth3cSVeZ03C85rd0O9qTtK2bu9lon05Q/b48S7X98vz4pg+b7NvOfbQPkW7LfZfFkc2A9aa2uK3r1vyu3BGYfej7FHbs78n3tHkc5ob9Br8B873mcMLt1j0mHlc4TOBYKkXPRc5XH2Z5FDswF0O7KqBqfE9FjuhCjpjYafJwsoHTmcAw97tCxceFLV1iFbPKI5s/5r+xercBZL46Cptw5q7p6r7oA2zyO5nczjo97i2BzBkszAlr06CVlWjt0aRbNn8a+8WQP6Iyruk09qe+SxP35TE8ymxShE3a09+kgn/A4BPM7cJ9GP0jP5E/Y1VJs8+YP+bh9pDqeU/50WfHIareZandgPv+2teJ9vL3GKg2g/TEqYECUui8DcIOnIW5Y2hXEyAR27AdS/ImHkz/Vd2mWOSE88rmzxwE1eQ+q7rKfFRjnj+hflmnho+Yye2h9lWP/dTmTBeKI19CxMLJbFAPGxt60ofY89PWL76GsZ9mt1xlMYYI8NXFoovK6p8mPcptMlZMo0+Fxnds4ZwP3Vg/xhzZnz9+y3P9E3Jo3pM5lsvDcdzq+QdyjzN7Fln9Y7tBlz9ntoT4ReOfdnHNcyVlpfK7/rgCaEwZ9KIA0nn7detMNtS+6vHhkyqgbtGKuWpp3X9t5Y/5rwv7mdJdk8+jqz2ZplQ2mXNsSLt7fXKH+kNVph3pwgmd3xp9/KzyZ32WhrDpsrhw393ffA7U9hjnjqeL7ZJsd5Uby/wxn9Zz/RM2kO3Jbbqp6iY/jtoPe2L+mLia9Fx5aRuHNiIbyfgHJcY/+fDHX4goFxNplz6pABIvCyA1pHrH5URtQ6ZZFD8mMvL5cz6SnufPWbPWzfMfmy52pKH8EMglz6Rdt3W1ndzkdpmysDY7Fd3DKOl5/qRZjf18vqVbGWZD8/ynC/OUrP3yFZOdxYg6DoN8BXJTbnsmATo7WYlza31zJ3zItk/mj876Lz//cRVO2lPbLX40fxx1/IGsyc159HCf49BsRN1TdwgcXP/ks+dwJVAll5cAucbLf3jdgOlFbKhl/RO+IwREdRtTyEyL4dB1UffUc/5cGjG42sblT+Pz5yJspRXmP6OeUn7ZSNqZP3qVPzrlj46na1b/CDc7ybu3Lj/V7Sh7XOZP7Uqo2ufEFKe7fe16nZ3xs54/D/V6/nOZ9zTnj17lj/+B7PxHuSDUgzTljqxtNMo6VkOa/EG5+uePkCl3pDD/tvMAOp8AiVf/VzbP659Vc6ZvQ5fVP+77Xf2jFvkT48rnj7tjuC76L/Pn4L9os8c3YKOrxPbnT2iWqmf911D783nZf82P7lYpFtfK5r6nNzVUffErS6n8MMHV3Mf+8/kzVmGqs57/pD190H9Nef/VypQ/No7IH5yQP63Jn3jtj5R5/thLf+Q8APqL+mfZf6Ub712MBps/zZw/OtYyjtmEKXDsQtdwrdxGV/PnkDlufBP+dJmlB7VdUT2ZP9cfz5/NZ3Uc8NRzz+Mnt3dfW+g0En6c+9pvd/kTrq3RYb3bPnTcd8L7Y2zHsB63qH/S/CfuyV/T82L+7LPzPq/Gm/xxTeWtJ39wfPzk8584+Fn3XyIbQb/sv9b1TzXG/qte5Y//Fps9vv550n9pN/YZ3LK7W38XN584XVh/90tiPrPcV+rKbcAfib7tW0k20ZHW34e0/j7M6+/xpM/X39ODbRtjvln6x5tj9OGQlvT9ee/X3932al/WNX0Xx9j9y+Ns7C4qt+V5/uPX3XVaf497uiyvA6ierL/bA6q26p+eBXiUnf+EK4DEZf0UsHEeAn3yOfGNnwHnU59mvtBOdM/nz4mrkKpw2aG//tCVOun6w8lXXbH/UlWYWNszyS/a71rLadL1hzpdf6jz6w9t4bC6/jDlz7s/633LI8yjpE+XeN2f++Z76r9MksQGaM6fHU1YvEbSr7/3Q5gntd18/WG2px3XH5oqp5/0nD/3NHcmf1CiAHpcf68e19/d6Nk1YGpv9xXWwKd0d1hqzxfDfcs1Xxp9aZb5o8NV1LuFQY/yVwRN2m+5eb+Nn8rkjVsf1E1xMWynMHv2kebrH733CQ/Nqnj97F/24zYuF1PySH8pZZ3qnz5cDQ0cnD8yu9TQVju2+RL5nfPo2f7Db+wH18KLdGL8gwL/z2XPv0h1z3DJ268xtmAjT4EH8JX5s3r+6SAXn4b2a+fVzwDwqQZMfPT6G61PntCAdfy6AHxpAC1fcWzx2X/zM08lr4AI4MvzR33w+qvZC7CyHgLg6A4sb8YatwrCSgiAg1wb+aT64W2YARxdAG1XQKIhfwAcH0DV4/svV8QPgCIBpOTqjXcU6QOgiKspgURce//TClv8EEAAytVAVSXsG51WitYLAAAAAAAAAAAAv9PtH8XfHED+kD8A/lYFAKcgfwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICvUH+INw4DQP4AIH8AgPwB8MPz5woAe5E/AP7F/JH+jyZ9IH8AHJ0/LmyklNQ/AM6tf8gfAOQPAPIHAErkTzZ9Jn8AUP8A+F3505A/AI7Pn4b6BwD9F4DfmD9SPl6BSP4AKFP/ZIMf8gfAGflT8/wvAIXyp+H57wBOrX9U+kD+ADi1/yJ/ABydP82HyB8A5A8A8gcAjs0fRf4AKJE/auO/8AfvvwPgOC/6L35BAMgfAOQPAByRP2p9k/wBcGT+qEXwLD8jfwAUqH/U1iI8+QOgUP/F/AcA+QPgl+WPerz+mV8QgAPzR62HP4r6B8AJ/ddqBZ78AVAgfxTzHwCn1j/kD4Cz80eRPwAK5I9ahI6i/gFQtP5R2yUQ+QOgeP9F/QPgnPxR5A+AkvmjNtow8gfAwfmj6L8AfIf+S/H6YwDK5I9i/gzg3PpnewGe/AFQrP9SrH8BKJk/6mkNRP4AKFb/kD8ATs8f1r8AFMsfxesfAji1/lH0XwCK5o961oGRPwCOzB/F+18A+A79F+tfAIrnz+b4mfwBQP0D4Mfnz+rtv8gfAEfnj+L1DwGcWf8o+i8AZfOH1/8BcHr9s7UORv4AODx/1HYKkT8AytQ/vP4PgML5o5j/ADi7/ml4/3cAZ+SPWmcQ82cAJesf3v8UQOH84f1PAZxe/5A/AE7JH/X4HmDkDwDqHwA/Mn/U87cgJH8AlK5/eP4FgDP7L67/AVAqfxSv/wzgm9Q/5A+Aw/Mnmz9z/TOA8+sfRf4AOCF/FPUPgLL5s/EuGOQPgHL1j2L+A6Bc/qjnz4AnfwCUq3+WZRD5A6BQ/qh1C0b+AChe/5A/AMrlj+L5XwCK549i/QvA9+m/eP0NAMXyR/H+pwC+R/1D/gAokz9qq/fi9ecBUP8A+PH5o3j9eQDfoP5h/QtAifxRz96BmdffAHBC/UP/BaBs/jxWQuQPgPL1D6//jP/ZOxf1VHUtjIJlYXRyt77/qy4SAgISryTUdox+p8tLDdR9GP3nDESAEP4R1n8GgC3zj9D/AYAt6y9h/gsANvIP+QcAgvpHFjIQ6z8DQKD84zoHEf8AAPUXAPx6/3D9KQBsmn+E9X8AIIx/hPN/AOCn5B/8AwDB/SNcfwoAof0jjg4Q/gEA6i8A+JX+EfwDAFvnH7kqxvAPAPj3j7D+GABsmH84/xkANvQP/R8ACOsf5wKs+AcAguSfhY+Bxz8A4NM/cqMDhH8AwH/+Efo/ALBd/YV/AGA7/wjr/wBAYP8I+QcAfkD9Rf8ZAIL7R8g/ABDaP+JeARr/AECo+kvIPwAQ2j9C/xkAts0/rP8DAJv6h89/B4Bg/hHHp1/gHwDYIP8w/wUAofxD/xkAfkD+EfwDAIH8Izca0PgHAELkH1n4BB78AwAh6y/6PwAQ0D/C/BcA/IT8Q/8ZAAL7R6i/ACC0f2Qx+zD/BQDh6y/mvwAgpH+E+S8A2D7/CPNfABDeP0L+AYAt/MP8FwBs4B/h+i8A2Lj+ul6DDP8AQDD/UH8BQGj/CNd/AcAG/hHX2c/4BwCovwDgb/iH698BILB/ZKkEwz8A4Nk/Qv0FAD+h/uL6dwAI7x+u/wKAsP4R5r8AYNP8c33uD+cfAkC4+mskHyH/AEBg/1B/AUBQ/4jzGjD8AwBh84/gHwAI6B9ZlBD+AYBw+UeovwAgnH+E/jMAbJ1/WP8HALasv1j/EABC+0dY/wcAtvAP628AwOb1l/D5XwAQ0D9c/w4AW+cf4fxnANiw/mL+CwC28w/nPwNASP+I8xJU/AMA/vOPsP4zAGxcf001hH8AIKh/yD8AEMo/4j4BEf8AAPkHAH6tf2T5BET8AwDkHwD4A/4Zf/wg/gEAz/4R8g8AbJx/hPOfAWAL/wj5BwC2yz/XE2H4BwA8+4f1VwHgB+SfaRLCPwDg0T/iXPwH/wBAkPwjiycB4R8ACFl/8flfALCVf6i/ACCkhHgLbr05St3RtJPxO/vOOKHHDjc4ANzRzxqH2rqHsO+xQw0Ofx1J4o8jGf91TrxuQO2T8t/LlP1AKmrHOayKz7EDDQ78eY/lA50ZK7/7P2xARcm/txiO4+SwOj7H9j44CoKWRD5xryXxvP/9BpQq3/NPqcsNXcOU6x/FPsf2PjiHHrTEH5raPO+/3UB7DP57E3sUKw9H8cHn2P4HB/hQ/0S+/dOPq+Rd/4jqxvFxFPsc2/vgGAjwz+0NqFX8o1OEeDuKlU9FKK9yA/yDf/znH+Ux/yif+UdF+Afwz0b+UavkHxX5yz/+xg4wOAD+8Z5/wvunHL7wD+Cfv93/UR7rr6WxRxftVasPjn/At3+yc77eBopDN+Z3+nf944gRlZf8U0V51VP6yT/lu2PjH3jEP9lRW6OYuWPskuzcXCurbka3uyeK7/2v8c8hLfQ/eWbuNXIcHnrKP7k7njT7uL+ZnvS35Bn/3PJaPj6fp1EnM7y59YR/qqVs1Uzev5PdVrM/pYJ/4CH/1Lsx33spdnmk+kd77Uh9EZB1Uz3Ry8g/yvpnrCQ9aJTV592x0q9SxXm3K/fmiebB/OXwj31lu4Gi/yWa/peyY2b15Rd50T9NJx6rHOOfvLP1M/Pv+a36KB98oAWRD4f0A1Pk2j9lkqaq+6qckogPuVi9xYv+cc6/V+7abjCl3VLcbiBX+Acezj/Fv/O5GZVPdT7Enuw88VMa2QfKsxXW+AfMUW4esE/vmot/svN3LsW51IbaVUlx1j9d7L7zlfyj565aTSq1j8w/+kb3E99JVt8XkNs/3S+RpaMoWGgjOSKQK0ZU7QvTtFrU0kCi7yWNfrEzRSz5R9tHzJeaeKKJes8Y4dh34eTwz3P5Z+afPmulJ+oveNw/bUHVHsWjkss2cEzUmXRx9J32Mf18G3/qUXQxt4tOT811+0froTCmMbd2nXMqfXd3eMc/auSfSyibZLMuez26gcX8c0jrUfml848JRI4KzH0Yuwslfcw2arhtIpA8U39F+XB3vJFmf/m9VZdLbuWft/wzMbzCP/CIf7KzsYbOJyak7HbxMXX7R/9kW2HZf6790z4am0cGiV38k3bxXNXdU9oSxe5rV62Uf/z5p8la3+RDWGyk7N+U7Kn5L5d/mn1yupRg6Sm/GOORKaqpf8rpRppJ/qnu+Wdpx6uqMjNsyWILOt1H8fB7dGOTf+Ax/7T2mXSA8l5FOx1MTAv5UmDlo+ZycxlhWn9lBz1CPX5NX3+V+3ED2wipfaK2/hv272iJ18k/ertqXH/d3MCif1JTbjWqtjraq1ObffJiSETP5J8yL6/6uIkyR29qOj5p6+hEx59HI8qN/DPu/7Sj9W+Cei7/XNYeWMo/0nRpx/4nlG7n8Q/c948a2sV9Y9n4R9+qD5MprGLX38kO+1H0mOefojGPTAOH0UNh288z/7R+mP50vGSH5/LPrvPnxZCT9s+tDSz2f8ygmW1Ca10eD6/75yoENa11dBHTHrRtfZRH3d2X/VPOx5/1kV6ov8rErR+z66mJQLkyAShPmsXOOf6B6/pL1fP28Sz/9PNkl8P5eB5NmM3mv2xtNpt97/SgiqNuN1v/KOufzkH53A/xW/2fdGg/R1ldprP+840NOM7/0e7J+4qrkTv+cU0jLfvHVi7DQZve9I9j/suZfy5tmVH/OX52/itx6qfr/+id7zQdtSMvnTyAf2DZP7fyj5rOz++arl80ih6THzj05Vg/G56P/WNk8J3P8k+7B9+z9kx8bYeX+j+12RNTFZ6rxzbg8o+dazc1WCPVINeFGXh3/jGl13ITqImGLkp6urjy9G7+aaWQ2uoo7nozWm/xs/1nnYAcyyKOZWPyT1ue0v+BR/vPD9VfxSX96ALEtH9GlZf93v3URSY6dai91UOS2yen/WdTmH3N2sNx/Hj/uXL7x6x8bu6ounlsA675d51/dLY79uf/tI9mL13/teyf9HJ8myau7jGtMv+VmDn4NOpesrf+efb8wzYBuVZlnfrHnEGQLJwAhH/g6fprmMMabtVNZvrFzS3/tK/Vhuq6zo0VUT0MP5l/txnq5fmvTmb15KTI6fxXl3+aN+a/uvrrS6uyP//wO82OQ0P6qeu/FvzTGPnk1hHd+Yen0RnR78x/DRWYGU3nn9RUYk/Mf9krXO/5J+8CW6q7QHmCf+DF/PMV2xJrwT/2xB7dg16svwpbdRXn794tlRSdrsz5hzoSjc8/7FT0sn/aDZVJVtvXO+a/dP8nf9s/JvMUpv/cdCZqj+zsyfyjT0KU6UmI+XCyTG7Sg2qru6TzhnosorRucPV/mt48Q8Iy/ed2S7LS9e+z+kt3u5uFU7fxDywdv3NGLhgVLfXMP9Hd+quVjG3ztHGo6kynr7pIo+n1F/mkP/S8f6LsuNsd88jpnzWuv1hx/Q39VuTrXyJ6K/+8O/jovUu5/hRW9M/08oqdOU1wb1vGw+xWsRvVR2rmn9n81+hxe23XfuXdnvtHrfq++F9/tXpDP+4pKvf81/uDV/lAhX/Aa/65SzZc5TVKGUv+WXcFjl+x/sbbi3C480/ar8CRr55/WP8Hfo5/1k0df9A/XpYorEY1Uol/4Jf7J8I/P2f9w5VWYGX9Q8A/5B/Wnwf8g3/wD/4B/PNx/uHzB/EP4B/yD/kH8M8H+YfPP+XzTwH/bOQfFVF/eRwcIJFP3GtJPO+/3cD79VfZ/aVXUq5/EPscO8jg8OdR8QcKSGLld/+HDSiJ3/NP3MeIeP2j2OfYIQYHiFQSfxyJ8rz/wwZUO/xb+km6Rqs+jlcOEqXHsQMNDgA37awkib9eJk5sofHmOKHHDjQ4ANwV0OvIMM/83jihxw41OPx10pskvEHdQfjS11rjhB5bBR4c8A/+AQD8AwD4B/8AwKb+2QMAPMrL/lEL/8M/AODZP8oq6Iv8AwBb5J/06wv/AMA2/iH/AAD+AQD8g38AILR/VMr8FwCQfwDgl/tH4R8AIP8AwB/2j8I/ABDaP2ZpuvHVGPgHAILlH64/BYDQ/lH4BwDIPwDwB/0j6ewW5x/+cBRvAZB/ILQq1MI9ZAQf6R91k2T5/+d8f/z7mu/gY2Zaef9RG/wA/8Afr7j4U8L3+38e8Q8AfGb+kdkt/AMAXv0jE/FMbvP5OwDgj2Xv4B8ACOofdV2L4R8ACOcfIf8A/G/vDo7biIEgigbQ+efrk0siF1D5YPSgqPdOUgK/ZsBdLIPzT/QHqPQniyPov//oD9Cdf+xfwER/4vwZGOhPzD9AuT/Z/gSmP8Dx+SfOf4DJ/es5BOkPUOmP9y+A0fnn25NA0R/gbH/i+R9gdP6J/gCT+1e8fwGU+xP7FzA8/zxapD9Aoz/vy5f3v4Dy/GP/Aor9yfYRRP0BzD/AB/cnq3No/QGK88/LVaz6AxzuT9w/Blww/+gPUOtPfrgCSH+A2vwT738B/f7E/c9Avz/ePwXm9y/9AWb68/gEs/4AJ/uTxQoW8w/Q37/c/wNM9cf5D9Dvj+9/ARP9WRz/OH8Gjvcn+xlIf4DK/uX8B9Af4Nf1J+/HP/oDnO5Pdu+A6Q9Q3L88fwjU+hPnP8Ad88/LLfT6A3T64/55YKI/WWZIf4DD/Ynnn4HZ/cv5MzDfn3j/FCj0J86fgdH5J54/BK7Yv/QHKPXH97+A8fknzp+Byf3L84dAqT/ZXz+vP0B3/tEfoNif3TNA+gO05x/nz0C3P55/BobnH79/Aa3+ZP8Iov4AtfnH/T/A5P71LUX6A1T6s/gRXn+A0/2J5w+B+f3L/T9ArT/ZH//oD9CYf5bfgNcfoLh/OX8Gmv1x/yFww/zz8iu8/gDl/cv8A1T6k9X5c/QHMP8Av6g/7t8Aev2J90+B8fnH/RtAvz9ZZUh/gJP9ifNnYH7/etzEqj/A6f7E+TMwO//Yv4CR/sT5MzA5//j9Haj2J/YvYH7++cqR+1eBUn/i++/A/PyjP0CrP9ksX/oDTM0/7l8FCv3x/VNgcv6J+8eAwf3r/QJo/QFa/bF/Ad3+eP4ZmJx/4vuDwBX7l+d/gG5/vH8BlPsT58/A4PyT9TmQ/gCd/eu5h+kPUOlP7F/A9PyjP0CpP9mvYPoDnJ9/8rwF0fOHgP0L0B+A/9yfrC/f0B/A/AN8dH/WM5D+AM35J+YfoNSf2L+AS+Yf9/8Azf5k9f6X5w+B5vwT+xcwuH/5/hfQ6k/2J0D6A5yff+L3L2By/4r+AEP98f0voN2feP4HuGD+sX8B5f7E9weB4fnH97+AYn/i+1/ADfOP/QvQH+B39CeLb+/oDzA2/3j+EDjdn7h/Fbhs/tEfQH+AT+7PywF03P8DmH+Az+5P9Ae4bP7x+zvQ6U/cPw/MzT9f587uHwNK/YnzH2B2/tEf4I7+RH+Aw/2J738BF8w/7/dw6A8wsX/pD1Doj9+/gMn5J6tL6PUH6O1fMf8AA/2J9y+Abn+yefhHf4DG/BPvvwOT+5ffv4C5/kR/gIH+ZPGn/gBH+7P+/pfnf4Dq/uX8B2j3J/oDTM8/0R+g35/H+bPnf4DT/fH9L+CG/estR/oDHO9P1iuY/gDN+cf+BegP8PH9yX4F0x+gPf/4/gVg/wI+vj/x+zswOP/E9y+Acn/i/jFgeP5x/xgw3x/zD9Cr0OZvAAAAAAAAAAAAAAAAAAAAAAAAAIB/9QfshRjshAQ/PAAAAABJRU5ErkJggg==" width="1151" height="534" class="img_ev3q"></p><p><a href="http://tools.kuizuo.cn/" target="_blank" rel="noopener noreferrer">在线工具地址</a></p><p>之前学习的时候，都会看到网络上一些在线工具的网站，比如获取时间戳，编码转化，正则表达式等等，这些对于一些初学者在电脑上没有安装相对应的工具，往往就会百度搜索在线工具，然后就能实现自己所要完成的目的。</p><p>这些工具很是方便，或多或少都会用到。但一些在线工具并不能满足我日常开发中的个别需求，于是乎我也准备自己写一个这样的在线工具网站。不过这里肯定不会像其他网站那种搞得花里胡哨的，同时也不会去重复的造轮子，这样很没有意义。</p><p>顺便也记录下这类工具的编写以及用途</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="技术栈">技术栈<a class="hash-link" href="#技术栈" title="标题的直接链接">​</a></h2><p>有一段时间没怎么写 React 了，同时对 mui 组件库感兴趣，于是这次的使用 React 和 material 设计风格的组件库来进行编写，使用到 create-react-app 脚手架进行开发，同时使用 TypeScript 进行编写。</p><p>该纯前端，无任何后端交互部分。</p><p>不做代码分析与演示，可自行在网站上测试与 clone 源码进行查看。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="功能">功能<a class="hash-link" href="#功能" title="标题的直接链接">​</a></h2><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="查询字符串与-json-转化">查询字符串与 json 转化<a class="hash-link" href="#查询字符串与-json-转化" title="标题的直接链接">​</a></h3><p>如果是在协议复现的话，有些包的请求体是通过查询字符串来拼接的，也就是协议头<code>Content-Type：application/x-www-form-urlencoded</code>，请求体如 <code>username=kuizuo&amp;password=a123456</code>，一般情况下都不会采取字符串来进行替换，而是转成 json 格式，如 <code>{ "username":"kuizuo","password","a123456"}</code> 然后使用一些库（querystring）将 json 转成查询字符串的形式。</p><p>但是编写代码的时候，<strong>需要把抓包得到的查询字符串转成 json</strong>，而这也就是这部分的主要功能。</p><p>不过 js 本身是不支持 gbk 编码的，遇到使用 gbk 进行 url 编码的网站就需要自定义先将原文本进行 gbk 编码或解码然后才进行转化操作。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="cookie-与-json-转化">Cookie 与 json 转化<a class="hash-link" href="#cookie-与-json-转化" title="标题的直接链接">​</a></h3><p>和查询字符串与 json 转化功能类似，只不过是将 cookie 文本与 json 互转。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="url-utf8-与-gbk-编码">URL UTF8 与 GBK 编码<a class="hash-link" href="#url-utf8-与-gbk-编码" title="标题的直接链接">​</a></h3><p>有些国内网站上可能会使用 GBK 编码，但大多数语言默认都是 UTF8 编码，如果编码格式错误，后端接收到的请求必定失败。在这里我是使用到<a href="https://www.npmjs.com/package/gbk-nice" target="_blank" rel="noopener noreferrer">gbk-nice</a>这个库，可以达到 gbk 版的<code>encodeURIComponent</code>与<code>decodeURIComponent</code>，与 js 自带的<code>encodeURIComponent</code>和<code>decodeURIComponent</code>也就是 gbk 与 utf-8 编码的区别。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="网站实现">网站实现<a class="hash-link" href="#网站实现" title="标题的直接链接">​</a></h2><p>上面所介绍的都是作为一个工具库的功能，我只是将其封装成一个在线工具使用，并非主要重点。而主要是对一些网站的功能实现，例如复制与下载等等。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="react-codemirror">react-codemirror<a class="hash-link" href="#react-codemirror" title="标题的直接链接">​</a></h3><p>在网页上展示代码，并有代码高亮的功能，首选的组件就是 codemirror 了，也是很多在线工具都使用的，我这里也不例外。</p><p><a href="https://uiwjs.github.io/react-codemirror/" target="_blank" rel="noopener noreferrer">React CodeMirror</a></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="复制">复制<a class="hash-link" href="#复制" title="标题的直接链接">​</a></h3><p>复制的话其实是可以使用 npm 包的，但是之前在写其他项目的时候，看到封装过一个 copyToClipboard 的功能，这里也就是将其拷贝置 utils 下供外部使用。</p><div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">interface</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">Options</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  target</span><span class="token operator" style="color:rgb(0, 0, 0)">?</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> HTMLElement</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">copyTextToClipboard</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">input</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(0, 112, 193)">string</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> target </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> document</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">body </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> Options </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> element </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> document</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">createElement</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'textarea'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> previouslyFocusedElement </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> document</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">activeElement</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  element</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">value </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> input</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  element</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">setAttribute</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'readonly'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">''</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">element</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">style </span><span class="token keyword" style="color:rgb(0, 0, 255)">as</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(0, 112, 193)">any</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">contain </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'strict'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  element</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">style</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">position </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'absolute'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  element</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">style</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">left </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'-9999px'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  element</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">style</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">fontSize </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'12pt'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> selection </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> document</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">getSelection</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> originalRange</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">selection </span><span class="token operator" style="color:rgb(0, 0, 0)">&amp;&amp;</span><span class="token plain"> selection</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">rangeCount </span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    originalRange </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> selection</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">getRangeAt</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  target</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">append</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">element</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  element</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">select</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  element</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">selectionStart </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  element</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">selectionEnd </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> input</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">length</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> isSuccess </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">try</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    isSuccess </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> document</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">execCommand</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'copy'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">e</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(0, 112, 193)">any</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">throw</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">Error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">e</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  element</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">remove</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">originalRange </span><span class="token operator" style="color:rgb(0, 0, 0)">&amp;&amp;</span><span class="token plain"> selection</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    selection</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">removeAllRanges</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    selection</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">addRange</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">originalRange</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">previouslyFocusedElement</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">previouslyFocusedElement </span><span class="token keyword" style="color:rgb(0, 0, 255)">as</span><span class="token plain"> HTMLElement</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">focus</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> isSuccess</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>主要使用浏览器中的<code>document.execCommand('copy')</code></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="下载">下载<a class="hash-link" href="#下载" title="标题的直接链接">​</a></h3><p>在需要这个需求的时候，我一开始是懵的，因为之前我是没有写过原生的浏览器下载事件，都是使用外有已经封装好的的接口直接调用即可，于是这次我也是毫不意外的通过搜索引擎找到了个复制的代码</p><div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">type</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">BlobPart</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> BufferSource </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> Blob </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(0, 112, 193)">string</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">downloadByData</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">data</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> BlobPart</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> filename</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(0, 112, 193)">string</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> mime</span><span class="token operator" style="color:rgb(0, 0, 0)">?</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(0, 112, 193)">string</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> bom</span><span class="token operator" style="color:rgb(0, 0, 0)">?</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> BlobPart</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> blobData </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">typeof</span><span class="token plain"> bom </span><span class="token operator" style="color:rgb(0, 0, 0)">!==</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'undefined'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">?</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">bom</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> blob </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">Blob</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">blobData</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> type</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> mime </span><span class="token operator" style="color:rgb(0, 0, 0)">||</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'application/octet-stream'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> blobURL </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> window</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token constant" style="color:rgb(129, 31, 63)">URL</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">createObjectURL</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">blob</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> tempLink </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> document</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">createElement</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'a'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  tempLink</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">style</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">display </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'none'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  tempLink</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">href </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> blobURL</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  tempLink</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">setAttribute</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'download'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> filename</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">typeof</span><span class="token plain"> tempLink</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">download </span><span class="token operator" style="color:rgb(0, 0, 0)">===</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'undefined'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    tempLink</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">setAttribute</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'target'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'_blank'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  document</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">body</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">appendChild</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">tempLink</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  tempLink</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">click</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  document</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">body</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">removeChild</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">tempLink</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  window</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token constant" style="color:rgb(129, 31, 63)">URL</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">revokeObjectURL</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">blobURL</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>原理的话是创建<a href="https://developer.mozilla.org/zh-CN/docs/Web/API/Blob" target="_blank" rel="noopener noreferrer">Blob</a>对象（类文件对象），将数据写入，然后创建一个 a 标签（隐藏任何样式），然后并点击创建后的 a 标签，最终移除 a 标签，已达到类似点击下载按钮来下载文件的目的。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="主题切换">主题切换<a class="hash-link" href="#主题切换" title="标题的直接链接">​</a></h3><p>我一开始实现这个功能是想使用自定义 hooks 的，但是在我编写的过程中，发现切换主题的组件与 codemirror 展示的组件，并不属于在一个组件内。也就是说，我如果写了个 useTheme（实际上我也真写了），我相当于在这两个组件内都使用了独立的状态，互不影响，也就是我点击了切换主题的按钮，但影响不到展示组件的代码。也算是加深了我对 hooks 的理解。</p><p>然后我就在想 Vue 的话是如何实现主题切换的，然后翻看了一些 vue 相关的代码，不出所料，使用到全局状态管理，也就是 Store。react 状态管理有 redux，还有官方提供的 useReducer，但我感觉都太繁琐了，于是我另寻其路。</p><p>我博客不是就是用 React 写的吗，我直接看源码是如何实现的，发现使用到了 React 的 useContext，也就是接下来我所要写的。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="usecontext">useContext<a class="hash-link" href="#usecontext" title="标题的直接链接">​</a></h4><p>首先要明确的是，theme 的状态应该是放在全局配置或者说最顶层的组件（当做父组件），然后子组件接收父组件的相关数据进行重新渲染组件。如果只是父子两层之间的关系还相对简单些，直接通过 props 传参即可，但是对于大部分组件关系，基本都是祖孙级别的关系，所以也就有了 Context。</p><p>并且 <a href="https://react.docschina.org/docs/context.html#reactcreatecontext" target="_blank" rel="noopener noreferrer">官方文档</a> 中也是用主题切换作为 context 作为演示例子。而对于应用程序中许多组件都需要的属性，Context 无法是一个很好的选择。</p><p>首先我创建了一个 Context</p><div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-tsx codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token imports"> createContext </span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'react'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> </span><span class="token maybe-class-name">ThemeContext</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token generic-function function" style="color:rgb(0, 0, 255)">createContext</span><span class="token generic-function generic class-name operator" style="color:rgb(0, 0, 0)">&lt;</span><span class="token generic-function generic class-name builtin" style="color:rgb(0, 112, 193)">any</span><span class="token generic-function generic class-name operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>然后在顶层组件中使用（Demo 仅作为演示），其中 value 需要是需要传入给子孙组件所要使用的状态或函数，比方这里 theme 和 toggleTheme。</p><div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-tsx codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token imports"> </span><span class="token imports maybe-class-name">ThemeContext</span><span class="token imports"> </span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'../contexts/theme-context'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag class-name" style="color:rgb(38, 127, 153)">ThemeContext.Provider</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">value</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:rgb(4, 81, 165)">=</span><span class="token tag script language-javascript punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token tag script language-javascript punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token tag script language-javascript" style="color:rgb(128, 0, 0)"> theme</span><span class="token tag script language-javascript punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token tag script language-javascript" style="color:rgb(128, 0, 0)"> toggleTheme </span><span class="token tag script language-javascript punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token tag script language-javascript punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain-text">  </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag class-name" style="color:rgb(38, 127, 153)">Demo</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag class-name" style="color:rgb(38, 127, 153)">Demo</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain-text"></span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag class-name" style="color:rgb(38, 127, 153)">ThemeContext.Provider</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>在子孙组件的话就可以使用 <code>useContext(ThemeContext)</code> 来获取父级传入的数据，在这里也就是 <code>{ theme, toggleTheme }</code></p><div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-tsx codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token imports"> </span><span class="token imports maybe-class-name">ThemeContext</span><span class="token imports"> </span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'../contexts/theme-context'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">default</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">SwitchTheme</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> theme</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> toggleTheme </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">useContext</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token maybe-class-name">ThemeContext</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token comment" style="color:rgb(0, 128, 0)">// ...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>接着就是切换主题的按钮点击，然后更改 theme，就会渲染对应的组件，至此切换主题的功能也就完成了</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="keep-alive">keep-alive<a class="hash-link" href="#keep-alive" title="标题的直接链接">​</a></h2><p>在使用 mui 的 Tabs 组件库时，来回切换 Tab 会导致上一个页面的组件重新渲染，状态返回初始状态。这肯定不是我所希望的，由于我之前又有接触过 Vue，所以自然而然就联想到 keep-alive，然后我就去搜索 react 的 keep-alive 解决方案，找到了个<a href="https://github.com/CJY0208/react-activation" target="_blank" rel="noopener noreferrer">react-activation</a>，并解决了的需求。</p><p>想做到的目的就是能把 Demo 组件缓存起来，像下面这样的写法</p><div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-tsx codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag class-name" style="color:rgb(38, 127, 153)">KeepAlive</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain-text">  </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag class-name" style="color:rgb(38, 127, 153)">Demo</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag class-name" style="color:rgb(38, 127, 153)">Demo</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain-text"></span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag class-name" style="color:rgb(38, 127, 153)">KeepAlive</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>由于我使用的是 React17+，所以需要使用放置<code>&lt;AliveScope&gt;</code>外层，也就是上面的代码要改写成</p><div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-tsx codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag class-name" style="color:rgb(38, 127, 153)">AliveScope</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain-text">  </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag class-name" style="color:rgb(38, 127, 153)">KeepAlive</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain-text">    </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag class-name" style="color:rgb(38, 127, 153)">Demo</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag class-name" style="color:rgb(38, 127, 153)">Demo</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain-text">  </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag class-name" style="color:rgb(38, 127, 153)">KeepAlive</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain-text"></span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag class-name" style="color:rgb(38, 127, 153)">AliveScope</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>不过要注意: 当与<code>react-router</code>或<code>react-redux</code>一起使用时，你需要将<code>&lt;AliveScope&gt;</code>放在<code>&lt;Router&gt;</code>或<code>&lt;Provider&gt;</code>内</p><p>这些在官方文档中也有介绍，这里就不细说了。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="webpack5-配置-node-相关库">Webpack5 配置 Node 相关库<a class="hash-link" href="#webpack5-配置-node-相关库" title="标题的直接链接">​</a></h2><p>由于使用的 create-react-app，就使用到了 Webpack5，但是 Webpack5 是不支持 Node 自带的一些库，例如我所需要使用到的 Buffer，所以就需要 npm run eject 把 webpack 配置暴露出来。</p><p>如果是要配置 Node 相关库是有一个插件 <a href="https://www.npmjs.com/package/node-polyfill-webpack-plugin" target="_blank" rel="noopener noreferrer">NodePolyfillPlugin</a>，将会把 Node 的系统库的函数注册到 webpack 中供前端使用，相对简单，而且方便。但相对打包体积肯定有所提升，这里只是提提。</p><p>在 webpack5 官方有个测试 <a href="https://webpack.docschina.org/migrate/5/#test-webpack-5-compatibility" target="_blank" rel="noopener noreferrer">兼容性</a> 的，就有提到 <code>Buffer: false</code></p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">module</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">exports</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token comment" style="color:rgb(0, 128, 0)">// ...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">node</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">Buffer</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">process</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>要解决 Buffer 也比较简单，直接通过如下代码即可</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">module</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">exports</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token comment" style="color:rgb(0, 128, 0)">// ...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">plugins</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token spread operator" style="color:rgb(0, 0, 0)">...</span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">webpack</span><span class="token class-name punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token class-name" style="color:rgb(38, 127, 153)">ProvidePlugin</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">Buffer</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'buffer'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'Buffer'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>也有可能需要在 resolve 中设置下 fallback</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token literal-property property">resolve</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">fallback</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">buffer</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> require</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">resolve</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'buffer'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="总结">总结<a class="hash-link" href="#总结" title="标题的直接链接">​</a></h2><p>实际编写过程其实并不轻松，但是好在很多坑与开发难点都有前人的遇到，所以搜索就已经帮我解决了很多问题。不过这期间也是不断的尝试，编译，最终实现结果是符合我一开始的期望的。</p><p>不过目前所编写的几个功能主要为我目前写协议复现所需要的，而对于大部分像时间戳，正则，加解密相关这些外面都有现成的，何必又要花费时间去造轮子呢。</p><p>后续的话应该还是会添加一些额外的功能，例如搞个代码框的配置页面，可供选择语言，代码框的高度，可视化表格的增删改。同时对代码进行一定的重构，对一些组件复用，已经完善持久化的配置。</p><p>最主要还是希望能成为我日常开发中常用的在线工具类，而不是简简单单 Demo 学习。</p>]]></content:encoded>
            <category>project</category>
            <category>react</category>
            <category>tool</category>
        </item>
        <item>
            <title><![CDATA[HTTP请求配置客户端SSL证书]]></title>
            <link>https://kuizuo.cn/http-config-client-ssl-certificate</link>
            <guid>http-config-client-ssl-certificate</guid>
            <pubDate>Thu, 17 Feb 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[在学习安卓逆向的时候，遇到一个 APP，服务端检测请求的 SSL 证书，需要提交 SSL 证书上去才能正常发送请求。而在开启抓包和协议复现的时候，请求是能正常发出去，但是服务器会返回 400 错误。于是便有了这篇文章来记录下。]]></description>
            <content:encoded><![CDATA[<p>在学习安卓逆向的时候，遇到一个 APP，服务端检测请求的 SSL 证书，需要提交 SSL 证书上去才能正常发送请求。而在开启抓包和协议复现的时候，请求是能正常发出去，但是服务器会返回 400 错误。于是便有了这篇文章来记录下。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="说明">说明<a class="hash-link" href="#说明" title="标题的直接链接">​</a></h2><p>由于是服务端效验客户端发送的证书，所以使用代理服务器（FD，Charles 等）抓包是会替换本地证书，当服务器效验客户端发送的证书与服务器内的证书不一致，那么就直接返回 400 错误，实际上请求还是能够发送出去，只是被服务器给拒绝了。俗称<strong>双向认证</strong></p><p>所以解决办法就是在请求的时候，将正确的证书也一同发送过去，这样服务端效验时就会将正常的响应结果返回给客户端，也就是<strong>配置自定义证书</strong>。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="例子">例子<a class="hash-link" href="#例子" title="标题的直接链接">​</a></h3><p>APP 例子：隐约</p><p>具体如何拉取证书，就是安卓逆向相关的部分了，这里我也只提供证书文件，不提供 app。</p><p>贴上下载地址及密码</p><p>证书: <a href="https://img.kuizuo.cn/cert.p12" target="_blank" rel="noopener noreferrer">https://img.kuizuo.cn/cert.p12</a></p><p>密码: <code>xinghekeji888.x</code></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="证书转化">证书转化<a class="hash-link" href="#证书转化" title="标题的直接链接">​</a></h3><p><a href="https://myssl.com/cert_convert.html" target="_blank" rel="noopener noreferrer">证书格式转换 (myssl.com)</a></p><p><a href="https://www.ssleye.com/ssltool/jks_pkcs12.html" target="_blank" rel="noopener noreferrer">SSL 在线工具-在线证书格式转换-证书在线合并-p12、pfx、jks 证书在线合成解析-SSLeye 官网</a></p><p>也可使用 OpenSSL 工具来进行转化证书</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="http-发送请求">HTTP 发送请求<a class="hash-link" href="#http-发送请求" title="标题的直接链接">​</a></h2><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="node-的-axios">node 的 axios<a class="hash-link" href="#node-的-axios" title="标题的直接链接">​</a></h3><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> axios </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">require</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'axios'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token keyword module" style="color:rgb(0, 0, 255)">default</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> fs </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">require</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'fs'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> https </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">require</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'https'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">axios</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">post</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string string" style="color:rgb(163, 21, 21)">https://app.yyueapp.com/api/passLogin</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">mobile</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'15212345678'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">password</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'a123456'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">httpsAgent</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">https</span><span class="token class-name punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token class-name" style="color:rgb(38, 127, 153)">Agent</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token literal-property property">cert</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> fs</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">readFileSync</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'./cert.cer'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token literal-property property">key</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> fs</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">readFileSync</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'./cert.key'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token comment" style="color:rgb(0, 128, 0)">// pfx: fs.readFileSync('./cert.p12'),</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token comment" style="color:rgb(0, 128, 0)">// passphrase: 'xinghekeji888.x,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">then</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">catch</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">response</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>如果没有配置 httpsAgent，也就是没有配置证书，那么返回 400 错误 <code>400 No required SSL certificate was sent</code>。</p><p>配置成功将会得到正确的响应结果</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">code</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">998</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">msg</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'系统维护中...'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">data</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token keyword null nil" style="color:rgb(0, 0, 255)">null</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="python-的-requests">python 的 requests<a class="hash-link" href="#python-的-requests" title="标题的直接链接">​</a></h3><p>requests 不支持 p12 格式的证书，所以需要使用其他的证书格式，如下</p><div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> requests</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">r </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> requests</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">post</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'https://app.yyueapp.com/api/passLogin'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> data</span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token string" style="color:rgb(163, 21, 21)">'mobile'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'15212345678'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'password'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'a123456'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> cert</span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'./cert.cer'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'./cert.key'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">print</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">r</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">status_code</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">print</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">r</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">text</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>]]></content:encoded>
            <category>http</category>
            <category>ssl</category>
        </item>
        <item>
            <title><![CDATA[记一次Github提交PR过程]]></title>
            <link>https://kuizuo.cn/github-pr-experience</link>
            <guid>github-pr-experience</guid>
            <pubDate>Tue, 25 Jan 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[故事起因]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="故事起因">故事起因<a class="hash-link" href="#故事起因" title="标题的直接链接">​</a></h2><p>博客正准备写一个项目展示的功能，其中 Docusaurus 中的<a href="https://docusaurus.io/zh-CN/showcase" target="_blank" rel="noopener noreferrer">案例展示</a>就很适合改写成项目展示页面，然后无意间刷到我当时搭建博客所参考的博主<a href="https://zxuqian.cn/" target="_blank" rel="noopener noreferrer">峰华</a>的博客也在展示页面。</p><p><img loading="lazy" src="https://img.kuizuo.cn/20220124214558.png" alt="image-20220124214558772" class="img_ev3q"></p><p>于是脑海中就想：要不然提交一下我的博客试试看？然后便有了下文的故事</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="故事过程">故事过程<a class="hash-link" href="#故事过程" title="标题的直接链接">​</a></h2><p>当时具体提交的<a href="https://github.com/facebook/docusaurus/pull/6458" target="_blank" rel="noopener noreferrer">Pull requests</a></p><p>展示页面中有个很明显的按钮 Please add your site，点击后就跳转到 Github 的编辑页面了，不过浏览器不方便操作代码，所以我就 clone 了项目，根据提示，修改了两份代码（一个是添加背景图片，一个是添加博客的 json 数据）提交了 PR（Pull requests）。</p><p><img loading="lazy" src="https://img.kuizuo.cn/20220124215841.png" alt="image-20220124215841410" class="img_ev3q"></p><p>一开始我是怀着尝试的态度去提交的，所以我不小心将代码格式化（也就是第 10 行 sortBy 两边的空格，原本代码风格是没有的），直到我已经提交上去的时候才发现 😂，甚至提交的时候我连 <em>description</em> 都没写（所以我当时真是怀着尝试的态度去提交的）。虽然这是我第二次提交 PR，但也告诉我以后 commit 提交，一定一定一定要比对前后代码变动的地方，不然就会像上面这样。</p><p>提交完之后，很快就有机器人给我回复</p><p><img loading="lazy" src="https://img.kuizuo.cn/20220124220731.png" alt="image-20220124220731250" class="img_ev3q"></p><p>大致的意思：首先很感谢你为社区提交请求，但是呢，为了合并你的代码，我们必须要贡献者签署我们的贡献者许可协议</p><p>很显然我并没有签署过，于是它就把解决方案也告诉了我，叫我访问<a href="https://code.facebook.com/cla%EF%BC%8C%E5%8E%BB%E7%AD%BE%E7%BD%B2CLA%E7%AD%BE%E5%90%8D%EF%BC%88%E8%B4%A1%E7%8C%AE%E8%80%85%E8%AE%B8%E5%8F%AF%E5%8D%8F%E8%AE%AE%EF%BC%89%EF%BC%8C%E5%83%8F%E4%B8%8B%E9%9D%A2%E8%BF%99%E6%A0%B7%EF%BC%8C%E7%82%B9%E5%87%BBSubmit%E5%B0%B1%E5%8F%AF%E4%BB%A5%E6%8F%90%E4%BA%A4%E3%80%82" target="_blank" rel="noopener noreferrer">https://code.facebook.com/cla，去签署CLA签名（贡献者许可协议），像下面这样，点击Submit就可以提交。</a></p><p><img loading="lazy" src="https://img.kuizuo.cn/20220124221203.png" alt="image-20220124221203894" class="img_ev3q"></p><p>当时我看签署完毕后，返回 PR 页面还是提交要签署，所以我打算关掉这个 pr，准备重新提交一个新的 PR。（这种做法是真的愚蠢，尤其是在一个大型的开源项目）</p><p>就正当我关闭 pr 的时候，这时 Reviewers（审核人）给我回复了一条信息</p><p><img loading="lazy" src="https://img.kuizuo.cn/20220124221555.png" alt="image-20220124221555614" class="img_ev3q"></p><blockquote><p>Hey, please don't close your PR if just because of the CLA. The bot will update your status soon after you signed it.</p></blockquote><p>意思就是：请不要在签署 CLA 签名前关闭 PR，机器人会自动在你签署后自动为你更改状态</p><p>然后我就灰溜溜的重新开放 PR，那时候感觉我是真小白，太尴尬了 😅。</p><p>然后等待了差不多有半个小时左右，机器人给了回复</p><p><img loading="lazy" src="https://img.kuizuo.cn/20220124222432.png" alt="image-20220124222432479" class="img_ev3q"></p><blockquote><p>Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Meta Open Source project. Thanks!</p></blockquote><p>意思：感谢您签署我们的贡献者许可协议。我们现在可以接受您的代码为这个(和任何)元开放源码项目。谢谢!</p><p>然后审核人为我的错误 commit 标题进行了修改<del>docs: Add Kuizuo's Personal Website to showcase page</del> docs: add Kuizuo's Personal Website to showcase，<strong>第一个单词 Add 不应该首字母大写</strong>，不符合规范。</p><p>然后为我提交的代码做了一些小调整 minor tweaks，也就是上面所提到的 sortBy 空格，然后为我提供的展示图裁剪成标准尺寸。</p><p><img loading="lazy" src="https://img.kuizuo.cn/20220124222739.png" alt="image-20220124222739483" class="img_ev3q"></p><p>审核人批准了我这两项修改，然后等待系统审核，具体审核的图我当时没截，现在没显示了，把已提交后的代码重新部署到 preview(预览)下，整个过程大约 5 分钟这样，接着审核人对我回复了一句 Great site, thanks! (很好的网站,谢谢)，然后这个 PR 状态就变成了 merged(合并)状态。</p><p>然后我犹豫了几分钟，不知道该怎么回复了，加上我英文表达不行，所以我原本中文是</p><p>谢谢,希望 Docusaurus 做的更好,一起努力 用软件翻译后 Thank you, Hope Docusaurus can do better. Let's go</p><p><img loading="lazy" src="https://img.kuizuo.cn/20220124222926.png" alt="image-20220124222926032" class="img_ev3q"></p><p>虽然才过去两个小时，但是我现在回想起来都感觉贼丢人。</p><p>首先，我这个回复不是指定为他回复，而是相当于全体评论，贼不礼貌，然后这个蹩脚的英文翻译，我真像把 Let‘s go 改成 Let's work together，就算改了，感觉这个回复也太不礼貌了，这就已经不是英文表达能力，而是中文的表达能力了。</p><p>总之最后的结果是好的，我提交的 PR 已经成功合并到了 main 分支上，并且在下一个发布的版本中，案例展示中将会有我的博客显示在上面，现在访问<a href="https://deploy-preview-6458--docusaurus-2.netlify.app/showcase/?name=kuizuo" target="_blank" rel="noopener noreferrer">preview 网站</a>，搜索 kuizuo 也能看到（B 格瞬间就上来了）</p><p><img loading="lazy" src="https://img.kuizuo.cn/20220124223506.png" alt="image-20220124223506489" class="img_ev3q"></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="事后思考">事后思考<a class="hash-link" href="#事后思考" title="标题的直接链接">​</a></h2><p>整个过程下来，审核员给我的印象太好了，我这小白式的 PR，现在回看下来都感觉太丢人了。然后我一看审核员的<a href="https://github.com/Josh-Cena" target="_blank" rel="noopener noreferrer">Github 账号</a>，好家伙，竟然是一名在中国上海的高中生！还是团队的核心人员！太牛了！</p><p><img loading="lazy" src="https://img.kuizuo.cn/20220124225625.png" alt="image-20220124225625869" class="img_ev3q"></p><p><img loading="lazy" src="https://img.kuizuo.cn/20220124225830.png" alt="image-20220124225830338" class="img_ev3q"></p><p><img loading="lazy" src="https://img.kuizuo.cn/20220124231207.png" alt="image-20220124231207662" class="img_ev3q"></p><p>很难想象的到一位高中生竟能为默默的为开源项目做出贡献，而我的这次 PR 能提交成功，也与这位热心的国内学生有很大关系。（再次对我一开始报着尝试提交 PR 的态度表示抱歉）</p><p>但又回到我这边，这次提交 PR 的经过也让我学到了很多，commit 时一定要仔细对比更改前后的代码，提交的 commit 标题的规范，不必要的 closed，以及最重要的开源精神，让我看到一个实实在在开源者的样子，也是我梦寐以求的样子。</p><p>最后也祝 Docusaurus 能越做越好，也感谢这些默默为开源做出贡献的人们，正因为有你们世界才会变得更好。</p>]]></content:encoded>
            <category>随笔</category>
            <category>github</category>
            <category>blog</category>
        </item>
        <item>
            <title><![CDATA[JavaScript中的二进制数据]]></title>
            <link>https://kuizuo.cn/js-binary-data</link>
            <guid>js-binary-data</guid>
            <pubDate>Mon, 24 Jan 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[在我编写 js 代码中，关于处理二进制数据了解甚少，好像都是用数组表示，但是成员又很模糊。尤其是在遇到一些 http 的 post 请求或 websocket，发送二进制数据（字节）时，还有一些算法的翻译，数据的转化，协议的复现，都需要不断的从网络上查阅，并未系统的从文档教程中入手。于是写这篇的目的就是为了加固对二进制数据的理解，以及 JavaScript 中如何操作二进制数据的。]]></description>
            <content:encoded><![CDATA[<p>在我编写 js 代码中，关于处理二进制数据了解甚少，好像都是用数组表示，但是成员又很模糊。尤其是在遇到一些 http 的 post 请求或 websocket，发送二进制数据（字节）时，还有一些算法的翻译，数据的转化，协议的复现，都需要不断的从网络上查阅，并未系统的从文档教程中入手。于是写这篇的目的就是为了加固对二进制数据的理解，以及 JavaScript 中如何操作二进制数据的。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="arraybuffer">ArrayBuffer<a class="hash-link" href="#arraybuffer" title="标题的直接链接">​</a></h2><p>其他语言 java，易所表示的是字节数组，字节集，而在 js 中则称二进制数组（都是用来表示二进制数据的），要注意的是这里的二进制数组并不是真正的数组，而是类似数组的对象。（后文会提到）</p><p>存储二进制数据用到的就是<code>ArrayBuffer</code>，但 <code>ArrayBuffer</code>不能直接读写，只能存储，需要通过视图来进行操作。</p><p>例如存储二进制数据的则是 ArrayBuffer 对象，例如请求图片时，就会指定参数 <code>responseType: 'arraybuffer'</code>表示返回二进制数据，也就是图片数据。</p><p><code>ArrayBuffer</code>也是一个构造函数，可以分配一段可以存放数据的连续内存区域。</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> buffer </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">ArrayBuffer</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">8</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token known-class-name class-name" style="color:rgb(38, 127, 153)">ArrayBuffer</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token maybe-class-name">Uint8Contents</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">&lt;</span><span class="token number" style="color:rgb(9, 134, 88)">00</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">00</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">00</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">00</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">00</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">00</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">00</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">00</span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">byteLength</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">8</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>这里的 buffer.byteLength 属性用于获取字节长度（返回 32），直接打印 buf 的结果</p><p>其中还有一个<code>slice</code>方法，允许将内存区域的一部分，拷贝生成一个新的<code>ArrayBuffer</code>对象。下面代码拷贝<code>buffer</code>对象的前 3 个字节（从 0 开始，到第 3 个字节前面结束）</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> buffer </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">ArrayBuffer</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">8</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> newBuffer </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> buffer</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">slice</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">3</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>除了<code>slice</code>方法，<code>ArrayBuffer</code>对象不提供任何直接读写内存的方法，只允许在其上方建立视图，然后通过视图读写。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="typedarray">TypedArray<a class="hash-link" href="#typedarray" title="标题的直接链接">​</a></h2><p>不过只有空数据可没用，肯定需要操作<code>ArrayBuffer</code>，也就要介绍下<code>TypedArray</code>。</p><p><code>ArrayBuffer</code>对象作为内存区域，可以存放多种类型的数据。同一段内存，不同数据有不同的解读方式，这就叫做“视图”（view），<code>ArrayBuffer</code>有两种视图，一种是<code>TypedArray</code>视图，另一种是<code>DataView</code>视图。这里只介绍<code>TypedArray</code></p><p><code>TypedArray</code>视图一共包括 9 种类型，每一种视图都是一种构造函数通过 9 个构造函数，可以生成 9 种数据格式的视图，比如<code>Uint8Array</code>（无符号 8 位整数，表示一个字节）数组视图，具体如下</p><table><thead><tr><th align="left">数据类型</th><th align="left">字节长度</th><th align="left">含义</th><th align="left">对应的 C 语言类型</th></tr></thead><tbody><tr><td align="left">Int8</td><td align="left">1</td><td align="left">8 位带符号整数</td><td align="left">signed char</td></tr><tr><td align="left">Uint8</td><td align="left">1</td><td align="left">8 位不带符号整数</td><td align="left">unsigned char</td></tr><tr><td align="left">Uint8C</td><td align="left">1</td><td align="left">8 位不带符号整数（自动过滤溢出）</td><td align="left">unsigned char</td></tr><tr><td align="left">Int16</td><td align="left">2</td><td align="left">16 位带符号整数</td><td align="left">short</td></tr><tr><td align="left">Uint16</td><td align="left">2</td><td align="left">16 位不带符号整数</td><td align="left">unsigned short</td></tr><tr><td align="left">Int32</td><td align="left">4</td><td align="left">32 位带符号整数</td><td align="left">int</td></tr><tr><td align="left">Uint32</td><td align="left">4</td><td align="left">32 位不带符号的整数</td><td align="left">unsigned int</td></tr><tr><td align="left">Float32</td><td align="left">4</td><td align="left">32 位浮点数</td><td align="left">float</td></tr><tr><td align="left">Float64</td><td align="left">8</td><td align="left">64 位浮点数</td><td align="left">double</td></tr></tbody></table><p>视图的构造函数可以接受三个参数：</p><ul><li>第一个参数（必需）：视图对应的底层<code>ArrayBuffer</code>对象。</li><li>第二个参数（可选）：视图开始的字节序号，默认从 0 开始。</li><li>第三个参数（可选）：视图包含的数据个数，默认直到本段内存区域结束。</li></ul><p>演示</p><p>不妨给它写入字符串 abc，对应的十进制 ASCII 码为 97,98,99，由于 ASCII 码占用一个字节存储，所以这里选择 Uint8Array 用于表示</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> buffer </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">ArrayBuffer</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">8</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> buf </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">Uint8Array</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">buffer</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">buf</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">set</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">97</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">98</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">99</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">buf</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">buffer</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// 输出结果</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token known-class-name class-name" style="color:rgb(38, 127, 153)">ArrayBuffer</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token maybe-class-name">Uint8Contents</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">&lt;</span><span class="token number" style="color:rgb(9, 134, 88)">61</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">62</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">63</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">00</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">00</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">00</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">00</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">00</span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">byteLength</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">8</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>可以看到 abc 确实存入了，并用十六进制的形式表示，为了验证，这里使用 NodeJS 中的 Buffer 来演示，当然也可以使用原生的<a href="https://es6.ruanyifeng.com/#docs/arraybuffer#ArrayBuffer-%E4%B8%8E%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%9A%84%E4%BA%92%E7%9B%B8%E8%BD%AC%E6%8D%A2" target="_blank" rel="noopener noreferrer">TextEncoder</a></p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token maybe-class-name">Buffer</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">buf</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">buffer</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">toString</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// abc</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>你也可以直接通过数组下标的形式，来访问数据，如<code>buf[0]</code>返回的就是 97，但 buf 又有 length 与其他的属性方法，这种数组就统称为类数组。</p><p>buf 还有一些方法，无非就是操作字节复制，偏移就不做过多介绍与演示了，具体可查看<a href="https://es6.ruanyifeng.com/#docs/arraybuffer" target="_blank" rel="noopener noreferrer">文档</a></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="nodejs-的-buffer">NodeJS 的 Buffer<a class="hash-link" href="#nodejs-的-buffer" title="标题的直接链接">​</a></h2><p><a href="http://nodejs.cn/api/buffer.html#buffer_buffers_and_character_encodings" target="_blank" rel="noopener noreferrer">buffer 缓冲区 | Node.js API 文档 (nodejs.cn)</a></p><p>在 Nodejs 中有专门的操作<code>ArrayBuffer</code> 的对象<code>Buffer</code>，<code>Buffer</code> 类是 JavaScript <a href="http://url.nodejs.cn/ZbDkpm" target="_blank" rel="noopener noreferrer"><code>Uint8Array</code></a> 类的子类</p><p>所以<code>Uint8Array</code>有的属性方法 Buffer 也有，不过 Nodejs 对 Buffer 增加了额外的方法供开发者调用。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="bufferfrom"><a href="http://nodejs.cn/api/buffer.html#static-method-bufferfromarray" target="_blank" rel="noopener noreferrer">Buffer.from</a><a class="hash-link" href="#bufferfrom" title="标题的直接链接">​</a></h3><p>上面的代码 <code>Buffer.from(buf.buffer).toString()</code>，也就是将<code>ArrayBuffer</code> 数据转为 utf8 编码文本。其中 toString 还能转为以下编码（toString 默认 utf8）</p><div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">type</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">BufferEncoding</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'ascii'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'utf8'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'utf-8'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'utf16le'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'ucs2'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'ucs-2'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'base64'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'base64url'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'latin1'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'binary'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'hex'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>不过 Nodejs 不支持 gbk 编码，所以需要使用第三方包，如 iconv-lite</p><p><code>Buffer.from()</code>有多个方法实现，第一个参数可以传入 ArrayBuffer | Uint8Array | string，如果是 string 类型，第二个参数为编码格式，例如实现编码转化</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)">// base64</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token maybe-class-name">Buffer</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">str</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">toString</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'base64'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 将str转base64编码</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token maybe-class-name">Buffer</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">str</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'base64'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">toString</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 将base64编码转str</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// hex</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token maybe-class-name">Buffer</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">str</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">toString</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'hex'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 将str转hex编码</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token maybe-class-name">Buffer</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">str</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'hex'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">toString</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 将hex编码转str</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>封装 Base64 编码与解码</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> </span><span class="token maybe-class-name">Base64</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function-variable function" style="color:rgb(0, 0, 255)">encode</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">str</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token maybe-class-name">Buffer</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">str</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">toString</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'base64'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function-variable function" style="color:rgb(0, 0, 255)">decode</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">str</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token maybe-class-name">Buffer</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">str</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'base64'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">toString</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="buftojson"><a href="http://nodejs.cn/api/buffer.html#buftojson" target="_blank" rel="noopener noreferrer">buf.toJSON()</a><a class="hash-link" href="#buftojson" title="标题的直接链接">​</a></h3><p>将会得到 buf 的视图类型，与二进制数组。</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)">// let buf = Buffer.from('abc');</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> buf </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token maybe-class-name">Buffer</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">97</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">98</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">99</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">buf</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// &lt;Buffer 61 62 63&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">buf</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">toJSON</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// { type: 'Buffer', data: [ 97, 98, 99 ] }</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// 效果等同于 JSON.stringify(buf);</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">buf</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">values</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// [ 97, 98, 99 ]   可以直接得到二进制数据</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>官方文档: <a href="http://nodejs.cn/api/buffer.html#buffer" target="_blank" rel="noopener noreferrer">buffer 缓冲区 | Node.js API 文档 (nodejs.cn)</a></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="arraybuffer-和-buffer-区别">ArrayBuffer 和 Buffer 区别<a class="hash-link" href="#arraybuffer-和-buffer-区别" title="标题的直接链接">​</a></h2><p>上述对这两者进行了介绍，这里总结一下</p><p><code>ArrayBuffer</code> 对象用来表示通用的、固定长度的原始二进制数据缓冲区，是一个字节数组，可读但不可直接写。</p><p><code>Buffer</code> 是 Node.JS 中用于操作 <code>ArrayBuffer</code> 的视图，继承自<code>Uint8Array</code>，是 <code>TypedArray</code> 的一种。</p><p>通俗点来说（<strong>对我而言</strong>），<code>ArrayBuffer</code>相当于其他语言的字节数组、字节集，但不可写，而<code>Buffer</code> 对象则是操作<code>ArrayBuffer</code>的。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="应用">应用<a class="hash-link" href="#应用" title="标题的直接链接">​</a></h2><p>与二进制数据有关的地方就有应用</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="编码转化">编码转化<a class="hash-link" href="#编码转化" title="标题的直接链接">​</a></h3><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="将请求图片转化成-base64-编码">将请求图片转化成 base64 编码<a class="hash-link" href="#将请求图片转化成-base64-编码" title="标题的直接链接">​</a></h3><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">axios</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">get</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'图片url地址'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">responseType</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'arraybuffer'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">then</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> base64Img </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">toString</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'base64'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">base64Img</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>在 axios 请求图片数据的时候，指定<code>responseType: 'arraybuffer'</code>，返回的 data 就是一个 buffer 对象。（当时写成这样的代码 <code>Buffer.from(res.data).buffer</code>，不过不妨碍）</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="http-发送二进制数据与-websocket">http 发送二进制数据与 WebSocket<a class="hash-link" href="#http-发送二进制数据与-websocket" title="标题的直接链接">​</a></h3><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">axios</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">post</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'http://example.com'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token maybe-class-name">Buffer</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'abc'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">then</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> socket </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">WebSocket</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'ws://127.0.0.1:8081'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">socket</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">binaryType</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'arraybuffer'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// Wait until socket is open</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">socket</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">addEventListener</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'open'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">event</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token comment" style="color:rgb(0, 128, 0)">// Send binary data</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> typedArray </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">Uint8Array</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">4</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  socket</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">send</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">typedArray</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">buffer</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// Receive binary data</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">socket</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">addEventListener</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'message'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">event</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> arrayBuffer </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">data</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token comment" style="color:rgb(0, 128, 0)">// ···</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="文件读写">文件读写<a class="hash-link" href="#文件读写" title="标题的直接链接">​</a></h3><p>等等。。。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="参考">参考<a class="hash-link" href="#参考" title="标题的直接链接">​</a></h2><blockquote><p><a href="https://es6.ruanyifeng.com/#docs/arraybuffer" target="_blank" rel="noopener noreferrer">ArrayBuffer - ECMAScript 6 入门 (ruanyifeng.com)</a></p><p><a href="https://www.zhihu.com/question/26246195/answer/1231680251#ref_1" target="_blank" rel="noopener noreferrer">ArrayBuffer 和 Buffer 有何区别？ - 知乎 (zhihu.com)</a></p></blockquote>]]></content:encoded>
            <category>javascript</category>
        </item>
        <item>
            <title><![CDATA[Docusaurus配置Gitalk评论插件]]></title>
            <link>https://kuizuo.cn/docusaurus-gitalk-plugin</link>
            <guid>docusaurus-gitalk-plugin</guid>
            <pubDate>Sat, 22 Jan 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[之前使用 vuepress 的时候，使用的评论系统是Valine，可是匿名用户也能直接评论，虽说会过滤垃圾信息，但是后台查看评论与通知总感觉没有那么实在。]]></description>
            <content:encoded><![CDATA[<p>之前使用 vuepress 的时候，使用的评论系统是<a href="https://valine.js.org/" target="_blank" rel="noopener noreferrer">Valine</a>，可是匿名用户也能直接评论，虽说会过滤垃圾信息，但是后台查看评论与通知总感觉没有那么实在。</p><p>然后换到了 docusaurus，并没有内置评论相关的，原本是打算自己写一个评论系统，MongoDB 存储评论数据相对方便些。然后这一拖就是拖到了过年前。。。无意间发现有一个插件<a href="https://gitalk.github.io/" target="_blank" rel="noopener noreferrer">Gitalk</a>，基于 Github Issue 的，而我平常又经常刷 github，加上需要 github 账号才能评论，所以就使用<a href="https://gitalk.github.io/" target="_blank" rel="noopener noreferrer">Gitalk</a> 来作为博客的评论（注：Gitalk 是基于 react 编写的）。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="操作步骤">操作步骤<a class="hash-link" href="#操作步骤" title="标题的直接链接">​</a></h2><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="1创建评论仓库">1、创建评论仓库<a class="hash-link" href="#1创建评论仓库" title="标题的直接链接">​</a></h3><p>首先需要 github 账号，创建一个仓库用于存放评论，由于我的博客是同步上传到<a href="https://github.com/kuizuo/blog" target="_blank" rel="noopener noreferrer">github</a>上，所以就无需新建仓库</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="2开启-issues-功能">2、开启 issues 功能<a class="hash-link" href="#2开启-issues-功能" title="标题的直接链接">​</a></h3><p>默认开启，可在 Settings -&gt; Features -&gt; Issues 中设置</p><p><img loading="lazy" src="https://img.kuizuo.cn/20220122141447.png" alt="image-20220122141447919" class="img_ev3q"></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="3注册一个-github-applications">3、注册一个 Github applications<a class="hash-link" href="#3注册一个-github-applications" title="标题的直接链接">​</a></h3><p>点击<a href="https://github.com/settings/developers" target="_blank" rel="noopener noreferrer">此处</a>创建或在 github 右上角路径 settings -&gt; Developer settings -&gt; OAuth Apps</p><p><img loading="lazy" src="https://img.kuizuo.cn/20220121225106.png" alt="image-20220121225059192" class="img_ev3q"></p><ul><li>Homepage URL：就是博客的网址（如果是 github.io 的 page）</li><li>Authorization callback URL: 就是 github 权限验证的回调地址，一般默认就是域名</li></ul><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="4获取-client-id-和-client-secret">4、获取 Client ID 和 Client Secret<a class="hash-link" href="#4获取-client-id-和-client-secret" title="标题的直接链接">​</a></h3><p>创建成功后，就可以获取到 Client ID 和 Client Secret 了，保存下来。</p><p><img loading="lazy" src="https://img.kuizuo.cn/20220122130222.png" alt="image-20220122130221871" class="img_ev3q"></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="5安装">5、安装<a class="hash-link" href="#5安装" title="标题的直接链接">​</a></h3><p><a href="https://github.com/gitalk/gitalk/blob/master/readme-cn.md#%E5%AE%89%E8%A3%85" target="_blank" rel="noopener noreferrer">官方教程</a></p><ul><li>直接引入</li></ul><div class="language-html codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-html codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">link</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">rel</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">stylesheet</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">href</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">https://cdn.jsdelivr.net/npm/gitalk@1/dist/gitalk.css</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">/&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">script</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">src</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">https://cdn.jsdelivr.net/npm/gitalk@1/dist/gitalk.min.js</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token script"></span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">script</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">&lt;!-- or --&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">link</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">rel</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">stylesheet</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">href</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">https://unpkg.com/gitalk/dist/gitalk.css</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">/&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">script</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">src</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">https://unpkg.com/gitalk/dist/gitalk.min.js</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token script"></span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">script</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><ul><li>npm 安装</li></ul><div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">npm i --save gitalk</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword module" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'gitalk/dist/gitalk.css'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword module" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token imports maybe-class-name">Gitalk</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'gitalk'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="6使用">6、使用<a class="hash-link" href="#6使用" title="标题的直接链接">​</a></h3><div class="language-html codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-html codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">div</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">id</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">gitalk-container</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">div</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>用下面的 Javascript 代码来生成 gitalk 插件：</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> gitalk </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">Gitalk</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">clientID</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'GitHub Application Client ID'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">clientSecret</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'GitHub Application Client Secret'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">repo</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'GitHub repo'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">owner</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'GitHub repo owner'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">admin</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'GitHub repo owner and collaborators, only these guys can initialize github issues'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">id</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token dom variable" style="color:rgb(9, 134, 88)">location</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">pathname</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// Ensure uniqueness and length less than 50</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">distractionFreeMode</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// Facebook-like distraction free mode</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">gitalk</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">render</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'gitalk-container'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h5 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="react-中使用">react 中使用<a class="hash-link" href="#react-中使用" title="标题的直接链接">​</a></h5><p>导入 Gitalk 组件与样式</p><div class="language-jsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-jsx codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword module" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'gitalk/dist/gitalk.css'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword module" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token imports maybe-class-name">GitalkComponent</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'gitalk/dist/gitalk-component'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>使用组件与配置参数</p><div class="language-jsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-jsx codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag class-name" style="color:rgb(38, 127, 153)">GitalkComponent</span><span class="token tag" style="color:rgb(128, 0, 0)"></span><br></span><span class="token-line" style="color:#000000"><span class="token tag" style="color:rgb(128, 0, 0)">  </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">options</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:rgb(4, 81, 165)">=</span><span class="token tag script language-javascript punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token tag script language-javascript punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token tag script language-javascript" style="color:rgb(128, 0, 0)"></span><br></span><span class="token-line" style="color:#000000"><span class="token tag script language-javascript" style="color:rgb(128, 0, 0)">    </span><span class="token tag script language-javascript literal-property property" style="color:rgb(128, 0, 0)">clientID</span><span class="token tag script language-javascript operator" style="color:rgb(0, 0, 0)">:</span><span class="token tag script language-javascript" style="color:rgb(128, 0, 0)"> </span><span class="token tag script language-javascript string" style="color:rgb(163, 21, 21)">'...'</span><span class="token tag script language-javascript punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token tag script language-javascript" style="color:rgb(128, 0, 0)"></span><br></span><span class="token-line" style="color:#000000"><span class="token tag script language-javascript" style="color:rgb(128, 0, 0)">    </span><span class="token tag script language-javascript comment" style="color:rgb(0, 128, 0)">// ...</span><span class="token tag script language-javascript" style="color:rgb(128, 0, 0)"></span><br></span><span class="token-line" style="color:#000000"><span class="token tag script language-javascript" style="color:rgb(128, 0, 0)">    </span><span class="token tag script language-javascript comment" style="color:rgb(0, 128, 0)">// options below</span><span class="token tag script language-javascript" style="color:rgb(128, 0, 0)"></span><br></span><span class="token-line" style="color:#000000"><span class="token tag script language-javascript" style="color:rgb(128, 0, 0)">  </span><span class="token tag script language-javascript punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token tag script language-javascript punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token tag" style="color:rgb(128, 0, 0)"></span><br></span><span class="token-line" style="color:#000000"><span class="token tag" style="color:rgb(128, 0, 0)"></span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">/&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>我的配置</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> options </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">clientID</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'GitHub Application Client ID'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">clientSecret</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'GitHub Application Client Secret'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">repo</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'blog'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">owner</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'kuizuo'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">admin</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'kuizuo'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">id</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> title</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">title</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> title</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">labels</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> labels</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">distractionFreeMode</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>具体参数<a href="https://github.com/gitalk/gitalk/blob/master/readme-cn.md#%E8%AE%BE%E7%BD%AE" target="_blank" rel="noopener noreferrer">gitalk</a></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="问题">问题<a class="hash-link" href="#问题" title="标题的直接链接">​</a></h2><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="error-not-found">Error: Not Found<a class="hash-link" href="#error-not-found" title="标题的直接链接">​</a></h3><p>options 有个选项 repo，填写的是仓库名称，不是链接，像上面我所填写的就是<code>blog</code>，而不是填写<a href="https://github.com/kuizuo/blog" target="_blank" rel="noopener noreferrer">https://github.com/kuizuo/blog</a></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="未找到相关的-issues-进行评论请联系-xxxxx-初始化创建">未找到相关的 <a href="https://github.com/kuizuo/blog/issues" target="_blank" rel="noopener noreferrer">Issues</a> 进行评论，请联系 @xxxxx 初始化创建<a class="hash-link" href="#未找到相关的-issues-进行评论请联系-xxxxx-初始化创建" title="标题的直接链接">​</a></h3><p>这里的 xxxxx 就是选项 admin 的内容，首次载入文章的话需要用管理员账号登录初始化一下（也就是新建一个 issues），否则其他人访问也将会提示该信息。</p><p>目前暂时没找到有效办法一键加载所有博客的 issues，只要用登录 github 的管理员账号去访问每一篇博客。</p><p>其中在<a href="#3%E6%B3%A8%E5%86%8C%E4%B8%80%E4%B8%AA-github-applications">第 3 步</a>的 Authorization callback URL 地址一定要填写成现在博客线上环境 <a href="https://kuizuo.cn" target="_blank" rel="noopener noreferrer">https://kuizuo.cn</a> ，否则也无法正常使用</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="validation-failed">Validation failed<a class="hash-link" href="#validation-failed" title="标题的直接链接">​</a></h3><p>原因是 id 参数不能超过 50 个字符，但是默认是 location.href，有可能会导致长度超过。所以我的做法是 id: title，同时访问页面的时候，会自动为仓库创建一个 issue，标题为文章的标题。</p><p>也有可能是请求过于频繁，触发了 Github 的限流机制，需要等待几分钟后恢复。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="react-编译遇到的问题">react 编译遇到的问题<a class="hash-link" href="#react-编译遇到的问题" title="标题的直接链接">​</a></h3><p>插件中会使用到浏览器的 window 对象，开发时正常，但是编译就会报错（提示 window is not defined），这边引用了 docusaurus 的<a href="https://docusaurus.io/zh-CN/docs/docusaurus-core#browseronly" target="_blank" rel="noopener noreferrer">BrowserOnly</a>，将代码封装成如下便可正常编译</p><div class="language-jsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-jsx codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag class-name" style="color:rgb(38, 127, 153)">BrowserOnly</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">fallback</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:rgb(4, 81, 165)">=</span><span class="token tag script language-javascript punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token tag script language-javascript tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag script language-javascript tag" style="color:rgb(128, 0, 0)">div</span><span class="token tag script language-javascript tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token tag script language-javascript tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag script language-javascript tag" style="color:rgb(128, 0, 0)">div</span><span class="token tag script language-javascript tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token tag script language-javascript punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag class-name" style="color:rgb(38, 127, 153)">GitalkComponent</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">options</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:rgb(4, 81, 165)">=</span><span class="token tag script language-javascript punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token tag script language-javascript" style="color:rgb(128, 0, 0)">options</span><span class="token tag script language-javascript punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">/&gt;</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag class-name" style="color:rgb(38, 127, 153)">BrowserOnly</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p><a href="https://github.com/kuizuo/blog/blob/main/src/theme/BlogPostPage/index.jsx" target="_blank" rel="noopener noreferrer">查看完整源码点我</a></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="github-api">Github Api<a class="hash-link" href="#github-api" title="标题的直接链接">​</a></h2><p><a href="https://docs.github.com/cn" target="_blank" rel="noopener noreferrer">GitHub Documentation</a></p><p>通过 github api 还可以获取 issues 列表</p><p>访问 <a href="https://api.github.com/repos/kuizuo/blog/issues%EF%BC%8C%E8%BF%94%E5%9B%9E%E7%BB%93%E6%9E%9C%E5%A6%82%E4%B8%8B" target="_blank" rel="noopener noreferrer">https://api.github.com/repos/kuizuo/blog/issues，返回结果如下</a></p><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"https://api.github.com/repos/kuizuo/blog/issues/24"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"repository_url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"https://api.github.com/repos/kuizuo/blog"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"labels_url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"https://api.github.com/repos/kuizuo/blog/issues/24/labels{/name}"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"comments_url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"https://api.github.com/repos/kuizuo/blog/issues/24/comments"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"events_url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"https://api.github.com/repos/kuizuo/blog/issues/24/events"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"html_url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"https://github.com/kuizuo/blog/issues/24"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1111300101</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"node_id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"I_kwDOF7NJDM5CPRgF"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"number"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">24</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"title"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Docusaurus配置Gitalk评论插件"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"user"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"login"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"kuizuo"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">61005888</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"node_id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"MDQ6VXNlcjYxMDA1ODg4"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"avatar_url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"https://avatars.githubusercontent.com/u/61005888?v=4"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"gravatar_id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">""</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"https://api.github.com/users/kuizuo"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"html_url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"https://github.com/kuizuo"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"followers_url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"https://api.github.com/users/kuizuo/followers"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"following_url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"https://api.github.com/users/kuizuo/following{/other_user}"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"gists_url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"https://api.github.com/users/kuizuo/gists{/gist_id}"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"starred_url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"https://api.github.com/users/kuizuo/starred{/owner}{/repo}"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"subscriptions_url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"https://api.github.com/users/kuizuo/subscriptions"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"organizations_url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"https://api.github.com/users/kuizuo/orgs"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"repos_url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"https://api.github.com/users/kuizuo/repos"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"events_url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"https://api.github.com/users/kuizuo/events{/privacy}"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"received_events_url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"https://api.github.com/users/kuizuo/received_events"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"type"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"User"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"site_admin"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"labels"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">3754161267</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"node_id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"LA_kwDOF7NJDM7fw_Rz"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"https://api.github.com/repos/kuizuo/blog/labels/Gitalk"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"name"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Gitalk"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"color"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"ededed"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"default"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"description"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token null keyword" style="color:rgb(0, 0, 255)">null</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">3754411279</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"node_id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"LA_kwDOF7NJDM7fx8UP"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"https://api.github.com/repos/kuizuo/blog/labels/blog"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"name"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"blog"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"color"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"ededed"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"default"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"description"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token null keyword" style="color:rgb(0, 0, 255)">null</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">3754517867</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"node_id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"LA_kwDOF7NJDM7fyWVr"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"https://api.github.com/repos/kuizuo/blog/labels/Docusaurus%E9%85%8D%E7%BD%AEGitalk%E8%AF%84%E8%AE%BA%E6%8F%92%E4%BB%B6"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"name"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Docusaurus配置Gitalk评论插件"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"color"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"ededed"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"default"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"description"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token null keyword" style="color:rgb(0, 0, 255)">null</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"state"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"open"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"locked"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"assignee"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token null keyword" style="color:rgb(0, 0, 255)">null</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"assignees"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"milestone"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token null keyword" style="color:rgb(0, 0, 255)">null</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"comments"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"created_at"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"2022-01-22T06:47:34Z"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"updated_at"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"2022-01-22T06:47:34Z"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"closed_at"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token null keyword" style="color:rgb(0, 0, 255)">null</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"author_association"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"OWNER"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"active_lock_reason"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token null keyword" style="color:rgb(0, 0, 255)">null</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"body"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"https://kuizuo.cn/develop/Docusaurus配置Gitalk评论插件\n前言"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"reactions"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"https://api.github.com/repos/kuizuo/blog/issues/24/reactions"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"total_count"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"+1"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"-1"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"laugh"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"hooray"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"confused"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"heart"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"rocket"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"eyes"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"timeline_url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"https://api.github.com/repos/kuizuo/blog/issues/24/timeline"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"performed_via_github_app"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token null keyword" style="color:rgb(0, 0, 255)">null</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>相关 api 文档 =&gt; <a href="https://docs.github.com/cn/rest/reference/issues#comments" target="_blank" rel="noopener noreferrer">github docs</a></p><p>也许后续可能考虑使用<a href="https://github.com/octokit/octokit.js" target="_blank" rel="noopener noreferrer">octokit.js</a>来编写一个后台查询与删除的管理页。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="最终效果">最终效果<a class="hash-link" href="#最终效果" title="标题的直接链接">​</a></h2><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="评论页">评论页<a class="hash-link" href="#评论页" title="标题的直接链接">​</a></h4><p><img loading="lazy" src="https://img.kuizuo.cn/20220122164034.png" alt="image-20220122164034147" class="img_ev3q"></p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="issues-页面">issues 页面<a class="hash-link" href="#issues-页面" title="标题的直接链接">​</a></h4><p><img loading="lazy" src="https://img.kuizuo.cn/20220122163957.png" alt="image-20220122163957435" class="img_ev3q"></p>]]></content:encoded>
            <category>blog</category>
            <category>docusaurus</category>
            <category>gitalk</category>
        </item>
        <item>
            <title><![CDATA[SpringBoot热更新]]></title>
            <link>https://kuizuo.cn/springboot-hot-update</link>
            <guid>springboot-hot-update</guid>
            <pubDate>Mon, 10 Jan 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[步骤一]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="步骤一">步骤一<a class="hash-link" href="#步骤一" title="标题的直接链接">​</a></h2><p>pom.xml 中在加入依赖</p><div class="language-xml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-xml codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">dependency</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">groupId</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain">org.springframework.boot</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">groupId</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">artifactId</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain">spring-boot-devtools</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">artifactId</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">optional</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain">true</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">optional</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">scope</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain">true</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">scope</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">dependency</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>然后再<code>&lt;build&gt;</code>下添加如下依赖。</p><div class="language-xml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-xml codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">build</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">plugins</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">plugin</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">groupId</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain">org.springframework.boot</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">groupId</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">artifactId</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain">spring-boot-maven-plugin</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">artifactId</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">configuration</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                    </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">fork</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain">true</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">fork</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">configuration</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">plugin</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">plugins</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">build</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="步骤二">步骤二<a class="hash-link" href="#步骤二" title="标题的直接链接">​</a></h2><p>（1）打开设置勾选自动构建项目</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220506130419248.png" alt="image-20220506130419248" class="img_ev3q"></p><p>（2）高级设置中勾选自动 make，老版 IDEA 需要<code>ctrl + shift + alt + /</code>，选择注册表，勾上 Compiler autoMake allow when app running，但新版中移到高级设置中。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220506130533312.png" alt="image-20220506130533312" class="img_ev3q"></p><p>接着启动项目，修改文件即可自动热加载，无需手动重新运行。</p>]]></content:encoded>
            <category>java</category>
            <category>springboot</category>
        </item>
        <item>
            <title><![CDATA[为什么使用pnpm]]></title>
            <link>https://kuizuo.cn/why-use-pnpm</link>
            <guid>why-use-pnpm</guid>
            <pubDate>Sat, 08 Jan 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[pnpm 文档]]></description>
            <content:encoded><![CDATA[<p><a href="https://pnpm.io/zh/" target="_blank" rel="noopener noreferrer">pnpm 文档</a></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="前言">前言<a class="hash-link" href="#前言" title="标题的直接链接">​</a></h2><p>在一个 node 项目中免不了 node_modules 依赖，假设项目 A 用的了 Express 依赖，同时项目 B 也用到了 Express，并且两者所存放的位置不同，那么磁盘空间将会多出两份 Express 依赖，假设有 100 个项目，那么将会有有 100 倍的空间被浪费。这些空间还可以用磁盘空间来弥补，但是这 100 个项目如果都使用 npm i 去下载同样版本依赖，则是实实在在耗费网络资源去下载。</p><p>pnpm 能解决以下两点问题</p><ul><li>包安装速度极快；</li><li>磁盘空间利用非常高效。</li></ul><p>而这些问题是一个 node 项目中常有的。相信此时的你都有点蠢蠢欲动了，而安装也很简单</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="安装">安装<a class="hash-link" href="#安装" title="标题的直接链接">​</a></h2><p>请查阅你的 node 版本与 pnpm 是否匹配 <a href="https://pnpm.io/zh/installation#%E5%85%BC%E5%AE%B9%E6%80%A7" target="_blank" rel="noopener noreferrer">安装 | pnpm</a></p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">npm install </span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain">g pnpm</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="升级">升级<a class="hash-link" href="#升级" title="标题的直接链接">​</a></h3><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">pnpm add </span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain">g pnpm</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>此时 pnpm 就已经安装完了，与 yarn 安装一样，都感觉没安装似的。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="使用">使用<a class="hash-link" href="#使用" title="标题的直接链接">​</a></h2><p>pnpm 命令几乎与 npm 一样，设置配置的方式也与 npm 相同，这里不妨尝试通过 pnpm 去下载 express 依赖，打开 CMD，将路径改成你平时写 js 代码的地方，切记不要在 C 盘路径下，不然将会在<code>C:\Users\{userDir}\.pnpm-store\v3</code>去管理你的所有依赖，至于为什么后文会说，这里选择 F 盘进行安装，安装结果如下。</p><p><img loading="lazy" src="https://img.kuizuo.cn/20220108040813.png" alt="image-20220108040813223" class="img_ev3q"></p><p>不难看出，它将依赖存放至<strong><code>F:\.pnpm-store\v3</code></strong>下，但此时查看项目目录的 node_modules 文件夹</p><p><img loading="lazy" src="https://img.kuizuo.cn/20220108041030.png" alt="image-20220108041030618" class="img_ev3q"></p><p>发现<code>express</code>与<code>mime-types</code>的右侧带了回车符，而这两个文件夹实际上是 window 的硬链接，而读取的就是存放在<code>F:\.pnpm-store\v3</code>下的依赖。虽然查看 node_modules 属性会发现显示的空间貌似和原始的链接所占用的空间一样，但其实是同一个位置，官方中常用问题中也有介绍到 <a href="https://pnpm.io/zh/faq#%E5%A6%82%E6%9E%9C%E5%8C%85%E5%AD%98%E5%82%A8%E5%9C%A8%E5%85%A8%E5%B1%80%E5%AD%98%E5%82%A8%E4%B8%AD%E4%B8%BA%E4%BB%80%E4%B9%88%E6%88%91%E7%9A%84-node_modules-%E4%BD%BF%E7%94%A8%E4%BA%86%E7%A3%81%E7%9B%98%E7%A9%BA%E9%97%B4" target="_blank" rel="noopener noreferrer">常见问题 | pnpm</a>，所以真不用担心磁盘空间的问题。</p><p>这时候去查看 <code>F:\.pnpm-store\v3\files</code> 会发现都是一堆数字与字母命名的文件夹，而依赖都存放至这些杂乱无章的文件名之中。同时.pnpm-store 是根据你所在驱动器（这里是 F 盘）下创建的，可以通过 <code>pnpm store path</code>查看，也就是上文为什么说不要在 C 盘路径（包括桌面）去安装依赖了，所以不用担心 C 盘空间会越来越小（如果你的代码是在 C 盘编写的话，那当我没说）。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="最后">最后<a class="hash-link" href="#最后" title="标题的直接链接">​</a></h2><p>不过还是要提醒一句，即便 pnpm 能解决磁盘问题，但还是存在一定的兼容性，如果一个项目是用 npm 或者 yarn 进行构建的，使用 pnpm 是绝对免不了一些问题，小问题暂时想不到，大问题无法运行，所以请三思再考虑对已有项目是否尝试升级 pnpm。</p><p>但我认为还是有必要尝试尝试下，不尝试，怎么能发现新大陆呢。</p><blockquote><p>参考链接：<a href="https://juejin.cn/post/6932046455733485575#heading-14" target="_blank" rel="noopener noreferrer">关于现代包管理器的深度思考——为什么现在我更推荐 pnpm 而不是 npm/yarn? - 掘金 (juejin.cn)</a></p></blockquote>]]></content:encoded>
            <category>node</category>
            <category>pnpm</category>
        </item>
        <item>
            <title><![CDATA[SpringBoot项目结构]]></title>
            <link>https://kuizuo.cn/springboot-project-structure</link>
            <guid>springboot-project-structure</guid>
            <pubDate>Sat, 08 Jan 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[演示代码地址：kuizuo/spring-boot-demo (github.com)]]></description>
            <content:encoded><![CDATA[<p>演示代码地址：<a href="https://github.com/kuizuo/spring-boot-demo" target="_blank" rel="noopener noreferrer">kuizuo/spring-boot-demo (github.com)</a></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="目录结构展示图">目录结构展示图<a class="hash-link" href="#目录结构展示图" title="标题的直接链接">​</a></h2><p><img loading="lazy" src="https://img.kuizuo.cn/20220108011921.png" class="img_ev3q"></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="controller">controller<a class="hash-link" href="#controller" title="标题的直接链接">​</a></h3><p>controller 目录下对应的也就是控制器，用于接收用户的请求（get，post 等），如下面代码</p><div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">controller/UserController.java</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token annotation punctuation" style="color:rgb(4, 81, 165)">@RestController</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token annotation punctuation" style="color:rgb(4, 81, 165)">@RequestMapping</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">"/user"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">public</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">UserController</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token annotation punctuation" style="color:rgb(4, 81, 165)">@Resource</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">private</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">UserService</span><span class="token plain"> userService</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token annotation punctuation" style="color:rgb(4, 81, 165)">@GetMapping</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">"list"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">public</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">List</span><span class="token generics punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token generics class-name" style="color:rgb(38, 127, 153)">User</span><span class="token generics punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">list</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> userService</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">findAll</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>用户请求<a href="http://127.0.0.1:8080/users/list" target="_blank" rel="noopener noreferrer">http://127.0.0.1:8080/user/list</a> 将会调用 userService.findAll 方法，当然这个方法事先定义好，用于获取所有用户。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="modelservice">model（service）<a class="hash-link" href="#modelservice" title="标题的直接链接">​</a></h3><p>这里数据库连接方式以 JPA（一个 ORM 框架）为例，可以安装一个 IDEA 插件 JPA Buddy 新建文件时可以直接创建 Entity(实体)或 Repository(仓库)</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220506115207717.png" alt="image-20220506115207717" class="img_ev3q"></p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="entity-类">entity 类<a class="hash-link" href="#entity-类" title="标题的直接链接">​</a></h4><p>在 domain 目录下创建实体类，大致如下（lombok 因人而异选择使用，相对不展示 get 与 set 会好一些）</p><div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">domain/User.java</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token import namespace">lombok</span><span class="token import namespace punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token import class-name" style="color:rgb(38, 127, 153)">Getter</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token import namespace">lombok</span><span class="token import namespace punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token import class-name" style="color:rgb(38, 127, 153)">Setter</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token import namespace">javax</span><span class="token import namespace punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token import namespace">persistence</span><span class="token import namespace punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token import operator" style="color:rgb(0, 0, 0)">*</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token annotation punctuation" style="color:rgb(4, 81, 165)">@Entity</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token annotation punctuation" style="color:rgb(4, 81, 165)">@Getter</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token annotation punctuation" style="color:rgb(4, 81, 165)">@Setter</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token annotation punctuation" style="color:rgb(4, 81, 165)">@Table</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">name </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"user"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">public</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">User</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">implements</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">Serializable</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token annotation punctuation" style="color:rgb(4, 81, 165)">@Id</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token annotation punctuation" style="color:rgb(4, 81, 165)">@GeneratedValue</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token annotation punctuation" style="color:rgb(4, 81, 165)">@ApiModelProperty</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">value </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"ID"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> hidden </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">private</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">Long</span><span class="token plain"> id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token annotation punctuation" style="color:rgb(4, 81, 165)">@Column</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">nullable </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> unique </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">private</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">String</span><span class="token plain"> username</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token annotation punctuation" style="color:rgb(4, 81, 165)">@Column</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">nullable </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">private</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">String</span><span class="token plain"> password</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token annotation punctuation" style="color:rgb(4, 81, 165)">@Column</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">nullable </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">private</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">String</span><span class="token plain"> email</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>User.java 用于定义 user 实体，在 ORM 中，数据库表中的字段都可以通过实体类中的属性来定义的，如果定义好 user 实体，并且在 resources/application.yml 中设置了<code>spring.jpa.hibernate.ddl-auto: update</code> 那么启动项目后，数据库将会自动创建 user 表且其表中字段自动为<code>@Column</code>注解的字段。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="repository-类">repository 类<a class="hash-link" href="#repository-类" title="标题的直接链接">​</a></h4><p>创建完实体后，还需要定义数据接口访问层 DAO，在 JPA 中则是在 repository 目录下创建。</p><div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">repository/UserRepository.java</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">public</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">interface</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">UserRepository</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">extends</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">JpaRepository</span><span class="token generics punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token generics class-name" style="color:rgb(38, 127, 153)">User</span><span class="token generics punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token generics"> </span><span class="token generics class-name" style="color:rgb(38, 127, 153)">Long</span><span class="token generics punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">JpaSpecificationExecutor</span><span class="token generics punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token generics class-name" style="color:rgb(38, 127, 153)">User</span><span class="token generics punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token class-name" style="color:rgb(38, 127, 153)">User</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">findByUsername</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token class-name" style="color:rgb(38, 127, 153)">String</span><span class="token plain"> username</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>一般情况下该接口无需定义额外方法，如有需要还可以定义属于自己的查询语句，比如上面的 findByUsername，这时候就注入后的 userRepository 对象就可以使用<code>userRepository.findByUsername("kuizuo");</code> ，将会返回数据库中该用户名的数据。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="userservice-类">UserService 类<a class="hash-link" href="#userservice-类" title="标题的直接链接">​</a></h4><div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">service/UserService.java</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token annotation punctuation" style="color:rgb(4, 81, 165)">@Service</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">public</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">UserService</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token annotation punctuation" style="color:rgb(4, 81, 165)">@Autowired</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">private</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">UserRepository</span><span class="token plain"> userRepository</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">public</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">List</span><span class="token generics punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token generics class-name" style="color:rgb(38, 127, 153)">User</span><span class="token generics punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">findAll</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> userRepository</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">findAll</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p><strong>@Autowired 可能不建议使用字段注入</strong>，可以在类添加@RequiredArgsConstructor 注解，表明 userRepository 不为空，总之目的就是将 userRepository 注入，供服务可用。</p><div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">service/UserService.java</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token import namespace">com</span><span class="token import namespace punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token import namespace">kuizuo</span><span class="token import namespace punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token import namespace">demo</span><span class="token import namespace punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token import namespace">domain</span><span class="token import namespace punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token import class-name" style="color:rgb(38, 127, 153)">User</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token import namespace">com</span><span class="token import namespace punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token import namespace">kuizuo</span><span class="token import namespace punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token import namespace">demo</span><span class="token import namespace punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token import namespace">repository</span><span class="token import namespace punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token import class-name" style="color:rgb(38, 127, 153)">UserRepository</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token import namespace">com</span><span class="token import namespace punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token import namespace">kuizuo</span><span class="token import namespace punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token import namespace">demo</span><span class="token import namespace punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token import namespace">service</span><span class="token import namespace punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token import class-name" style="color:rgb(38, 127, 153)">UserService</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token import namespace">lombok</span><span class="token import namespace punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token import class-name" style="color:rgb(38, 127, 153)">RequiredArgsConstructor</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token import namespace">org</span><span class="token import namespace punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token import namespace">springframework</span><span class="token import namespace punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token import namespace">stereotype</span><span class="token import namespace punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token import class-name" style="color:rgb(38, 127, 153)">Service</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token import namespace">java</span><span class="token import namespace punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token import namespace">util</span><span class="token import namespace punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token import class-name" style="color:rgb(38, 127, 153)">List</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token annotation punctuation" style="color:rgb(4, 81, 165)">@Service</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token annotation punctuation" style="color:rgb(4, 81, 165)">@RequiredArgsConstructor</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">public</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">UserService</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">private</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">final</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">UserRepository</span><span class="token plain"> userRepository</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token annotation punctuation" style="color:rgb(4, 81, 165)">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">public</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">List</span><span class="token generics punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token generics class-name" style="color:rgb(38, 127, 153)">User</span><span class="token generics punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">findAll</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> userRepository</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">findAll</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>接着就可以使用 userRepository 下的方法，如 <code>userRepository.findAll</code>命令相当于 <code>select * from user</code>，返回所有的用户列表。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="service-接口实现">service 接口实现<a class="hash-link" href="#service-接口实现" title="标题的直接链接">​</a></h4><p>此外 service 服务还可以有另一种写法，在 service 中添加一个 impl 目录，通过对 userService <strong>接口</strong>进行实现的服务。
在上面所写的 UserService 是一个类，这边将其改为一个接口，代码如下</p><div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">service/UserService.java</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">public</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">interface</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">UserService</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token class-name" style="color:rgb(38, 127, 153)">List</span><span class="token generics punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token generics class-name" style="color:rgb(38, 127, 153)">User</span><span class="token generics punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">findAll</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token class-name" style="color:rgb(38, 127, 153)">User</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">findOne</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token class-name" style="color:rgb(38, 127, 153)">Long</span><span class="token plain"> id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>同时只保留 UserService 所要提供的方法，然后在 service/impl 中创建文件 UserServiceImpl.java，具体代码如下</p><div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">service/impl/UserServiceImpl.java</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token annotation punctuation" style="color:rgb(4, 81, 165)">@Service</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token annotation punctuation" style="color:rgb(4, 81, 165)">@RequiredArgsConstructor</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">public</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">UserServiceImpl</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">implements</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">UserService</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">private</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">final</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">UserRepository</span><span class="token plain"> userRepository</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token annotation punctuation" style="color:rgb(4, 81, 165)">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">public</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">List</span><span class="token generics punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token generics class-name" style="color:rgb(38, 127, 153)">User</span><span class="token generics punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">findAll</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> userRepository</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">findAll</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token annotation punctuation" style="color:rgb(4, 81, 165)">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">public</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">User</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">findOne</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token class-name" style="color:rgb(38, 127, 153)">Long</span><span class="token plain"> id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> userRepository</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">findById</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">orElseThrow</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">-&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">BadRequestException</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">"用户不存在"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>调用并无差异，对 service 进一步的封装，相对更规范些（我看外面都这么写的，所以就这么写了）。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="数据接口">数据接口<a class="hash-link" href="#数据接口" title="标题的直接链接">​</a></h4><p><a href="https://developer.aliyun.com/article/694418" target="_blank" rel="noopener noreferrer">POJO、PO、DTO、DAO、BO、VO 需要搞清楚的概念</a>
此外还可能对不同层的数据进行命令</p><ul><li>数据实体(entity)类<code>PO</code> ：<ul><li>jpa 项目: domain 目录</li><li>mybatis 项目: entity 目录</li></ul></li><li>数据接口访问层<code>DAO</code>：<ul><li>jpa 项目： repository 目录</li><li>mybatis 项目： mapper 目录</li></ul></li><li>数据传输对象<code>DTO</code>：dto 目录</li><li>视图对象<code>VO</code>：vo 目录</li></ul><p>其中前两种在上文中 jpa 的例子中已经介绍了，简单介绍下后两者</p><p><code>DTO</code> 经过处理后的 PO，在传输数据对象中可能增加或者减少 PO 的属性</p><p><code>VO</code> 在控制层与视图层进行传输交换</p><p>对于后两者而言，可能还需要提供 Mapper 类用于数据转化，如 DTO 转 PO，PO 转 DTO。</p><h5 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="modelmapper">modelMapper<a class="hash-link" href="#modelmapper" title="标题的直接链接">​</a></h5><div class="language-xml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-xml codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">dependency</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">groupId</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain">org.modelmapper</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">groupId</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">artifactId</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain">modelmapper</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">artifactId</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">version</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain">2.3.5</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">version</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">dependency</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>同时在启动类下配置为一个 Bean 才能被注入使用</p><div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token annotation punctuation" style="color:rgb(4, 81, 165)">@SpringBootApplication</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">public</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">DemoApplication</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">public</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">static</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">main</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token class-name" style="color:rgb(38, 127, 153)">String</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> args</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token class-name" style="color:rgb(38, 127, 153)">SpringApplication</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">run</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token class-name" style="color:rgb(38, 127, 153)">DemoApplication</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token keyword" style="color:rgb(0, 0, 255)">class</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> args</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token annotation punctuation" style="color:rgb(4, 81, 165)">@Bean</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">public</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">ModelMapper</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">modelMapper</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">ModelMapper</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h5 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="po-与-dto-转化">po 与 dto 转化<a class="hash-link" href="#po-与-dto-转化" title="标题的直接链接">​</a></h5><p>还是上面那个 user 实体，但是返回的数据中不需要将 user 的 password 展示出来。在 service/dto 中创建一个 UserDTO</p><div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">service/dto/UserDto.java</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token annotation punctuation" style="color:rgb(4, 81, 165)">@Getter</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token annotation punctuation" style="color:rgb(4, 81, 165)">@Setter</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">public</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">UserDto</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">private</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">Long</span><span class="token plain"> id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">private</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">String</span><span class="token plain"> username</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">private</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">String</span><span class="token plain"> email</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>如果要转化，通常要一个个字段转化，如下</p><div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token annotation punctuation" style="color:rgb(4, 81, 165)">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">public</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">UserDto</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">findOne</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token class-name" style="color:rgb(38, 127, 153)">Long</span><span class="token plain"> id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token class-name" style="color:rgb(38, 127, 153)">User</span><span class="token plain"> user </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain">  userRepository</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">findById</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">orElseThrow</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">-&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">BadRequestException</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">"用户不存在"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line theme-code-block-highlighted-line" style="color:#000000"><span class="token plain">        </span><span class="token class-name" style="color:rgb(38, 127, 153)">UserDto</span><span class="token plain"> userDto </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">UserDto</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line theme-code-block-highlighted-line" style="color:#000000"><span class="token plain">        userDto</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">setId</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">user</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">getId</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line theme-code-block-highlighted-line" style="color:#000000"><span class="token plain">        userDto</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">setUsername</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">user</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">getUsername</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line theme-code-block-highlighted-line" style="color:#000000"><span class="token plain">        userDto</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">setEmail</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">user</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">getEmail</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> userDto</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>结果肯定是没问题的，但是代码写的很丑陋且不易于维护。就可以使用 modelMapper 来转化（前提已经注入）</p><div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">private</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">final</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">ModelMapper</span><span class="token plain"> modelMapper</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token annotation punctuation" style="color:rgb(4, 81, 165)">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">public</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">UserDto</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">findOne</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token class-name" style="color:rgb(38, 127, 153)">Long</span><span class="token plain"> id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line theme-code-block-highlighted-line" style="color:#000000"><span class="token plain">        </span><span class="token class-name" style="color:rgb(38, 127, 153)">User</span><span class="token plain"> user </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain">  userRepository</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">findById</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">orElseThrow</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">-&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">BadRequestException</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">"用户不存在"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token class-name" style="color:rgb(38, 127, 153)">UserDto</span><span class="token plain"> userDto </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> modelMapper</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token function" style="color:rgb(0, 0, 255)">map</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">user</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">UserDto</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token keyword" style="color:rgb(0, 0, 255)">class</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> userDto</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>不过这样使用可能还是不大规范，同时还需要手动传入对象及其 Class 对象。所以可能还会创建 service/mapstruct，然后创建 UserMapper，这里就不举例了。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="view">view<a class="hash-link" href="#view" title="标题的直接链接">​</a></h3><p>此外还有个文件 resources/templates/user.html 用于返回页面，不过这些都属于模板语言的内容，就不细说了（针对前后端分离的项目而言，后端主要提供数据便可）</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="整体流程">整体流程<a class="hash-link" href="#整体流程" title="标题的直接链接">​</a></h3><p>大致的流程便可总结为 Controller 接收请求 → 调用 service 服务 → 调用数据接口服务 dao 提供数据 → 将数据(页面)返回给用户</p><p><strong>此外，该目录结构仅仅本人所选用的 springboot 项目结构，实际情况还需额外考虑。</strong></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="总结">总结<a class="hash-link" href="#总结" title="标题的直接链接">​</a></h2><p>回到开头，其中提供业务服务（数据）的也就是 service 所做的事情，控制接口的则是 controller，还有一个视图层 view 介绍的比较少（反正就是返回数据或页面）。其中最为复杂的也就是 service 所提供的服务，相对 controller 和 view 而言会繁琐许多。</p>]]></content:encoded>
            <category>java</category>
            <category>springboot</category>
            <category>develop</category>
        </item>
        <item>
            <title><![CDATA[为何我选择日夜颠倒敲代码]]></title>
            <link>https://kuizuo.cn/why-i-turn-night-into-day-to-code</link>
            <guid>why-i-turn-night-into-day-to-code</guid>
            <pubDate>Mon, 03 Jan 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[其实我很早就想写这个话题了。因为我是一个熬夜大户，经常动不动就是 3,4 点睡觉，甚至有时候是日夜颠倒的作息习惯，如同过美国时间般，在 0 点到 6 点这时间段几乎是我的 coding time。但与常人想法不同，我巴不得在保持这种作息状态。我会分以下几点来阐述我这一不正常的行为，相对于我而言的好点。]]></description>
            <content:encoded><![CDATA[<p>其实我很早就想写这个话题了。因为我是一个熬夜大户，经常动不动就是 3,4 点睡觉，甚至有时候是日夜颠倒的作息习惯，如同过美国时间般，在 0 点到 6 点这时间段几乎是我的 coding time。但与常人想法不同，我巴不得在保持这种作息状态。我会分以下几点来阐述我这一不正常的行为，相对于我而言的好点。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="对我而言的好处">对我而言的好处<a class="hash-link" href="#对我而言的好处" title="标题的直接链接">​</a></h2><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="安静">安静<a class="hash-link" href="#安静" title="标题的直接链接">​</a></h3><p>夜生活过的人应该最清楚了，那种静可以算上是幽静了，加上黑夜的承托与屏幕前的微光，如果恰好此时耳机还播放着音乐，好了，直接进入自我境界。</p><p>这种安静与图书馆的安静是根本无法相比的，图书馆可能还有走动声，而凌晨你唯独只能听见自己的脚步声（不排除有上厕所的室友，有时候可能被其吓得一跳），最主要还是黑，你的视野中除了屏幕的信息外几乎很难有其他东西去干涉你。</p><p>你问我用的什么键盘？程序员不都用静电容的键盘吗？机械键盘的声音在晚上敲怕不是给室友去世器。(tips: 室友包括我)</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="琐事">琐事<a class="hash-link" href="#琐事" title="标题的直接链接">​</a></h3><p>安静也许远远还不够，想要达到与世隔绝的地步，在互联网这个时间段最简单的办法就是断网。如果事情都与你毫不相干，那也差不多已经与这个世界说拜拜了，但在白天你还是有一定的存在感，会有一些莫名的琐事干涉你当前正在进行的状态。</p><p>我就说一个最简单的例子，假如你正在编写一个功能的时候，此时手机正好弹出一条信息（通常为广告），此时大多数人基本上就去看手机去了，意志力好一点的可能看完直接回到手头的任务上，差一点的可能就是几十分钟的短视频，也许很夸张，但确实如此。</p><p>所以我一般都会在 0~6 点开启勿扰模式（睡眠模式），但在白天却又不能错过很多重要的信息。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="思考">思考<a class="hash-link" href="#思考" title="标题的直接链接">​</a></h3><p>可能对我而言，灵感通常是在睡前（准确说是夜深时）产生的，同时脑子里想的东西也会比白天而言多，想的多自然写的东西也就多，所以也就是我为什么很多代码 Commit 与博客编写时间都是在 0~6 点这个时间，就连这篇文章也都是在夜间写的，白天实在是想不出什么点来写。</p><p>也许与静也有相关，白天普遍嘈杂的声音，说实话很难让人能静下来去冥想，但在夜晚，静确实它唯一的资本。</p><p><strong>唯有夜深人静，才有自我深思。</strong></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="工作效率">工作效率<a class="hash-link" href="#工作效率" title="标题的直接链接">​</a></h3><p>在我亲身体验下来，可以毫不夸张的说，我在夜晚的工作效率可以是白天的 3，4 倍，没错就是这么恐怖。</p><p>至于原因，大概率（99%）是由上面几点导致的，所以也就是为什么我巴不得在夜深人静的时候开始 doing，导致这异于常人的作息规律。尤其在夜晚，是很难感受到时间的存在，有时候可能天亮了才知道。这时才发觉自己又熬了一个晚上。</p><p>但回想 1 小时抵 3 小时，怎么想都是赚，换做你，会考虑这样的作息吗？</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="对我而言的坏处">对我而言的坏处<a class="hash-link" href="#对我而言的坏处" title="标题的直接链接">​</a></h2><p>不过导致这种规律的原因，与当天任务未完成，要到凌晨加班加点完成。或者是一时上头，忘记了时间的存在，手头的任务打消了睡意。久而久之，作息时间点不断延后，就导致现在现在的生物钟。</p><p>其实坏处都不用写，是个正常作息的一眼就能看出来，我也不细说了。</p><p>但往往事与愿违，上面的这种作息行为都有点压榨白天的时间，因为白天总要上学，上班，周末又不可能一次性就调整成这样的作息，所以我这种情况一般也都发生在长假期，例如寒暑假（包括这次的寒假）。但其实日常生活中大多时间还都是夜间做事，只是假期的夜间时间相对延后那么亿点。</p><font size="1">与好处相比，除了猝死其他都还能接受。</font><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="总结">总结<a class="hash-link" href="#总结" title="标题的直接链接">​</a></h2><p>原本标题我是起为什么喜欢熬夜，但后来我并不认为我是在熬夜，只是时间相对错乱，每天睡觉的时间与正常作息并没有差别，唯一的差别估计就是天亮了我睡了，天暗了我醒了。主要还是强调作息，所以便有了这个标题。</p><p>当然我写这篇文章也不是想要倡导夜间做事有多好，每个人都有属于自己适应的时间段，比方说有些人就喜欢早晨背单词，而有些选择在睡前，道理都是同样的。我只是觉得我这种习惯比较异类，也许也有人的作息习惯和我臭味相投。</p><p>:::danger ⚠️ 非专业人士，请勿模仿！ :::</p>]]></content:encoded>
            <category>随笔</category>
            <category>杂谈</category>
        </item>
        <item>
            <title><![CDATA[2021年终总结（休学一年）]]></title>
            <link>https://kuizuo.cn/2021-year-end-summary</link>
            <guid>2021-year-end-summary</guid>
            <pubDate>Fri, 31 Dec 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[距离上篇记录过去了 1 年半时间，以后应该也会在每年的 12 月 31 号发布年终总结。]]></description>
            <content:encoded><![CDATA[<div class="theme-admonition theme-admonition-info alert alert--info admonition_LlT9"><div class="admonitionHeading_tbUL"><span class="admonitionIcon_kALy"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>这篇文章发布时间与实际编写时间有所不同，所以内容上有可能会包含未来相关的信息，主要是想对过去的经历做个记录总结，算是一个弥补吧。 :::</div><div class="admonitionContent_S0QG"><p>距离上篇记录过去了 1 年半时间，以后应该也会在每年的 12 月 31 号发布年终总结。</p><p>不过在总结的时候还是要唠嗑唠嗑，其实说实话，今年没去年那么想写年终总结，一是感觉去年过得没有前年那么充实，尤其是在学习方面；二是因为 21 年这年休学出去工作(创业)；三是感觉很多时候过于迷茫，尤其是 2021 年后半年，浪费了太多本该提升自我的时间；最后加上 2022 年 1 月闭关安卓逆向学习，所以便没有抽出时间来完善年终总结。</p><p>所以说要写年终前一定要趁早，否则将会越来越拖，这次就整整拖了半年才最终完善。平常也要时刻保持记录的习惯，这样年终总结的时候思路才清醒，看到平时记录的点滴就能一时刻地回忆起所有细节。</p><p>每次写年终总结时不时也会潸然泪下，写的时候就需要不断的回忆过去，而往往过去的某些时刻的做法会让自己觉得是不是有个更优解？常常会回忆起过去这一年所经历的往往，难以忘怀，不知从何写起。</p><p>话虽说，但总归还是学到了点东西，所以还是得总结一下，不记录可能这段经历就消逝在时间的烟海之中。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="web-开发">Web 开发<a class="hash-link" href="#web-开发" title="标题的直接链接">​</a></h2><p>在这过去的中时间内，我已经从一位逆向爱好者的转到 Web 开发行业上。在上次的记录中我也仅仅只是搭建了一个博客，还是基于<a href="https://vuepress.vuejs.org/zh/" target="_blank" rel="noopener noreferrer">Vuepress</a>，不过由于拖更过久，于是就索性使用<a href="https://docusaurus.io/" target="_blank" rel="noopener noreferrer">Docusaurus</a>做为未来的博客。像一些主流前端框架(<a href="https://v3.cn.vuejs.org/" target="_blank" rel="noopener noreferrer">Vue</a>,<a href="https://reactjs.org/" target="_blank" rel="noopener noreferrer">React</a>)以及 <a href="https://cn.vitejs.dev/" target="_blank" rel="noopener noreferrer">Vite</a> 和 <a href="https://webpack.js.org/" target="_blank" rel="noopener noreferrer">webpack</a> 构建工具使用过，期间也不断尝试新的技术栈，了解其新特性，所以实现些基本的前端页面或功能倒是不成问题。</p><p>但 Web 开发可不仅仅只是由前端页面构成的，虽然对于上面静态站点的博客而言，那确实够。不过想要做到一些页面阅读量，以及评论相关的，就必须涉及到数据交互，也就是后端服务。后端服务所选用的语言可就多了，例如 nodejs、java、php、python、go 等等，虽说都有接触过(尝试搭建过后端服务与部署)，但 node 还是我的后端开发首选， JavaScript/TypeScript 是我目前用的最多的编程语言，这其中就使用到<a href="https://nestjs.com/" target="_blank" rel="noopener noreferrer">Nest.js</a>这类 Node.js 版的 Spring 框架，同时也接触到<a href="https://typeorm.io/" target="_blank" rel="noopener noreferrer">TypeORM</a>这个 ORM 框架，操作数据就如操作对象一样，可以不用写 sql 就能完成基本的 CRUD。同时也接触到 Java 的<a href="https://spring.io/" target="_blank" rel="noopener noreferrer">Spring</a>、Php 的<a href="https://www.thinkphp.cn/" target="_blank" rel="noopener noreferrer">ThinkPHP</a>、Go 的<a href="https://gin-gonic.com/zh-cn/" target="_blank" rel="noopener noreferrer">Gin</a>、Python 的<a href="https://fastapi.tiangolo.com/zh/" target="_blank" rel="noopener noreferrer">FastAPI</a>，这些语言中的后端框架。同时数据库方面也学习与使用到<a href="https://www.mysql.com/" target="_blank" rel="noopener noreferrer">Mysql</a>、<a href="https://www.mongodb.com/" target="_blank" rel="noopener noreferrer">MongoDB</a>、<a href="https://redis.io/" target="_blank" rel="noopener noreferrer">Redis</a>、<a href="https://www.elastic.co/cn/elasticsearch/" target="_blank" rel="noopener noreferrer">Elasticsearch</a>，这些 SQL 与 NoSQL 数据库以及搜索和数据分析引擎。</p><p>可以肯定是的未来的编程日子里有一大段时间估计也与 Web 开发息息相关。</p><p>不过在年终这并不想介绍在学习期间所涉及的项目，因为这太啰嗦了，导致有挺大一部分时间都是在介绍，而不是在总结，违背年终总结的意义。<strong>(学习的)过程往往不是人们所在意的，人们往往在意的是所导致的结果。</strong></p><p>关于项目的开发我一般都会放置在<a href="https://github.com/kuizuo" target="_blank" rel="noopener noreferrer">Github</a>上，以及<a href="https://kuizuo.cn/project" target="_blank" rel="noopener noreferrer">博客项目页</a>中，可自行查看。</p></div></div><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="看书">看书<a class="hash-link" href="#看书" title="标题的直接链接">​</a></h2><p>也是在今天开始去看书，看文章，加固对已有技术的理解，基本上每天凌晨 0-2 点的时间段都在看技术相关的书籍。主要都是针对 JS 相关的书籍与一些其他书籍，例如</p><ul><li>《JavaScript 高级程序设计》（第 4 版，简称红宝书）</li><li>《重构 改善既有代码的设计》（第 2 版，JS）</li><li>《JavaScript 设计模式与开发实践》</li><li>《深入浅出 Node.js》</li><li>《Visual Studio Code 权威指南》</li><li>《深入浅出 Vue.js》</li><li>《Vue.js 设计与实现》</li></ul><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="经历总结">经历总结<a class="hash-link" href="#经历总结" title="标题的直接链接">​</a></h2><p>相比学习记录而言，我反倒是想总结个人的一些机遇与所做（缺点与不足），以及未来遇到这类情景能否有改进的地方。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="深思熟虑">深思熟虑<a class="hash-link" href="#深思熟虑" title="标题的直接链接">​</a></h3><p>反思我当时面对这种情况，我当时的做法是否合理？是否为最优解？是否有考虑他人感受？是否有考虑这么做未来有什么不利？是否...?</p><p>事情发生后能否做到不后悔？能否想过如何挽回？能否总结下次遇到这种情况又该如何做？...(语塞片刻) 还能有下一次吗？</p><p>很显然，在这一年当中我并没有很好的反思与总结，而是直到出现一些严重性的结果，我才会开始考虑此后果与弥补。</p><p>而休学便是我当时面对情景中的做法之一。</p><p>当时的我没有思考我休学后所会给我带来的不利，如后续学校课程的变化能否顺便完成毕业，是否想过休学后的生活，复学手续的办理，等等太多要思考的了，然而当时的我只思考到学校课程的无聊，不如出去工作闯闯，这可不比学校每天枯燥的生活来的丰富。我甚至还幻想着我休学出去，技术特别厉害，是不是回去就能直接免修课程，直接当大三来读。然而这种想法的天真程度不亚于一个三岁小孩问父母我为什么不能像鸟儿一样在天空中遨游，而现实生活是你只能在地面上爬行。</p><p>在学校跟着校方的课程，修满学分，遵守学校规定，完成日常内务卫生，方可毕业。而休学就是休学，休学期间学校只保留你的学籍，你在休学期间外面所发生的一切都与学校无关，如果在休学期结束后还未办理休学手续，则视为退学处理。</p><p>到了复学的日子，当时的早上我回到学校办理复学手续，准备重归校园生活。但由于疫情的缘故，学校是不让正常进出，需要使用学校 app 上申报进出码，在当时的我无论怎么申请都无法通过，提示找不到辅导员，因为我休学期间的又重新分配了新的辅导员，也就导致我无法申报进出码，当时的保安无论如何都要学生凭进出码才可进出学校，哪怕我把学生证，以及我休学时的手续，保安与辅导员的沟通，都不允许我进去学校。即便我家属陪同的情况下，依旧等了越 10 来分钟才方可放我进入学校。</p><p>现在回想当时如果我的家属没有陪同，也许这一天这个保安都可能不放我进去，保安估计是因为不希望家属在门口等候太久，同时也因为我复学的情况，所以破例放我进入学校，办理复学手续。</p><p>扯了这么多，也该说说休学的原因了。</p><p>当时（2020 年 12 月），我写了一个软件，并将其发布到我的 QQ 空间上供他人免费使用。有人加了我微信，简单咨询下，机缘很巧，他们的工作地点离我学校仅有 5 公里，于是线下交谈了下，问我有没有兴趣开发一个软件，并提供了一些想法和规划，当然，功能和需求与我所编写的大致。加之那段时间我已经厌烦学校所教的课程，与他们不谋而合，于是伴着辍学的心态办理休学手续，在 2021 这一整年“大展身手”。</p><p>这也就是为什么我 2021 年上半年没继续学习前端，没写博客的原因。在这期间，我基本上都是在忙着对该软件的更新维护。至于说为何要休学，明明离校那么近，可以边远程边线下办公。这主要还是与我的生活态度有关，我不希望我在做任何事情的时候，突然有其他的事情来打断我现有的阶段任务，哪怕只是一点小事，都有可能导致我难以进入工作状态。我忌惮的是在同时兼顾学业与工作，到头来很有可能两者都干得一塌糊涂（不过最主要我当时的内心是非常不情愿在上课的）。于是在学业与工作上两者无法兼顾到于是就休学专心工作。</p><p>说这么多，最主要是当时的我确实不是很想在校园里呆在，与其听着学校老师教的，不如自己出去社会闯荡一番来的实在。但最终的事实告诉我，还是出来太早了，社会的经验是不断磨练学习，而不是凭自己短暂实践与猜想的，只有<strong>切身体会才能悟出真谛</strong>。</p><p>又有点扯远了，总之简单交代下休学的缘由。而在今后的未来也会有一大堆这样的例子，而所发生过的甚至能写一天。<strong>能做的仅有是保持一颗善良的心，与权衡自己内心的真实</strong></p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="如何考虑诸多结果">如何考虑诸多结果<a class="hash-link" href="#如何考虑诸多结果" title="标题的直接链接">​</a></h4><p>有很多种结果，并不是由自己所能考虑到的，哪有该如何是好。</p><p>如果之前的话，我确实不知道该如何，但现在我多半会把我所遇到的情况告诉身边的人(父母、朋友)，让他们帮我出谋划策。</p><p>他们所能给的也是建议，最终的决定权还是归咎于自己。事情的最终发展走向，也是看自己的表现。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="人情世故">人情世故<a class="hash-link" href="#人情世故" title="标题的直接链接">​</a></h3><p>在没休学前，我的情商可以说是低的离谱，一点人情世故都不会有的那种。遇到一些情况我都很直面的揭穿，没有留有一定的台阶给他人下，没有思考这样做的情况对长期利益下的影响。这里我有一个亲身例子。</p><p>当时在工作中有位用户 A 反馈了一个网站的充值系统的 bug，这个 bug 可以导致随意给任意用户充值任意金额（没听错，这个 bug 的严重程度就是如此。不过当然不是我写的，这部分核心是由当时的一个外包公司搞得）。用户 A 交代了这个 bug 是由其他用户 B 告诉他的，并没有指名 B 的真实身份，原本 B 是想告诉 A 一起薅这个网站的漏洞，但 A 觉得不妥，想和我们长期合作，并将这个 bug 反馈给了我们。如果换做你的话，你又该如何处理这种事情。</p><p>当时的我第一想法就是找到漏洞，并将该漏洞修复了，但是是否有想过，在 B 告诉 A 没多久后，网站就把这个漏洞修复了，这不就明摆告诉 B，A 把这个 bug 反馈给了网站所有者，并且出卖了他。到时候 A 和 B 的关系又会如何发展？A 是否又会认为这个网站很没有格局？最终不打算长期合作？</p><p>而这些显然不是我当时所能想到的，而是我的同事所告诉我的。接着再来说说最终这件事情是如何处理的。首先我们第一时间肯定不是修复这个 bug，而是尝试去查询一些异常数据，例如大额充值，余额异常，对比真实流水与网站流水，尽快的确保找到这个 B 用户。不过这个 B 用户做事非常小心，这些数据与真实的几乎难以排查。于是我们尝试给这个 bug 加个暗桩，只要有用户触发这个 bug 就会将数据上报，最终找到 B 用户，也就是在赌这个 B 用户还会利用这个漏洞来进行充值。</p><p>果不其然，这个 B 用户还是抱着侥幸心理触发了这个 bug，然后项目的负责人直接联系到 B，然后暗示 B 用户，说他最近账号的活跃度这么高，金额有点异常。人总是有做贼心虚的时候，和 B 用户说了一大堆道理啥的，也说明 B 的这种行为是直接利用网站漏洞来盈利，其行为是有可能构成犯罪的。可能是把 B 说怕了，也是让 B 自己说出自己利用过 Bug，也说自己把这个 Bug 告诉了几个同伙 A，C 等人。最终，修复了这个 Bug，并一一联系这些并将其获利的金额给补齐，也就没在追究。（但实际上是有一定的损失的，只要这个 bug 被发现，能做的也只有弥补损失）</p><p>现在一回想，如果不是 A 主动告诉我们，也许这 Bug 可能在长时间都无法发现。最终这个 A 也成为了我们网站的合伙人。如果当时直接修复这个 bug，失去的金额是有可能找的回来的，但 A 这个用户却再也成为不了合作伙伴。但要说 B 会知道是 A 说的吗，他也许不知道，因为自始至终都未提及过 A，但他们之间的关系会有影响吗？与直接修复 bug 的相比，我看微不足道。</p><p>身边有太多为人处世的方法、道理和经验。</p><ul><li>麻烦他人签字盖个凭证，如果态度不是很友好，并且无感激之言，会让签字的人所感厌烦，下次的签字是否会顺利？</li><li>遇到他人能否做到打个招呼，即便不是那么熟的情况下？</li><li>如果麻烦他人帮忙处理点事情，顺带带点吃的、送点礼物，那么他是否就会帮忙处理一下？</li><li>学会聆听长辈的建议，长辈所经历的远非后辈可言，都有长辈一定的道理，如果你只会觉得厌烦这些道理，那么很有可能一些长辈的经验只有自己吃过亏了才懂。</li><li>人都爱听赞美之词，能否在别人取得一定成果的时，给予一定的夸奖，对于他的心情是否也会变好？</li><li>……</li></ul><p>有些人说他不想拘泥于生活的小节，想活得无拘无束。然而绝大多数情况下是不可能的，就像上面所举的例子而言，很多小节就有很大程度决定事情最终的发展。</p><p><strong>人活着务必要懂的人情世故，合理的为人处世往往会名利兼收，而不是狼狈不堪。</strong></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="行事低调">行事低调<a class="hash-link" href="#行事低调" title="标题的直接链接">​</a></h3><p>人在外面，要尽可能保持低调，不要展现自己过多的储备与能力。</p><p>就当我而言，我复学回学校正常上课的期间，很多学校老师所教的与所问的我都悉知，但我并不会第一时间回答，甚至是不回答。因为我知道如果我一旦回答，就会显得我很专业，他人会认为我的知识面比较广，可能就会来问我问题，交流技术。这本质是好的，一是能给同学一个相对好的印象，二是对班级同学学习氛围都有一定影响。但如果我不回答，对我有害吗？并不会。但回答就有优吗？也不见得。因为随着越来越多人询问，就可能会导致本该属于我的时间，却因为这些问答所耽搁。</p><p>至于是否回答与导致的结果，就需要权衡自身当下的言语行为是否对你有利，就比如对于新室友而言，我反倒第一时间说明自己有一定的技术水平，也在外面工作过，并给他们展示一些个人项目。因为我知道他们身边有个大佬，一些技术问题就有个大腿可抱，对于人际关系与求人办事来说都是对我非常有利。</p><p>不要泄露自身的“底”，这里的“底”对于上面的例子就是技术而言，而实际生活中，“底”有可能财富，背景，智慧等等。要知道社会处处是勾心斗角，越是让他人知道你的情况，往往是对自己不利。即便此刻的他对你所述的并无兴趣，但当他需要的时候，第一时间想到的就很有可能就是你。</p><p>“财不外露”是古人总结的经验教训，低调就是最好的自我保护。这是社会上的生存法则。</p><p><strong>一时的得意洋洋会换来以后的肠子悔青，一时的众星捧月会招来以后的众人愤恨。</strong></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="言多必失">言多必失<a class="hash-link" href="#言多必失" title="标题的直接链接">​</a></h3><p>我是属于那种说几句话，就容易滔滔不绝的那种。平常聊天中，也许对方只是想问下我银行卡号是多少，而我可能已经把银行卡密码告诉他（夸张点）。直白点意思就是话很多，非常容易说出一些本不应该说的东西。像以前如果有个人偷偷告诉我一个秘密，叫我千万不要说出去，而有时候不经意间就成为了告密者。然而我本意并不想泄密，但就是因为交际中，过度不必要的话语就往往。</p><p>当然，如果说的是自己的一些事情的话，对于他人来说，可能就听听就忘了。但有很多时候说着说着就说到他人去了，这时候一些过多的言语，就可能导致一些不恰当的词语加在他人身上。</p><p>我也许做不到<strong>沉默是金</strong>的实践，但我一定明白存在的意义。不善言，那就不必言。我之前就很喜欢给别人安利些东西，具体点如技术框架这些，但大部分情况下没成功安利，哪怕我对他当下的情况进行一定的分析，并告诉他使用了对自己的提升等等。而结果往往是将我的话语当做耳边风一般，也许是我的言语没有那么说服力，又或者是他不愿尝试新事物。所以这也就是为什么我现在不喜欢安利，不想多说些什么。即便说得再多，对我来说几乎没有任何利益可言，反倒是不说，没有任何亏损。</p><p><strong>能沉默寡言就不必口若悬河</strong></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="得意忘形">得意忘形<a class="hash-link" href="#得意忘形" title="标题的直接链接">​</a></h3><p>当一个人突然对你特别好，那么这时候就需要谨慎了，很有可能自己<strong>沉浸在好处之中</strong>，而<strong>忘记所在的风险</strong>。</p><p>就比如陌生人给小孩子糖果的例子，小孩子往往容易沉浸在得到甜味之中，而不会去想陌生人会将自己处于何种地步，当然这也和小孩子没有明确的自我辨别善恶的能力有关。但换到成人年身上不妨是同一道理，只是将这里的糖果换成了其他的好处而已。</p><p>这里我想强调的是，人一旦处于高兴的状态下就容易忘记一些行为。就如酒后吐真言，在喝酒兴奋的状态，是难以有任何的危险警觉，在喝醉的情况下，可能会把自己的一切说出去，而醒后根本难以想到当时兴奋的时候竟说过这般话语。</p><p>而多数人往往容易处于这种状态，对我来说可能就是别人夸我几句，我感觉非常得意，然后又和对方说起无关该话题的内容。然后这就回到上一个口若悬河话题。</p><p>也许可能会说，为啥要如此盯防这些潜在危险，因为坏人多数都是利用这种得意忘形的状态去坑害受害者。而能做的只有时刻预防危险，因为你永远不清楚危险的来临，当危险真正来临之时，就以措手不及。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="急于求成">急于求成<a class="hash-link" href="#急于求成" title="标题的直接链接">​</a></h3><p>就如这次休学，我就巴不得早点工作，早点实现财富自由。但<strong>过早的发育，往往会迷失方向</strong>。</p><p>其实我日常编写代码的时候也是如此，有时候就是为了快点实现功能需求，就会去寻找相关功能库，就容易忽视底层实现逻辑。久而久之就成为了 CV（复制粘贴）工程师，导致一些学习本该了解的知识点，就因此忽视，直到别人的库无法实现自己的功能的，到自己实现起来可谓是愁眉苦脸的。</p><p>所以我现在心态也相对以前平坦了许多，没有之前的那种激情劲，或者说更加稳重，走一步都要稳一步。</p><p>有时候有些东西就应该顺从时间的发展，强行去改变它的发展方向有可能就得不偿失。还有，为何要急于去创造成功，而不是成功去找寻你呢？</p><p><strong>顺其自然，不失一个生活态度。</strong></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="虚假欺诈">虚假欺诈<a class="hash-link" href="#虚假欺诈" title="标题的直接链接">​</a></h3><p><a href="https://movie.douban.com/subject/1292064/" target="_blank" rel="noopener noreferrer">楚门的世界</a>中有一句台词对我印象特别深刻。</p><p><strong>外面的世界跟我给你的世界一样的虚假，有一样的谎言一样的欺诈</strong>。</p><p>外面的世界即现实，亦或者是社会。确实，这里存在太多虚伪的内容，多数人对他人的表现与自身内心存在极大差异。举个例子，一个非常普通的人，面对领导时展现积极主动，面对朋友时展现情同手足，面对亲人时展现情同骨肉，对不同的人，都有不同的表现形式，而真实的他却只有自己最清楚。可以说人本就是很虚伪的，只是这种形式在交际中被放大。</p><p>除了虚伪外，很多的还是谎言。这里举一个不那么黑暗的谎言，多数人都喜欢装逼，吹嘘自己如何如何的。将自己包装得有多么厉害，地位多么显赫。其目的也只有自己最清楚，在被这种表面所影响下，就认为他事情都相对可靠，其实不然的。</p><p>所以言语上，并不能以百分之百的确信。再好比目前互联网的新闻内容或者是短视频，我都不会去对其真实性保持绝对，至少肯定不会是完整的。因为太清楚这些内容多数是以博人眼球为目的，也许会歪曲一定的事实，营造一个绝对火爆的效果。没置身于此地，又怎敢下一断言呢。</p><p><strong>俗话说得好眼见为实，不要轻信传闻，看到的才是事实。</strong></p><p>不要轻易的他言，越是真诚的人，越是容易被欺骗。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="自我保护">自我保护<a class="hash-link" href="#自我保护" title="标题的直接链接">​</a></h2><p>这些就是我这一年的大部分社会感悟，然而事实上这仅仅只是皮毛中的皮毛，有很多不是那么友好的面我并没有用言语去展现，也难以展示。</p><p>但最终想说的是出门在外，保护好自己才是最重要的。无论是身体还是精力，起码活着是为自己而活。</p><p>同时时刻<strong>当心</strong>生活中的风险，无论大火小火最终都有可能酿成不可挽回的伤害。能做的也只有提防，警惕。</p><p>与社会相比，校园生活也确实安全多了。与你相龄的同学，很多都没有经过社会，做事处事都不会搞得如此复杂，但或多或少肯定还是存在的，只是相比社会而言没那么复杂。倒是可以说大学校园就是步入社会的一个缓冲区，缓冲区有多大，就决定在社会中你的发展效率。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="回到校园">回到校园<a class="hash-link" href="#回到校园" title="标题的直接链接">​</a></h2><p>办理完复学手续，接触了新室友，新班级，依旧还是熟悉的校园，但此时此刻却感受不到校园的气息。内心也许还停留在休学一年的风光，可身体可却要老老实实在待上两年。</p><p>每日起床，打开屏幕，查看邮件信息，吃饭，能旷的课就旷，不能旷的课就尽量去，坐下敲代码，一天的日子就这样过去了。这半年里至少有百分之 80 的日子是处于这种状态。</p><p>要说枯燥，其实也有一些乐趣，要说充实，其实也会摸点鱼。不过，这不就是大部分人的生活方式吗？以混日子的方式做着重复的事，在重复中寻求一丝不同。</p><p>在学校也没啥特殊的要求，别挂科，在读两年拿到毕业证与学位证即可。还有两年的时间发展，也许这两年是程序生涯中仅存可自由分配的时间。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="总结">总结<a class="hash-link" href="#总结" title="标题的直接链接">​</a></h2><p>要说我这一年的总结，<strong>一切行为都一定要留后路</strong>。</p><p>人生要做太多的后退路，才能够走出自己的路。过去的自己的很多决定都是不留活路，可以说是大部分的情况连后悔的机会都没有。当时的我为何要做得如此绝呢？仅仅只是鲁莽吗。不，所突显的是一个真诚的态度。如果做得任何事情都留有后路，只能说你是一个警惕的人，但不是一个真诚的人。但这个社会往往就是不需要真诚老实的人，在结果面前，这些都一文不值。越是真诚，越容易被欺骗。到头来，伤的还是真诚的人。</p><p>我高中因为一些特殊原因换过班，换完之后有一段时间非常后悔，失去(永别)日常课上课下与要好的同学。可结果已经发生了，很多东西就难以还原成最初的模样。上了大学第一学期结束，我就从数学专业转到软件工程专业，只为毕业时有个科班的资格，而现在科班在我看来一文不值，还要面临补修原专业没有的课程。但相关手续都已经办理完毕，即便撕毁手续，也无济于事。每一次的选择，都总让我觉得不值，失去的远比得到的多。</p><p>不过话也不能说的这么绝对，我高中换班让我远离那些特意”针对”我的老师（我高中学习表现特别差，属于那种差生不爱学习的，虽然现在也差不多）。我转专业也认识到一些志同道合都热爱编程的伙伴，我要是不转专业也许在这个学校里可能都难以有交集。同样的休学也让我收获了不少，社会经验与做人处事有了个质的提升。</p><p>所以高中的我特别渴求大学，在大学里不断的提升自我，也就是为什么高考一结束，我就沉浸在电脑面前，不是游戏电影，而是可创造一切的代码上。在上一学期后，想去软件工程软件。并且当我有了一定的代码基础水平，我觉得有能力去应付实际任务需求，也就办理休学手续，去完成一番“事业”。现在回到校园，同样的，我也非常渴求毕业，只为能够更早做出一番事情来。</p><p>如果有个选择让你在 40 岁前平平无奇，但在 40 岁后一鸣惊人成就一番事业，我想我肯定不会选择。我已经经历了比同龄人多的多的经历，我完全认为 30 岁就能达到 40 岁时的目标。有一个梦想叫别人 30 岁有的东西我 20 岁就要，这也是我的梦想。</p><p>为什么会休学，想必已经有了一个很明确的答案。而且我也很清楚，谁都劝不动当年的我。即便休学让我晚毕业的一年，同时还带来了各种琐事。在明知道结果的前提我依然还是会决定。</p><p>做技术写程序的不应该只有技术上的进步，更应该在友好的交互方面，这里的交互不单单是人与机的交互，而是生活中人与人，人与事之间的交互。</p><p>一个应用程序的实用性如何，很大一部分取决于交互。生活中圈子同样与他人的交互有很大牵连。代码写的再好，功能再强大，但是没有一个好的交互，用户同样不会使用。生活中，即使能力再强大，但对他人不友好、对工作不上进，也难被认可。</p><p>愿来年提升自我的同时，能够辨别是非，待人处世。修正自身缺点，发挥自有特长。不要高傲自大，不要妄自菲薄。不要只沉浸做事，而不去做人。保持原有的心态，不被大起大落所失衡。不断经历，不断收获。</p><p>愿一切安好，愿前程似锦。</p>]]></content:encoded>
            <category>年终总结</category>
            <category>summary</category>
        </item>
        <item>
            <title><![CDATA[JS代码之还原]]></title>
            <link>https://kuizuo.cn/js-code-deobfuscator</link>
            <guid>js-code-deobfuscator</guid>
            <pubDate>Sat, 25 Dec 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[基于 Babel 对 JS 代码进行混淆与还原操作的网站 JS 代码混淆与还原 (kuizuo.cn)]]></description>
            <content:encoded><![CDATA[<p>基于 Babel 对 JS 代码进行混淆与还原操作的网站 <a href="http://deobfuscator.kuizuo.cn/" target="_blank" rel="noopener noreferrer">JS 代码混淆与还原 (kuizuo.cn)</a></p><p><img loading="lazy" src="https://img.kuizuo.cn/20220131193110.png" alt="js-de-obfuscator" class="img_ev3q"></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="还原前言">还原前言<a class="hash-link" href="#还原前言" title="标题的直接链接">​</a></h2><p>AST 仅仅只是静态分析，但可以将还原出来的代码替换原来的代码，以便更好的动态分析找出相关点。在还原时，并不是所有的代码都能还原成一眼就识破代码执行逻辑的，ast 也并非万能，如果你拥有强大的 js 逆向能力，有时候动态调试甚至比 AST 静态分析来的事半功倍。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="还原不出最原始的代码">还原不出最原始的代码<a class="hash-link" href="#还原不出最原始的代码" title="标题的直接链接">​</a></h3><p>标识符是可以随便定义的，只要变量不冲突，我可以随意定义，那么就已经决定我们还原不出源代码的变量名，所以能还原的只有一些花指令，使其代码变好看，方便调试。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="还原也不是万能的">还原也不是万能的<a class="hash-link" href="#还原也不是万能的" title="标题的直接链接">​</a></h3><p>混淆的方式有很多，与之对应还原的方式也有很多，上面那套混淆的还原可能只针对那一套混淆的代码，如果拿另一份混淆过的代码，然后执行这个还原程序的话，那程序多半有可能报错。所以绝对没有万能的还原代码，所有的还原程序，都需要针对不同的混淆手段来进行处理的。</p><p><strong>我只是将我所遇到的混淆手段整合到一套代码上，而非所有的混淆手段都能进行还原处理的。</strong></p><p><strong>同时也别过于追求还原，因为还原很容易破坏原有代码，导致一些未知 bug。</strong></p><div class="theme-admonition theme-admonition-tip alert alert--success admonition_LlT9"><div class="admonitionHeading_tbUL"><span class="admonitionIcon_kALy"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>提示</div><div class="admonitionContent_S0QG"><p>如需要定制化还原，也可联系。（还是要说下，绝对无法还原出最原始代码）</p></div></div><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="例子">例子<a class="hash-link" href="#例子" title="标题的直接链接">​</a></h2><p>下文将会针对主流的一些混淆手段（至少是在我遇到的混淆中相对比较好还原的），并会附上对应代码供参考（不放置代码出处）。</p><p>接下来我将要演示一个混淆代码是如何还原的，这个例子是我第一次接触混淆的例子，也可以说是我玩的最溜的一次还原了，反正折腾了也有 4,5 来次。</p><p>贴上代码 git 地址 <a href="https://github.com/kuizuo/js-de-obfuscator/blob/main/example/deobfuscator/cx/code.js" target="_blank" rel="noopener noreferrer">js-de-obfuscator/example/deobfuscator/cx</a></p><blockquote><p>注：该 js 文件是通过工具<a href="https://www.obfuscator.io/" target="_blank" rel="noopener noreferrer">JavaScript Obfuscator Tool</a>进行混淆处理的。</p></blockquote><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="分析-ast">分析 AST<a class="hash-link" href="#分析-ast" title="标题的直接链接">​</a></h3><p>首先一定一定要将混淆的代码解析成 AST 树结构，任何混淆的还原都是如此。首先简单随便看看代码，不难发现这些代码中都有<code>'\x6a\x4b\x71\x4b'</code>这样的十六进制编码字符，可以使用现成的工具，格式化便会限制编码前的结果，不过这边使用 ast 来进行操作</p><p>通过 AST 查看 node 节点，可以发现<code>value</code>正是我们想要的数据，但这里确显示的是<code>extra.raw</code>，实际上只需要遍历到相应的节点，然后 extra 属性给删除即可，同样的 Unicode 编码也是按上述方式显示。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20211224202108279.png" alt="image-20211224202108279" class="img_ev3q"></p><p>具体遍历的代码如下</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)">// 将所有十六进制编码与Unicode编码转为正常字符</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token function" style="color:rgb(0, 0, 255)">hexUnicodeToString</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token function" style="color:rgb(0, 0, 255)">traverse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token function maybe-class-name" style="color:rgb(0, 0, 255)">StringLiteral</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token keyword" style="color:rgb(0, 0, 255)">var</span><span class="token plain"> curNode </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token keyword" style="color:rgb(0, 0, 255)">delete</span><span class="token plain"> curNode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">extra</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token function maybe-class-name" style="color:rgb(0, 0, 255)">NumericLiteral</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token keyword" style="color:rgb(0, 0, 255)">var</span><span class="token plain"> curNode </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token keyword" style="color:rgb(0, 0, 255)">delete</span><span class="token plain"> curNode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">extra</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>然后将遍历后处理过的代码与 demo.js 替换一下，方便接下来的还原处理。不过处理完还是有大部分未知的字符串需要解密，当然也有一些没处理过的代码。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="找解密函数">找解密函数<a class="hash-link" href="#找解密函数" title="标题的直接链接">​</a></h3><p>如果你尝试过静态分析该代码，会发现一些参数都通过<!-- -->_<!-- -->0x3028 来调用，像这样</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">_0x3028</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'nfkbEK'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token function" style="color:rgb(0, 0, 255)">_0x3028</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'0x0'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'jKqK'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token function" style="color:rgb(0, 0, 255)">_0x3028</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'0x1'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">')bls'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>不过认真查看会发现像成员表达式<code>MemberExpression</code>语句<code>_0x3028["nfkbEK"]</code>，但在第三条语句却定义函数<code>_0x3028</code>。其实是 js 的特性，比方说下面的代码就可以给函数添加一个自定义属性</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> </span><span class="token function-variable function" style="color:rgb(0, 0, 255)">add</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">a</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> b</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  add</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'abc'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">123</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> a </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> b</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token function" style="color:rgb(0, 0, 255)">add</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">2</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">add</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'abc'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// 3</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// 123</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>不过不影响，这里只是提一嘴，并不是代码的问题。而其中<strong><code>_0x3028</code>就是解密函数</strong>，且遍历<code>_0x3028</code>调用表达式，且参数为两个的 CallExpression。</p><p>那么接下来就要着重查看前三个语句，因为这三条语句便是这套混淆的关键所在。</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">demo.js</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">var</span><span class="token plain"> _0x34ba </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">"JcOFw4ITY8KX"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"EHrDoHNfwrDCosO6Rkw="</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token spread operator" style="color:rgb(0, 0, 0)">...</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">_0x2684bf</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> _0x5d23f1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">// 这里只是定义了一个数组乱序的函数,但是调用是在后面</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">var</span><span class="token plain"> </span><span class="token function-variable function" style="color:rgb(0, 0, 255)">_0x20d0a1</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">_0x17cf70</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">while</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token plain">_0x17cf70</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            _0x2684bf</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'push'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">_0x2684bf</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'shift'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">var</span><span class="token plain"> </span><span class="token function-variable function" style="color:rgb(0, 0, 255)">_0x1b4e1d</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword" style="color:rgb(0, 0, 255)">var</span><span class="token plain"> _0x3dfe79 </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token string-property property">'data'</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token string-property property">'key'</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'cookie'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token string-property property">'value'</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'timeout'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token string-property property">"setCookie"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">_0x41fad3</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> _0x155a1e</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> _0x2003ae</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> _0x48bb02</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token spread operator" style="color:rgb(0, 0, 0)">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token string-property property">"removeCookie"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"dev"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token string-property property">"getCookie"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">_0x23cc41</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> _0x5ea286</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                _0x23cc41 </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> _0x23cc41 </span><span class="token operator" style="color:rgb(0, 0, 0)">||</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">_0x20a5ee</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> _0x20a5ee</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token comment" style="color:rgb(0, 128, 0)">// 在这里定义了一个花指令函数调用来调用</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token keyword" style="color:rgb(0, 0, 255)">var</span><span class="token plain"> </span><span class="token function-variable function" style="color:rgb(0, 0, 255)">_0x267892</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">_0x51e60d</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> _0x57f223</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                    </span><span class="token function" style="color:rgb(0, 0, 255)">_0x51e60d</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token operator" style="color:rgb(0, 0, 0)">++</span><span class="token plain">_0x57f223</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token comment" style="color:rgb(0, 128, 0)">// 实际调用的地方</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token function" style="color:rgb(0, 0, 255)">_0x267892</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">_0x20d0a1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> _0x5d23f1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> _0x1c1cc3 </span><span class="token operator" style="color:rgb(0, 0, 0)">?</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">decodeURIComponent</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">_0x1c1cc3</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token keyword nil" style="color:rgb(0, 0, 255)">undefined</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token function" style="color:rgb(0, 0, 255)">_0x1b4e1d</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">_0x34ba</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">296</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">var</span><span class="token plain"> </span><span class="token function-variable function" style="color:rgb(0, 0, 255)">_0x3028</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">_0x2308a4</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> _0x573528</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  _0x2308a4 </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> _0x2308a4 </span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">var</span><span class="token plain"> _0x29a1e7 </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> _0x34ba</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">_0x2308a4</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token comment" style="color:rgb(0, 128, 0)">// 省略百行代码...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> _0x29a1e7</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>其中省略的代码没必要细读，因为后续都只将这三条语句写入到 node 内存中（eval），然后来调用。接下来分析每一个语句都是干嘛的。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="大数组">大数组<a class="hash-link" href="#大数组" title="标题的直接链接">​</a></h4><p>基本 99%的混淆<strong>第一条语句都是一个大数组</strong>，存放这所有加密过的字符串，而我们要做的就是找到所有加密过的字符串，将其还原。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="数组乱序">数组乱序<a class="hash-link" href="#数组乱序" title="标题的直接链接">​</a></h4><p>然后接着<strong>第二条语句一般都是自调用函数</strong>，将大数组与数组乱序数量作为参数，其中的作用是将数组进行乱序，也就是上面代码中加亮的地方，但这里只是定义了一个函数<code>_0x20d0a1</code>，而实际调用的地方 <code>_0x1b4e1d</code> 中<code>_0x3dfe79</code>.<code>getCookie</code>中调用的，上述代码中有注释。如果你是正常一步步分析还真不一定的分析的出来，这就是混淆恶心的地方。</p><p>不吹混淆了，总之只要知道第二条语句是用作数组乱序，而具体无论怎么混淆，我们都可以通过 eval 来调用一遍，详看后文代码。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="解密函数">解密函数<a class="hash-link" href="#解密函数" title="标题的直接链接">​</a></h4><p>第三条语句就是加密函数，实际上就是传入大数组的索引，然后返回数组对应的成员，只是这边将其封装成函数，相当于原本 <code>_0x34ba[0]</code> 变为<code>_0x3028("0x0", "jKqK")</code> 形式来获取原本的字符串（这里只是举例，实际还涉及到第二个参数）。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="还原字符串">还原字符串<a class="hash-link" href="#还原字符串" title="标题的直接链接">​</a></h3><p>上面说了那么多，实际上具体混淆逻辑其实根本没必要去理解，像传入的第二个参数做了啥根本无需了解，因为我们最终的目的是将 <code>_0x3028("0x0", "jKqK")</code>转为原本字符串，然后替换的当前节点的。所有只需要遍历到<code>_0x3028("0x0", "jKqK")</code>，然后<strong>执行一遍解密函数</strong>得到解密后的结果，然后替换即可。所以如何执行解密函数便是重点了。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="将解密函数添加到内存中">将解密函数添加到内存中<a class="hash-link" href="#将解密函数添加到内存中" title="标题的直接链接">​</a></h4><p>首先要将三条语句运行一遍，js 中要在运行时运行字符串的代码，就可以使用 eval，但 eval 有作用域的问题，eval 运行的代码作用范围都是局部的，如果脱离当前作用域，eval 运行的代码就相当于无效了，所有可以使用<code>window.eval</code>或<code>global.eval</code>，将其写入置全局作用域下，由于这里是 node 环境，便用<code>global.eval</code>。</p><p>截取前三条语句，使用 eval 写入内存</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)">// 拿到解密函数所在节点</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> stringDecryptFuncAst </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">program</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">body</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">2</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// 拿到解密函数的名字 也就是_0x3028</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> </span><span class="token maybe-class-name">DecryptFuncName</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> stringDecryptFuncAst</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">declarations</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">name</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> newAst </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> parser</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">parse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">''</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">newAst</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">program</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">body</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">push</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">program</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">body</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">newAst</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">program</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">body</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">push</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">program</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">body</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">newAst</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">program</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">body</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">push</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">stringDecryptFuncAst</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// 把这三部分的代码转为字符串，由于存在格式化检测，需要指定选项，来压缩代码</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> stringDecryptFunc </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">generator</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">newAst</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">compact</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">code</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// 将字符串形式的代码执行，这样就可以在 nodejs 中运行解密函数了</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">global</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">eval</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">stringDecryptFunc</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="调用解密函数">调用解密函数<a class="hash-link" href="#调用解密函数" title="标题的直接链接">​</a></h4><p>这时候，就可以使用<code>_0x3028("0x0", "jKqK")</code> 来输出解密后的结果，不过要一个个手动输入还是太麻烦了，完全可以找到<code>_0x3028</code>调用的所有地方，然后判断是否为调用表达式 CallExpression，然后使用<code>eval('_0x3028("0x0", "jKqK")')</code> 获取解密结果。这边就举一个遍历的例子。</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token function" style="color:rgb(0, 0, 255)">traverse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function maybe-class-name" style="color:rgb(0, 0, 255)">VariableDeclarator</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">// 当变量名与解密函数名相同</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">name</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token plain"> </span><span class="token maybe-class-name">DecryptFuncName</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> binding </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">scope</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">getBinding</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token maybe-class-name">DecryptFuncName</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token comment" style="color:rgb(0, 128, 0)">// 通过referencePaths可以获取所有引用的地方</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      binding </span><span class="token operator" style="color:rgb(0, 0, 0)">&amp;&amp;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        binding</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">referencePaths</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">map</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">p</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token comment" style="color:rgb(0, 128, 0)">// 判断父节点是调用表达式，且参数为两个</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">p</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">parentPath</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">isCallExpression</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token comment" style="color:rgb(0, 128, 0)">// 输出参数与解密后的结果</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> args </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> p</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">parentPath</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">arguments</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">map</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">a</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> a</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">value</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">join</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">' '</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> str </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">eval</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">p</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">parentPath</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">toString</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">args</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            p</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">parentPath</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">replaceWith</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">stringLiteral</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">str</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>在混淆的时候就提及到 binding 可以获取当前变量的作用域，而<code>binding.referencePaths</code>就可以获取到所有调用的地方，那么只需要判断是否为调用表达式，且参数是两个的情况下，然后通过 eval 执行一遍整个节点，也就是<code>eval('_0x3028("0x0", "jKqK")')</code>，然后通过 replaceWith，替换节点即可。传入的参数与加密后的结果大致展示如下，可自行运行一遍程序中<code>decStringArr()</code></p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token number" style="color:rgb(9, 134, 88)">0x0</span><span class="token plain"> jKqK </span><span class="token maybe-class-name">PdAlB</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token number" style="color:rgb(9, 134, 88)">0x1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain">bls jtvLV</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token number" style="color:rgb(9, 134, 88)">0x2</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">M10H</span><span class="token plain"> </span><span class="token maybe-class-name">SjQMk</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token number" style="color:rgb(9, 134, 88)">0x3</span><span class="token plain"> 2Q@</span><span class="token constant" style="color:rgb(129, 31, 63)">E</span><span class="token plain"> length</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token number" style="color:rgb(9, 134, 88)">0x4</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token constant" style="color:rgb(129, 31, 63)">YLR</span><span class="token plain"> length</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token number" style="color:rgb(9, 134, 88)">0x5</span><span class="token plain"> </span><span class="token maybe-class-name">QvlS</span><span class="token plain"> charCodeAt</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token number" style="color:rgb(9, 134, 88)">0x6</span><span class="token plain"> </span><span class="token maybe-class-name">YvHw</span><span class="token plain"> </span><span class="token maybe-class-name">IrwYd</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token number" style="color:rgb(9, 134, 88)">0x7</span><span class="token plain"> iLkl </span><span class="token maybe-class-name">ClOby</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token number" style="color:rgb(9, 134, 88)">0x8</span><span class="token plain"> </span><span class="token maybe-class-name">DSlT</span><span class="token plain"> console</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token spread operator" style="color:rgb(0, 0, 0)">...</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="两者代码对比">两者代码对比<a class="hash-link" href="#两者代码对比" title="标题的直接链接">​</a></h4><p>原先代码与处理后的代码对比(部分)</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">var</span><span class="token plain"> _0x505b30 </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token function" style="color:rgb(0, 0, 255)">_0x3028</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'0x0'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'jKqK'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">!==</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">_0x3028</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'0x1'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">')bls'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">var</span><span class="token plain"> _0x104ede </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">!</span><span class="token operator" style="color:rgb(0, 0, 0)">!</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">_0x3d32a2</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> _0x35fd15</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'bKNqX'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">===</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">_0x3028</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'0x2'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'M10H'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword" style="color:rgb(0, 0, 255)">var</span><span class="token plain"> _0x46992c</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          _0x1efd4e </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          _0x5cae2b </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">d</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">f</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">===</span><span class="token plain"> _0xb2c58f</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token function" style="color:rgb(0, 0, 255)">_0x3028</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'0x3'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'2Q@E'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> _0x1efd4e</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">for</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">_0x46992c </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"> _0x46992c </span><span class="token operator" style="color:rgb(0, 0, 0)">&lt;</span><span class="token plain"> _0xb2c58f</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token function" style="color:rgb(0, 0, 255)">_0x3028</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'0x4'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'[YLR'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"> _0x46992c</span><span class="token operator" style="color:rgb(0, 0, 0)">++</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">_0x1efd4e </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">_0x1efd4e </span><span class="token operator" style="color:rgb(0, 0, 0)">&lt;&lt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">_0x5cae2b </span><span class="token operator" style="color:rgb(0, 0, 0)">?</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">5</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">16</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain"> _0x1efd4e </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> _0xb2c58f</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token function" style="color:rgb(0, 0, 255)">_0x3028</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'0x5'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'QvlS'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">_0x46992c</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">_0x1efd4e </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> _0x5cae2b </span><span class="token operator" style="color:rgb(0, 0, 0)">?</span><span class="token plain"> _0x1efd4e </span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">~</span><span class="token plain">_0x1efd4e</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">2147483647</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">&amp;</span><span class="token plain"> _0x1efd4e</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">else</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword" style="color:rgb(0, 0, 255)">var</span><span class="token plain"> _0x45a8ce </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> _0x104ede</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token operator" style="color:rgb(0, 0, 0)">?</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token function" style="color:rgb(0, 0, 255)">_0x3028</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'0x6'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'YvHw'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">===</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">_0x3028</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'0x7'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'iLkl'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                that</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token function" style="color:rgb(0, 0, 255)">_0x3028</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'0x8'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'DSlT'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'log'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> func</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                that</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token function" style="color:rgb(0, 0, 255)">_0x3028</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'0x9'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'YW6h'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token function" style="color:rgb(0, 0, 255)">_0x3028</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'0xa'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'&amp;12i'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> func</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                that</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token function" style="color:rgb(0, 0, 255)">_0x3028</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'0xb'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'1jb4'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'debug'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> func</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                that</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token function" style="color:rgb(0, 0, 255)">_0x3028</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'0xc'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'k9U['</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token function" style="color:rgb(0, 0, 255)">_0x3028</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'0xd'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'nUsA'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> func</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                that</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token function" style="color:rgb(0, 0, 255)">_0x3028</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'0xe'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">')bls'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token function" style="color:rgb(0, 0, 255)">_0x3028</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'0xf'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'PZDB'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> func</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                that</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'console'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token function" style="color:rgb(0, 0, 255)">_0x3028</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'0x10'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'r8Qx'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> func</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                that</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token function" style="color:rgb(0, 0, 255)">_0x3028</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'0x11'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'AIMj'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token function" style="color:rgb(0, 0, 255)">_0x3028</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'0x12'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'[YLR'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> func</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">else</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">_0x35fd15</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token function" style="color:rgb(0, 0, 255)">_0x3028</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'0x13'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'r8Qx'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">!==</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">_0x3028</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'0x14'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'YLF%'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                    </span><span class="token keyword" style="color:rgb(0, 0, 255)">var</span><span class="token plain"> _0x1fa1e3 </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> _0x35fd15</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token function" style="color:rgb(0, 0, 255)">_0x3028</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'0x15'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'sLdn'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">_0x3d32a2</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> arguments</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                    _0x35fd15 </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword null nil" style="color:rgb(0, 0, 255)">null</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> _0x1fa1e3</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">else</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                    </span><span class="token function" style="color:rgb(0, 0, 255)">_0x142a1e</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        _0x104ede </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">!</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> _0x45a8ce</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">else</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">!</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token function" style="color:rgb(0, 0, 255)">_0x3028</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'0x16'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'Yp5j'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token function" style="color:rgb(0, 0, 255)">_0x3028</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'0x17'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">']R4I'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">_0x3028</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'0x18'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'M10H'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token function" style="color:rgb(0, 0, 255)">_0x3028</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'0x19'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'%#u0'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'stateObject'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">var</span><span class="token plain"> _0x505b30 </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'PdAlB'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">!==</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'jtvLV'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">var</span><span class="token plain"> _0x104ede </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">!</span><span class="token operator" style="color:rgb(0, 0, 0)">!</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">_0x3d32a2</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> _0x35fd15</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'bKNqX'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">===</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'SjQMk'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword" style="color:rgb(0, 0, 255)">var</span><span class="token plain"> _0x46992c</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          _0x1efd4e </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          _0x5cae2b </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">d</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">f</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">===</span><span class="token plain"> _0xb2c58f</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'length'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> _0x1efd4e</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">for</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">_0x46992c </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"> _0x46992c </span><span class="token operator" style="color:rgb(0, 0, 0)">&lt;</span><span class="token plain"> _0xb2c58f</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'length'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"> _0x46992c</span><span class="token operator" style="color:rgb(0, 0, 0)">++</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">_0x1efd4e </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">_0x1efd4e </span><span class="token operator" style="color:rgb(0, 0, 0)">&lt;&lt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">_0x5cae2b </span><span class="token operator" style="color:rgb(0, 0, 0)">?</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">5</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">16</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain"> _0x1efd4e </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> _0xb2c58f</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'charCodeAt'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">_0x46992c</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">_0x1efd4e </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> _0x5cae2b </span><span class="token operator" style="color:rgb(0, 0, 0)">?</span><span class="token plain"> _0x1efd4e </span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">~</span><span class="token plain">_0x1efd4e</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">2147483647</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">&amp;</span><span class="token plain"> _0x1efd4e</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">else</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword" style="color:rgb(0, 0, 255)">var</span><span class="token plain"> _0x45a8ce </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> _0x104ede</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token operator" style="color:rgb(0, 0, 0)">?</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'IrwYd'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">===</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'ClOby'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                that</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'console'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'log'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> func</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                that</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'console'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'warn'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> func</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                that</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'console'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'debug'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> func</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                that</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'console'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'info'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> func</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                that</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'console'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'error'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> func</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                that</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'console'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'exception'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> func</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                that</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'console'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'trace'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> func</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">else</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">_0x35fd15</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'WuEjf'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">!==</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'qpuuN'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                    </span><span class="token keyword" style="color:rgb(0, 0, 255)">var</span><span class="token plain"> _0x1fa1e3 </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> _0x35fd15</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'apply'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">_0x3d32a2</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> arguments</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                    _0x35fd15 </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword null nil" style="color:rgb(0, 0, 255)">null</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> _0x1fa1e3</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">else</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                    </span><span class="token function" style="color:rgb(0, 0, 255)">_0x142a1e</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        _0x104ede </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">!</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> _0x45a8ce</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">else</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">!</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'constructor'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'debu'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'gger'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'apply'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'stateObject'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>可以发现处理过的代码至少无需动态调用出解密后的结果，并且像<code>if ("PdAlB" !== "jtvLV")</code>这种语句都可以直接一眼看出必定为 true，但混淆后<code>if (_0x3028("0x0", "jKqK") !== _0x3028("0x1", ")bls"))</code>却无法看出，<strong>这就是 AST 静态分析的优势所在</strong>。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="删除混淆语句">删除混淆语句<a class="hash-link" href="#删除混淆语句" title="标题的直接链接">​</a></h4><p>在执行完字符串解密后，其实大数组与解密函数都已经用不到了，那么就可以通过 shift 将前三条语句给删除。</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)">// 将源代码中的解密代码给移除</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">program</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">body</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">shift</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">program</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">body</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">shift</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">program</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">body</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">shift</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>但一般<strong>不推荐删除</strong>，因为我们有可能是需要将我们还原后的代码与网站内混淆过的代码进行替换，然后再进行动态调试分析，但如果删除了这三条混淆语句，有可能会导致代码执行出错。我之前习惯删除，但直到我遇到了一个网站。。。</p><p>最终整个完成的代码在类方法<code>decStringArr</code></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="找解密函数优化">找解密函数优化<a class="hash-link" href="#找解密函数优化" title="标题的直接链接">​</a></h3><p>在上面的代码中有一段这样的代码</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">// 当变量名与解密函数名相同</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">name</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token plain"> </span><span class="token maybe-class-name">DecryptFuncName</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">// ...</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>其中这里的 DecryptFuncName 对应的是解密函数的函数名<!-- -->_<!-- -->0x3028，是通过人为定义，同时载入的是前三条语句，万一解密函数在第四条语句，或者有多个解密函数的情况下，就需要去改动代码</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)">// 拿到解密函数所在节点</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> stringDecryptFuncAst </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">program</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">body</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">2</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// 拿到解密函数的名字 也就是_0x3028</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> </span><span class="token maybe-class-name">DecryptFuncName</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> stringDecryptFuncAst</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">declarations</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">name</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> newAst </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> parser</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">parse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">''</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">newAst</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">program</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">body</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">push</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">program</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">body</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">newAst</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">program</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">body</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">push</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">program</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">body</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">newAst</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">program</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">body</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">push</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">stringDecryptFuncAst</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// 把这三部分的代码转为字符串，由于存在格式化检测，需要指定选项，来压缩代码</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> stringDecryptFunc </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">generator</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">newAst</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">compact</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">code</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>无意间翻看代码的时候，灵光一现，解密函数调用的这么频繁，我直接把所有函数都遍历一遍，并将它们的引用<code>referencePaths</code>从高到低排序，不就知道那个是解密函数了吗，于是便有了<code>findDecFunctionArr</code>方法</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="finddecfunctionarr">findDecFunctionArr<a class="hash-link" href="#finddecfunctionarr" title="标题的直接链接">​</a></h4><p>一般而言，解密函数通常是在大数组与数组乱序后定义的，在上面代码中，可以看到是通过制定下标来定位解密函数 <code>this.ast.program.body[2];</code>，所以只要能截取到这个 2 即可，具体代码</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)">/**</span><br></span><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)">   * 根据函数调用次数寻找到解密函数</span><br></span><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)">   */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">findDecFunction</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> decFunctionArr </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> index </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 定义解密函数所在语句下标</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">// 先遍历所有函数(作用域在Program)，并根据引用次数来判断是否为解密函数</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token function" style="color:rgb(0, 0, 255)">traverse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token function maybe-class-name" style="color:rgb(0, 0, 255)">Program</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">p</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        p</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">traverse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token string" style="color:rgb(163, 21, 21)">'FunctionDeclaration|VariableDeclarator'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token operator" style="color:rgb(0, 0, 0)">!</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">isFunctionDeclaration</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">||</span><span class="token plain"> t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">isFunctionExpression</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">init</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> name </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> binding </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">scope</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">getBinding</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token operator" style="color:rgb(0, 0, 0)">!</span><span class="token plain">binding</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token comment" style="color:rgb(0, 128, 0)">// 调用超过100次多半就是解密函数,具体可根据实际情况来判断</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">binding</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">referencePaths</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">length</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">100</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              decFunctionArr</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">push</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token comment" style="color:rgb(0, 128, 0)">// 根据最后一个解密函数来定义解密函数所在语句下标</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> binding </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> p</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">scope</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">getBinding</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token operator" style="color:rgb(0, 0, 0)">!</span><span class="token plain">binding</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> parent </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> binding</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">findParent</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">_p</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> _p</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">isFunctionDeclaration</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">||</span><span class="token plain"> _p</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">isVariableDeclaration</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token operator" style="color:rgb(0, 0, 0)">!</span><span class="token plain">parent</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> body </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> p</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">scope</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">block</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">body</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">for</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> i </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"> i </span><span class="token operator" style="color:rgb(0, 0, 0)">&lt;</span><span class="token plain"> body</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">length</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"> i</span><span class="token operator" style="color:rgb(0, 0, 0)">++</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> node </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> body</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">start</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token plain"> parent</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">start</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  index </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> i </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">break</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token comment" style="color:rgb(0, 128, 0)">// 遍历完当前节点,就不再往子节点遍历</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">skip</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> newAst </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> parser</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">parse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">''</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">// 插入解密函数前的几条语句</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    newAst</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">program</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">body</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">program</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">body</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">slice</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> index</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">// 把这部分的代码转为字符串，由于可能存在格式化检测，需要指定选项，来压缩代码</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> code </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">generator</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">newAst</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">compact</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">code</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">// 将字符串形式的代码执行，这样就可以在 nodejs 中运行解密函数了</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    global</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">eval</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">code</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">decFunctionArr</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> decFunctionArr</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>同时增加 decFunctionArr 属性，用于表示解密函数数组供 decStringArr 使用，就可以免去判断解密函数的步骤了。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="优化还原后的代码">优化还原后的代码<a class="hash-link" href="#优化还原后的代码" title="标题的直接链接">​</a></h2><p>就此，还原后的代码基本就能静态分析出大概，接下来都是对这份代码进行细微的优化还原。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="对象属性-改为对象属性">对象<!-- -->['属性']<!-- --> 改为对象.属性<a class="hash-link" href="#对象属性-改为对象属性" title="标题的直接链接">​</a></h3><p>与混淆对象属性相反，但其实没必要，只是代码相对而言好看一点，影响不大。具体代码如下</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token function" style="color:rgb(0, 0, 255)">changeObjectAccessMode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token function" style="color:rgb(0, 0, 255)">traverse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token function maybe-class-name" style="color:rgb(0, 0, 255)">MemberExpression</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">isStringLiteral</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">property</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> name </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">property</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">value</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                    path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">property</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">identifier</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                    path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">computed</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="还原为-boolean">还原为 Boolean<a class="hash-link" href="#还原为-boolean" title="标题的直接链接">​</a></h3><p>在还原后的代码还存在<code>!![]</code>与 <code>![]</code>或者是<code>!0</code>与<code>!1</code>，而这对应 js 中也就是<code>true</code>与<code>false</code>，所以也可以遍历这部分的代码，然后将其还原成 Boolean，像这种表达式就不细说了（有点类似 jsfuck），ast 结构自行分析。具体代码如下</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token function" style="color:rgb(0, 0, 255)">traverseUnaryExpression</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token function" style="color:rgb(0, 0, 255)">traverse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token function maybe-class-name" style="color:rgb(0, 0, 255)">UnaryExpression</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">operator</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">!==</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'!'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 避免判断成 void</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token comment" style="color:rgb(0, 128, 0)">// 判断第二个符号是不是!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">isUnaryExpression</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">argument</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">isArrayExpression</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">argument</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">argument</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// !![]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                        </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">argument</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">argument</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">elements</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">length</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                            path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">replaceWith</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">booleanLiteral</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                            path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">skip</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">else</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">isArrayExpression</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">argument</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// ![]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">argument</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">elements</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">length</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                        path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">replaceWith</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">booleanLiteral</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                        path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">skip</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">else</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">isNumericLiteral</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">argument</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// !0 or !1</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">argument</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">value</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">===</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                        path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">replaceWith</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">booleanLiteral</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">else</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">argument</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">value</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">===</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                        path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">replaceWith</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">booleanLiteral</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">else</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="计算二项式字面量">计算二项式字面量<a class="hash-link" href="#计算二项式字面量" title="标题的直接链接">​</a></h3><p>还原后的代码中还存在<code>["constructor"]("debu" + "gger")["call"]("action");</code>这样的语句，其中<code>debugger</code> 特意给拆分成两部分，而这同样可以通过 ast 来进行还原成完整字符串，同样类似的 <code>1 + 2</code> 这种字面量 都可以合并。还原程序代码如下</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token function" style="color:rgb(0, 0, 255)">traverseLiteral</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token function" style="color:rgb(0, 0, 255)">traverse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token function maybe-class-name" style="color:rgb(0, 0, 255)">BinaryExpression</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> left</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> right </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token comment" style="color:rgb(0, 128, 0)">// 判断左右两边是否为字面量</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">isLiteral</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">left</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">&amp;&amp;</span><span class="token plain"> t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">isLiteral</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">right</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> confident</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> value </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">evaluate</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 计算二项式的值</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                    confident </span><span class="token operator" style="color:rgb(0, 0, 0)">&amp;&amp;</span><span class="token plain"> path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">replaceWith</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">valueToNode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">value</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                    path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">skip</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>其中 confident 表示是否为可计算，比如说一个变量 + 1，由于程序不知道这变量此时的值，所以就不可计算，confident 也就是为 false。</p><p>同时这个计算二项式字面量可以还原一些相对简单的混淆，比方说数字异或混淆 <code>706526 ^ 706516</code>计算为 10 就可以直接替换原节点。所以这步的遍历需要相对其他还原提前一些。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="字符串和数值常量直接替换对应的变量引用地方">字符串和数值常量直接替换对应的变量引用地方<a class="hash-link" href="#字符串和数值常量直接替换对应的变量引用地方" title="标题的直接链接">​</a></h3><p>有些变量可能赋值过一次就不在进行改变，就如同常量，如下面代码。</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> a </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">100</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">a</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>那么完全可以替换成<code>console.log(100)</code> ，最终输出的效果一样，但是前提是 a 只赋值过一次，也可以说 a 必须要是变量，否则这样还原是有可能导致原有执行结果失败，而通过 binding 就能查看变量 a 的赋值历史。</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token function" style="color:rgb(0, 0, 255)">traverseStrNumValue</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token function" style="color:rgb(0, 0, 255)">traverse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token string" style="color:rgb(163, 21, 21)">'AssignmentExpression|VariableDeclarator'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> _name </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword null nil" style="color:rgb(0, 0, 255)">null</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> _initValue </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword null nil" style="color:rgb(0, 0, 255)">null</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">isAssignmentExpression</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                    _name </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">left</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                    _initValue </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">right</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">else</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                    _name </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                    _initValue </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">init</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">isStringLiteral</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">_initValue</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">||</span><span class="token plain"> t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">isNumericLiteral</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">_initValue</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> binding </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">scope</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">getBinding</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">_name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">binding </span><span class="token operator" style="color:rgb(0, 0, 0)">&amp;&amp;</span><span class="token plain"> binding</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">constant</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">&amp;&amp;</span><span class="token plain"> binding</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">constantViolations</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">length</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                        </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">for</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> i </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"> i </span><span class="token operator" style="color:rgb(0, 0, 0)">&lt;</span><span class="token plain"> binding</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">referencePaths</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">length</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"> i</span><span class="token operator" style="color:rgb(0, 0, 0)">++</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                            binding</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">referencePaths</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">replaceWith</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">_initValue</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="移除无用变量与无用代码块">移除无用变量与无用代码块<a class="hash-link" href="#移除无用变量与无用代码块" title="标题的直接链接">​</a></h3><p>上面说了有些字符串与数值常量替换，针对是只赋值过一遍的变量，但还可能存在变量未使用过的情况，遇到这种情况，我们可以判断 constantViolations 成员是否为空，然后将其删除。</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token function" style="color:rgb(0, 0, 255)">removeUnusedValue</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token function" style="color:rgb(0, 0, 255)">traverse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token function maybe-class-name" style="color:rgb(0, 0, 255)">VariableDeclarator</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> init </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token operator" style="color:rgb(0, 0, 0)">!</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">isLiteral</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">init</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">||</span><span class="token plain"> t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">isObjectExpression</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">init</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> binding </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">scope</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">getBinding</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token operator" style="color:rgb(0, 0, 0)">!</span><span class="token plain">binding </span><span class="token operator" style="color:rgb(0, 0, 0)">||</span><span class="token plain"> binding</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">constantViolations</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">length</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">binding</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">referencePaths</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">length</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">remove</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token function maybe-class-name" style="color:rgb(0, 0, 255)">FunctionDeclaration</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> binding </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">scope</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">getBinding</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token operator" style="color:rgb(0, 0, 0)">!</span><span class="token plain">binding </span><span class="token operator" style="color:rgb(0, 0, 0)">||</span><span class="token plain"> binding</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">constantViolations</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">length</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">binding</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">referencePaths</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">length</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">remove</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>同时还有一些无用代码块，比如</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">test</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'123'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">else</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token known-class-name class-name" style="color:rgb(38, 127, 153)">Math</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">floor</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">10</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">*</span><span class="token plain"> </span><span class="token known-class-name class-name" style="color:rgb(38, 127, 153)">Math</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">random</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token function" style="color:rgb(0, 0, 255)">test</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>第二条语句是绝对不会执行到的，那么就可以将其移除。虽然说代码编辑器会将其标暗，表示不会执行到，但在混淆中巴不得代码量少一下，所有还是有必要通过 AST 进行操作。</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token function" style="color:rgb(0, 0, 255)">removeUnusedBlockStatement</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token function" style="color:rgb(0, 0, 255)">traverse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token function maybe-class-name" style="color:rgb(0, 0, 255)">IfStatement</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">isBooleanLiteral</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">test</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> testValue </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">test</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">value</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">testValue </span><span class="token operator" style="color:rgb(0, 0, 0)">===</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                        path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">replaceInline</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">consequent</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">else</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">testValue </span><span class="token operator" style="color:rgb(0, 0, 0)">===</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                        path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">replaceInline</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">alternate</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>虽然说这种只针对 if 条件为 Boolean，如果条件为<code>if(1===1)</code>的情况也是可以，因为在前面还原中 计算二项式字面量，就已经将<code>if(1===1)</code> 替换成了 <code>if(true)</code>，所以这里只需要判断<code>isBooleanLiteral</code>即可。最终还原后的结果会将 if 代码块去除，同时保留 BlockStatement，代码如下</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">test</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"123"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token function" style="color:rgb(0, 0, 255)">test</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="添加注释">添加注释<a class="hash-link" href="#添加注释" title="标题的直接链接">​</a></h3><p>有些关键的代码会隐藏在 debugger，setTimeout，setInterval 等，在调试的时候都需要额外注意下是否有关键代码，所以这时候就可以添加一个注释来进行添加一个标签如 TOLOOK 来进行定位。具体根据要指定的标识符来定位，下列代码做为演示，将会在这些地方添加注释 // TOLOOK</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token function" style="color:rgb(0, 0, 255)">addComments</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token function" style="color:rgb(0, 0, 255)">traverse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token function maybe-class-name" style="color:rgb(0, 0, 255)">DebuggerStatement</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">addComment</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'leading'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">' TOLOOK'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token function maybe-class-name" style="color:rgb(0, 0, 255)">CallExpression</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token operator" style="color:rgb(0, 0, 0)">!</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'setTimeout'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'setInterval'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">includes</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">callee</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">addComment</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'leading'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">' TOLOOK'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token function maybe-class-name" style="color:rgb(0, 0, 255)">StringLiteral</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">value</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">===</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'debugger'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                    path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">addComment</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'leading'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">' TOLOOK'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="十六进制与-unicode-编码转正常字符">十六进制与 Unicode 编码转正常字符<a class="hash-link" href="#十六进制与-unicode-编码转正常字符" title="标题的直接链接">​</a></h3><p>在一开始还原的时候就调用过这个方法，不过这里要特意在说一遍，因为这套混淆十六进制是最后处理，也就是说我们一开始直接使用还原是没问题的，但如果加密的字符串中存在十六进制编码字符，而这步操作确实在解密字符串前的话，那么可能就有部分字符串还是以十六进制形式显示，所有把这个方法特意放到较后文的地方，同时这个方法也可以最后调用。</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token function" style="color:rgb(0, 0, 255)">hexUnicodeToString</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token function" style="color:rgb(0, 0, 255)">traverse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token function maybe-class-name" style="color:rgb(0, 0, 255)">StringLiteral</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token keyword" style="color:rgb(0, 0, 255)">var</span><span class="token plain"> curNode </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token keyword" style="color:rgb(0, 0, 255)">delete</span><span class="token plain"> curNode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">extra</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token function maybe-class-name" style="color:rgb(0, 0, 255)">NumericLiteral</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token keyword" style="color:rgb(0, 0, 255)">var</span><span class="token plain"> curNode </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token keyword" style="color:rgb(0, 0, 255)">delete</span><span class="token plain"> curNode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">extra</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="标识符优化">标识符优化<a class="hash-link" href="#标识符优化" title="标题的直接链接">​</a></h3><p>大部分的混淆标识符都为<!-- -->_<!-- -->0x123456 这种，但有些却很另类，比如 OOOO0o 这种，相比前面这种更容易看花眼，很容易看错代码，那么就可以将标识符都统一重命名一下。</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token function" style="color:rgb(0, 0, 255)">renameIdentifier</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> code </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">code</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> newAst </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> parser</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">parse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">code</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token function" style="color:rgb(0, 0, 255)">traverse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">newAst</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token string" style="color:rgb(163, 21, 21)">'Program|FunctionExpression|FunctionDeclaration'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">traverse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                    </span><span class="token function maybe-class-name" style="color:rgb(0, 0, 255)">Identifier</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">p</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                        path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">scope</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">rename</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">p</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">scope</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">generateUidIdentifier</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'_0xabc'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">ast</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> newAst</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>但想知道源代码的标识符是根本不可能的，所以就无法通过代码语义来理解代码了。</p><p>不过还有一些可以特定的替换，比如 for i</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">for</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">var</span><span class="token plain"> _0x1e5665 </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> _0x3620b9 </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'JIyEgF'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'length'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"> _0x1e5665 </span><span class="token operator" style="color:rgb(0, 0, 0)">&lt;</span><span class="token plain"> _0x3620b9</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"> _0x1e5665</span><span class="token operator" style="color:rgb(0, 0, 0)">++</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'JIyEgF'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'push'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token known-class-name class-name" style="color:rgb(38, 127, 153)">Math</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'round'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token known-class-name class-name" style="color:rgb(38, 127, 153)">Math</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'random'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  _0x3620b9 </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'JIyEgF'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'length'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>像这种代码，就完全可以将<code>_0x1e5665</code>替换成<code>i</code>，不过对整体阅读影响基本不大。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="其他还原手段">其他还原手段<a class="hash-link" href="#其他还原手段" title="标题的直接链接">​</a></h3><p>还有一些还原的手段就不细说了（这里例子中并未用到），比如说</p><ul><li>形参改为实参</li><li>还原 switch 执行流程</li><li>处理对象花指令</li><li>处理 eval 代码</li></ul><p>等等，总之你想咋优化都完全可以优化，但还原完的代码就不一定能看懂了。与解密字符串那个相比，如果搞不定字符串解密，那这些都是徒劳。</p><p>具体的实例可通过 <a href="https://github.com/kuizuo/js-de-obfuscator/tree/main/example/deobfuscator" target="_blank" rel="noopener noreferrer">源码例子</a> 中查看对 AST 的操作。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="运行还原后的代码">运行还原后的代码<a class="hash-link" href="#运行还原后的代码" title="标题的直接链接">​</a></h2><p>最终整个还原后的代码可以在<code>newCode.js</code>中查看，但到目前为止还没有测试还原后的代码到底能否正常运行，或者是替换节点导致语法错误，所有就需要将还原后的代码与混淆过的代码替换运行这样才能测试的出来。这里就不放具体执行过程了（因为真的懒得在处理这个 js 文件了。。。）</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="js-混淆与还原的网站">JS 混淆与还原的网站<a class="hash-link" href="#js-混淆与还原的网站" title="标题的直接链接">​</a></h2><p>针对上述还原操作其实还不够明显，于是就编写了一个在线对 JS 代码混淆与还原的网站（主要针对还原）– <a href="https://deobfuscator.kuizuo.cn/" target="_blank" rel="noopener noreferrer">JS 代码混淆与还原 (kuizuo.cn)</a></p><p>其实也就是对上述的还原代码进行封装成工具使用。</p>]]></content:encoded>
            <category>javascript</category>
            <category>ast</category>
            <category>reverse</category>
            <category>project</category>
        </item>
        <item>
            <title><![CDATA[JS代码之混淆]]></title>
            <link>https://kuizuo.cn/js-code-obfuscator</link>
            <guid>js-code-obfuscator</guid>
            <pubDate>Tue, 21 Dec 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[AST 在线解析 AST explorer]]></description>
            <content:encoded><![CDATA[<blockquote><p>AST 在线解析 <a href="https://astexplorer.net/" target="_blank" rel="noopener noreferrer">AST explorer</a></p><p>js 在线混淆工具 <a href="https://www.obfuscator.io/" target="_blank" rel="noopener noreferrer">JavaScript Obfuscator Tool</a></p><p>书籍 《反爬虫 AST 原理与还原混淆实战》</p><p>相关混淆代码 <a href="https://github.com/kuizuo/js-de-obfuscator" target="_blank" rel="noopener noreferrer">kuizuo/js-de-obfuscator</a></p><p>自写在线混淆与还原网站 <a href="http://deobfuscator.kuizuo.cn/" target="_blank" rel="noopener noreferrer">JS 代码混淆与还原 (kuizuo.cn)</a></p></blockquote><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="什么是-ast">什么是 AST<a class="hash-link" href="#什么是-ast" title="标题的直接链接">​</a></h2><p>抽象语法树（Abstract Syntax Tree），简称 AST，初识 AST 是在一门网页逆向的课程，该课程讲述了 js 代码中混淆与还原的对抗，而所使用的技术便是 AST，通过 AST 能很轻松的将 js 源代码混淆成难以辨别的代码。同样的，也可以通过 AST 将其混淆的代码 还原成执行逻辑相对正常的代码。</p><p>例如下面的代码（目的是当天时间格式化）</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token class-name" style="color:rgb(38, 127, 153)">Date</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">prototype</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method-variable function-variable method function property-access" style="color:rgb(0, 0, 255)">format</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">formatStr</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">var</span><span class="token plain"> str </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> formatStr</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">var</span><span class="token plain"> </span><span class="token maybe-class-name">Week</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'日'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'一'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'二'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'三'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'四'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'五'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'六'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  str </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">replace</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token regex regex-delimiter">/</span><span class="token regex regex-source language-regex">yyyy|YYYY</span><span class="token regex regex-delimiter">/</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">getFullYear</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  str </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">replace</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token regex regex-delimiter">/</span><span class="token regex regex-source language-regex">MM</span><span class="token regex regex-delimiter">/</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">getMonth</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">toString</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">padStart</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">2</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'0'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  str </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">replace</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token regex regex-delimiter">/</span><span class="token regex regex-source language-regex">dd|DD</span><span class="token regex regex-delimiter">/</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">getDate</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">toString</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">padStart</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">2</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'0'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> str</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">Date</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">format</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'yyyy-MM-dd'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>通过 AST 混淆的结果为</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">OOOOOO</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token string" style="color:rgb(163, 21, 21)">'eXl5eS1NTS1kZA=='</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token string" style="color:rgb(163, 21, 21)">'RGF0ZQ=='</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token string" style="color:rgb(163, 21, 21)">'cHJvdG90eXBl'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token string" style="color:rgb(163, 21, 21)">'Zm9ybWF0'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token string" style="color:rgb(163, 21, 21)">'5pel'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token string" style="color:rgb(163, 21, 21)">'5LiA'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token string" style="color:rgb(163, 21, 21)">'5LqM'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token string" style="color:rgb(163, 21, 21)">'5LiJ'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token string" style="color:rgb(163, 21, 21)">'5Zub'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token string" style="color:rgb(163, 21, 21)">'5LqU'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token string" style="color:rgb(163, 21, 21)">'5YWt'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token string" style="color:rgb(163, 21, 21)">'cmVwbGFjZQ=='</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token string" style="color:rgb(163, 21, 21)">'Z2V0RnVsbFllYXI='</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token string" style="color:rgb(163, 21, 21)">'Z2V0TW9udGg='</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token string" style="color:rgb(163, 21, 21)">'dG9TdHJpbmc='</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token string" style="color:rgb(163, 21, 21)">'cGFkU3RhcnQ='</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token string" style="color:rgb(163, 21, 21)">'MA=='</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token string" style="color:rgb(163, 21, 21)">'Z2V0RGF0ZQ=='</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token string" style="color:rgb(163, 21, 21)">'bG9n'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter constant" style="color:rgb(129, 31, 63)">OOOOOO</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> </span><span class="token parameter constant" style="color:rgb(129, 31, 63)">OOOOO0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">var</span><span class="token plain"> </span><span class="token function-variable function maybe-class-name" style="color:rgb(0, 0, 255)">OOOOOo</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter constant" style="color:rgb(129, 31, 63)">OOOOO0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">while</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token constant" style="color:rgb(129, 31, 63)">OOOOO0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token constant" style="color:rgb(129, 31, 63)">OOOOOO</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">push</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token constant" style="color:rgb(129, 31, 63)">OOOOOO</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">shift</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function maybe-class-name" style="color:rgb(0, 0, 255)">OOOOOo</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token operator" style="color:rgb(0, 0, 0)">++</span><span class="token constant" style="color:rgb(129, 31, 63)">OOOOO0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token constant" style="color:rgb(129, 31, 63)">OOOOOO</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">115918</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">^</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">115930</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token dom variable" style="color:rgb(9, 134, 88)">window</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token function" style="color:rgb(0, 0, 255)">atob</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token constant" style="color:rgb(129, 31, 63)">OOOOOO</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">694578</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">^</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">694578</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token function" style="color:rgb(0, 0, 255)">atob</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token constant" style="color:rgb(129, 31, 63)">OOOOOO</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">873625</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">^</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">873624</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token function" style="color:rgb(0, 0, 255)">atob</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token constant" style="color:rgb(129, 31, 63)">OOOOOO</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">219685</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">^</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">219687</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter constant" style="color:rgb(129, 31, 63)">OOOOO0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">OOOO00</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter constant" style="color:rgb(129, 31, 63)">OOOOOO</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> </span><span class="token parameter constant" style="color:rgb(129, 31, 63)">OOOOO0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">OOOOOO</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">OOOOO0</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">var</span><span class="token plain"> </span><span class="token maybe-class-name">OOOOOo</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">OOOOO0</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">var</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">OOOO0O</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token function" style="color:rgb(0, 0, 255)">atob</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token constant" style="color:rgb(129, 31, 63)">OOOOOO</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">945965</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">^</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">945966</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token function" style="color:rgb(0, 0, 255)">atob</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token constant" style="color:rgb(129, 31, 63)">OOOOOO</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">298561</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">^</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">298565</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token function" style="color:rgb(0, 0, 255)">atob</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token constant" style="color:rgb(129, 31, 63)">OOOOOO</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">535455</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">^</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">535450</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token function" style="color:rgb(0, 0, 255)">atob</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token constant" style="color:rgb(129, 31, 63)">OOOOOO</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">193006</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">^</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">193000</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token function" style="color:rgb(0, 0, 255)">atob</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token constant" style="color:rgb(129, 31, 63)">OOOOOO</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">577975</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">^</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">577968</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token function" style="color:rgb(0, 0, 255)">atob</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token constant" style="color:rgb(129, 31, 63)">OOOOOO</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">428905</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">^</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">428897</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token function" style="color:rgb(0, 0, 255)">atob</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token constant" style="color:rgb(129, 31, 63)">OOOOOO</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">629582</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">^</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">629575</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token maybe-class-name">OOOOOo</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token maybe-class-name">OOOOOo</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token function" style="color:rgb(0, 0, 255)">atob</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token constant" style="color:rgb(129, 31, 63)">OOOOOO</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">607437</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">^</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">607431</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token regex regex-delimiter">/</span><span class="token regex regex-source language-regex">yyyy|YYYY</span><span class="token regex regex-delimiter">/</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token function" style="color:rgb(0, 0, 255)">atob</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token constant" style="color:rgb(129, 31, 63)">OOOOOO</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">799010</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">^</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">799017</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token maybe-class-name">OOOOOo</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token maybe-class-name">OOOOOo</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token function" style="color:rgb(0, 0, 255)">atob</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token constant" style="color:rgb(129, 31, 63)">OOOOOO</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">518363</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">^</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">518353</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token regex regex-delimiter">/</span><span class="token regex regex-source language-regex">MM</span><span class="token regex regex-delimiter">/</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token constant" style="color:rgb(129, 31, 63)">OOOO00</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token function" style="color:rgb(0, 0, 255)">atob</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token constant" style="color:rgb(129, 31, 63)">OOOOOO</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">862531</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">^</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">862543</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">671347</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">^</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">671346</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token function" style="color:rgb(0, 0, 255)">atob</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token constant" style="color:rgb(129, 31, 63)">OOOOOO</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">822457</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">^</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">822452</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token function" style="color:rgb(0, 0, 255)">atob</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token constant" style="color:rgb(129, 31, 63)">OOOOOO</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">974597</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">^</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">974603</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">741860</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">^</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">741862</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">atob</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token constant" style="color:rgb(129, 31, 63)">OOOOOO</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">544174</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">^</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">544161</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token maybe-class-name">OOOOOo</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token maybe-class-name">OOOOOo</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token function" style="color:rgb(0, 0, 255)">atob</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token constant" style="color:rgb(129, 31, 63)">OOOOOO</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">406915</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">^</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">406921</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token regex regex-delimiter">/</span><span class="token regex regex-source language-regex">dd|DD</span><span class="token regex regex-delimiter">/</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token function" style="color:rgb(0, 0, 255)">atob</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token constant" style="color:rgb(129, 31, 63)">OOOOOO</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">596004</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">^</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">596020</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token function" style="color:rgb(0, 0, 255)">atob</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token constant" style="color:rgb(129, 31, 63)">OOOOOO</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">705321</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">^</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">705316</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token function" style="color:rgb(0, 0, 255)">atob</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token constant" style="color:rgb(129, 31, 63)">OOOOOO</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">419232</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">^</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">419246</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">318456</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">^</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">318458</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">atob</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token constant" style="color:rgb(129, 31, 63)">OOOOOO</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">662337</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">^</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">662350</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token maybe-class-name">OOOOOo</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token function" style="color:rgb(0, 0, 255)">atob</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token constant" style="color:rgb(129, 31, 63)">OOOOOO</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">490983</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">^</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">490998</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">window</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token function" style="color:rgb(0, 0, 255)">atob</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token constant" style="color:rgb(129, 31, 63)">OOOOOO</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">116866</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">^</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">116866</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token function" style="color:rgb(0, 0, 255)">atob</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token constant" style="color:rgb(129, 31, 63)">OOOOOO</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">386287</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">^</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">386285</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token function" style="color:rgb(0, 0, 255)">atob</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token constant" style="color:rgb(129, 31, 63)">OOOOOO</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">530189</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">^</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">530207</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>将上述代码复制到浏览器控制台内执行，将会输出当天的年月日。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="ast-有什么用">AST 有什么用<a class="hash-link" href="#ast-有什么用" title="标题的直接链接">​</a></h3><p>除了上述的混淆代码，很多文本编辑器中也会使用到，例如：</p><ul><li>编辑器的错误提示、代码格式化、代码高亮、代码自动补全；</li><li><code>elint</code>、<code>pretiier</code> 对代码错误或风格的检查；</li><li><code>webpack</code> 通过 <code>babel</code> 转译 <code>javascript</code> 语法；</li></ul><p>不过本篇并非介绍 AST 的基本概念，看本篇你只需要知道<strong>如何通过 babel 编译器生成 AST 并完成上述的混淆操作</strong>即可。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="有必要学-ast-吗">有必要学 AST 吗<a class="hash-link" href="#有必要学-ast-吗" title="标题的直接链接">​</a></h3><p>如果作为 JS 开发者并且想要深入了解 V8 编译，那么 AST 基本是必修课之一，像 Vue,React 主流的前端框架都使用到 AST 对代码进行编译，在 ast 学习中定能让你对 JS 语法有一个更深入的了解。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="ast-误区">AST 误区<a class="hash-link" href="#ast-误区" title="标题的直接链接">​</a></h3><p>AST 本质上是静态分析，静态分析是在不需要执行代码的前提下对代码进行分析的处理过程，与动态分析不同，静态分析的目的是多种多样的， 它可用于语法检查，编译，代码高亮，代码转换，优化，压缩等等场景。即便你的程序也许在运行时报错，但都不会影响 AST 解析（除非语法错误），在 js 逆向中，通过静态分析还原出相对容易看的出的代码有对于代码分析，而对于一些需要知道某一变量执行后的结果静态分析是做不到的。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="环境安装">环境安装<a class="hash-link" href="#环境安装" title="标题的直接链接">​</a></h2><p>首先需要 Node 环境，这就不介绍了，其次工具 Babel 编译器可通过 npm 安装</p><div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">npm i @babel/core -S-D</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>安装代码提示</p><div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">npm i @types/node @types/babel__traverse @types/babel__generator -D</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>新建 js 文件，导入相关模块（也可使用 ES module 导入），大致代码如下</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> fs </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">require</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'fs'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> parser </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">require</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'@babel/parser'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> traverse </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">require</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'@babel/traverse'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token keyword module" style="color:rgb(0, 0, 255)">default</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> t </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">require</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'@babel/types'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> generator </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">require</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'@babel/generator'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token keyword module" style="color:rgb(0, 0, 255)">default</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> jscode </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> fs</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">readFileSync</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">__dirname </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"/demo.js"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">encoding</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"utf-8"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// 解析为AST</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> ast </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> parser</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">parse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">jscode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// 转化特征代码</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token function" style="color:rgb(0, 0, 255)">traverse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token spread operator" style="color:rgb(0, 0, 0)">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// 生成转化后的代码</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> code </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">generator</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">code</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>babel 的编译过程主要有三个阶段</p><ol><li>解析(Parse): 将输入字符流解析为 AST 抽象语法树</li><li>转化(Transform): 对抽象语法树进一步转化</li><li>生成(Generate): 根据转化后的语法树生成目标代码</li></ol><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="ast-的-api">AST 的 API<a class="hash-link" href="#ast-的-api" title="标题的直接链接">​</a></h2><p>在进行编译前，首先需要了解 Babel 的一些相关 API，这边所选择的是 babel/parser 库作为解析，还有一个在线 ast 解析网站<a href="https://astexplorer.net/" target="_blank" rel="noopener noreferrer">AST explorer</a> 能帮助我们有效的了解 AST 中的树结构。</p><p>同时 Babel 手册(中文版) <a href="https://github.com/jamiebuilds/babel-handbook/blob/master/translations/zh-Hans/plugin-handbook.md" target="_blank" rel="noopener noreferrer">babel-handbook</a>强烈建议反复阅读，官方的例子远比我所描述来的详细。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20211212151620278.png" alt="image-20211212151620278" class="img_ev3q"></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="例子">例子<a class="hash-link" href="#例子" title="标题的直接链接">​</a></h3><p>这边就举一个非常简单的例子，混淆变量名（或说标识符混淆）感受一下。引用网站代码例子</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)">/**</span><br></span><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)"> * Paste or drop some JavaScript here and explore</span><br></span><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)"> * the syntax tree created by chosen parser.</span><br></span><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)"> * You can use all the cool new features from ES6</span><br></span><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)"> * and even more. Enjoy!</span><br></span><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> tips </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token string" style="color:rgb(163, 21, 21)">"Click on any AST node with a '+' to expand it"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token string" style="color:rgb(163, 21, 21)">'Hovering over a node highlights the \</span><br></span><span class="token-line" style="color:#000000"><span class="token string" style="color:rgb(163, 21, 21)">   corresponding location in the source code'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token string" style="color:rgb(163, 21, 21)">'Shift click on an AST node to expand the whole subtree'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">printTips</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  tips</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">forEach</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">tip</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> i</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string string" style="color:rgb(163, 21, 21)">Tip </span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">${</span><span class="token template-string interpolation">i</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token template-string string" style="color:rgb(163, 21, 21)">:</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> tip</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>比如说，我要将这个 tips 标识符更改为<code>_0xabcdef</code> ，那么肯定是需要找到这个要 tips，在 Babel 中要找到这个则可以通过遍历特部位（如函数表达式，变量声明等等）。</p><p>鼠标点击这个 tips 查看 tips 变量在树节点中的节点。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20211212170832228.png" alt="image-20211212170832228" class="img_ev3q"></p><p>这边可以看到有两个蓝色标记的节点，分别是<code>VariableDeclaration</code>和<code>VariabelDeclarator</code>，翻译过来便是变量声明与变量说明符，很显然整个<code>let tips = [ ]</code> 是<code>VariableDeclaration</code>，而<code>tips</code>则是<code>VariabelDeclarator</code>。</p><p>所以要将<code>tips</code>更改为<code>_0xabcdef</code>就需要遍历<code>VariabelDeclarator</code>并判断属性<code>name</code>是否为<code>tips</code>，大致代码如下。<strong>（后文代码将会省略模块引入、js 代码读取、解析与生成的代码）</strong></p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> fs </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">require</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'fs'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> parser </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">require</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'@babel/parser'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> traverse </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">require</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'@babel/traverse'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token keyword module" style="color:rgb(0, 0, 255)">default</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> t </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">require</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'@babel/types'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> generator </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">require</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'@babel/generator'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token keyword module" style="color:rgb(0, 0, 255)">default</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> jscode </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> fs</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">readFileSync</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">__dirname </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'/demo.js'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">encoding</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'utf-8'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> ast </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> parser</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">parse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">jscode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token function" style="color:rgb(0, 0, 255)">traverse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function maybe-class-name" style="color:rgb(0, 0, 255)">VariableDeclarator</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> name </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">name</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">name </span><span class="token operator" style="color:rgb(0, 0, 0)">===</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'tips'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> binding </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">scope</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">getOwnBinding</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      binding</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">scope</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">rename</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'_0xabcdef'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> code </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">generator</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">code</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>生成的代码如下，成功的将<code>tips</code>更改为<code>_0xabcdef</code>，并且是<code>tips</code>的所有作用域（printTips 函数下）都成功替换了。</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)">/**</span><br></span><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)"> * Paste or drop some JavaScript here and explore</span><br></span><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)"> * the syntax tree created by chosen parser.</span><br></span><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)"> * You can use all the cool new features from ES6</span><br></span><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)"> * and even more. Enjoy!</span><br></span><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> _0xabcdef </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">"Click on any AST node with a '+' to expand it"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Hovering over a node highlights the \</span><br></span><span class="token-line" style="color:#000000"><span class="token string" style="color:rgb(163, 21, 21)">   corresponding location in the source code"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> "</span><span class="token maybe-class-name">Shift</span><span class="token plain"> click on an </span><span class="token constant" style="color:rgb(129, 31, 63)">AST</span><span class="token plain"> node to</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">expand the whole subtree"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">printTips</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  _0xabcdef</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">forEach</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">tip</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> i</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string string" style="color:rgb(163, 21, 21)">Tip </span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">${</span><span class="token template-string interpolation">i</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token template-string string" style="color:rgb(163, 21, 21)">:</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> tip</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>简单描述下上述代码的过程</p><p>1、遍历所有<code>VariableDeclarator</code>节点，也就是<code>tips</code>变量说明符（标识符）</p><p>2、获取当前遍历到的标识符的 name，也就是<code>path.node.id.name</code>，在树节点是对应的也是<code>id.name</code></p><p>3、判断 name 是否等于 tips，是的话，通过<code>path.scope.getOwnBinding(name)</code>，获取当前标识符（tips）的作用域，scope 的意思就是作用域，如果只是赋值操作的话如<code>path.node.id.name = '_0xabcdef'</code>，那只修改的<code>let tips =</code> 的 tips，而后面的对 tips 进行<code>forEach</code>操作的 tips 并不会更改，所以这里才需要使用<code>binding</code>来获取 tips 的作用域，并调用提供好的<code>rename</code>方法来进行更改。</p><p>4、调用<code>binding.scope.rename(name, '_0xabcdef')</code>，将旧名字 name（tips）更改为<!-- -->_<!-- -->0xabcdef，就此整个遍历就结束，此时的 ast 已经发生了变化，所以只需要根据遍历过的 ast 生成代码便可得到修改后的代码。</p><p>如果在仔细观察的话，其实<code>Identifier</code>（标识符）也是蓝色表示的，说明<code>Identifier</code>也同样可以遍历，甚至比上面的效果更好（后续替换所有的标识符也是遍历这个）</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token function" style="color:rgb(0, 0, 255)">traverse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function maybe-class-name" style="color:rgb(0, 0, 255)">Identifier</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line theme-code-block-highlighted-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> name </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">name</span><span class="token plain"></span><br></span><span class="token-line theme-code-block-highlighted-line" style="color:#000000"><span class="token plain">    </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">name </span><span class="token operator" style="color:rgb(0, 0, 0)">===</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'tips'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> binding </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">scope</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">getOwnBinding</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      binding</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">scope</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">rename</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'_0xabcdef'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>并尝试输出所有的标识符，输出的 name 结果为</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">tips</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">printTips</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">_0xabcdef</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">forEach</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">tip</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">i</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">console</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">log</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">i</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">tip</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>这个例子也许有点啰嗦，但我认为是有必要的，同时想说的是某种混淆（还原）的实现往往可以有好几种方法遍历，会懂得融会贯通，AST 混淆与还原才能精通。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="parser-与-generator">parser 与 generator<a class="hash-link" href="#parser-与-generator" title="标题的直接链接">​</a></h3><p>前者用于将 js 代码解析成 AST，后者则是将 AST 转为 js 代码，两者的具体参数可通过 babel 手册查看，这就不做过多介绍了。</p><p><a href="https://github.com/jamiebuilds/babel-handbook/blob/master/translations/en/plugin-handbook.md#babel-parser" target="_blank" rel="noopener noreferrer">babel-handbook #babel-parser</a></p><p><a href="https://github.com/jamiebuilds/babel-handbook/blob/master/translations/en/plugin-handbook.md#babel-generator" target="_blank" rel="noopener noreferrer">babel-handbook #babel-generator</a></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="traverse-与-visitor">traverse 与 visitor<a class="hash-link" href="#traverse-与-visitor" title="标题的直接链接">​</a></h3><p>整个 ast 混淆还原最关键的操作就是遍历，而 visitor 则是根据特定标识（函数声明，变量订阅）来进行遍历各个节点，而非无意义的全部遍历。</p><p>traverse 一共有两个参数，第一个就是 ast，第二个是 visitor，而 visitor 本质是一个对象如下(分别有 JavaScript 和 TypeScript 版本，区别就是在于这样定义的 visitor 是否有代码提示)</p><div class="tabs-container tabList__CuJ"><ul role="tablist" aria-orientation="horizontal" class="tabs"><li role="tab" tabindex="0" aria-selected="true" class="tabs__item tabItem_LNqP tabs__item--active">JS</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">TS</li></ul><div class="margin-top--md"><div role="tabpanel" class="tabItem_Ymn6"><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> visitor </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function maybe-class-name" style="color:rgb(0, 0, 255)">FunctionDeclaration</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 输出函数名</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-tsx codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> visitor</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token maybe-class-name">Visitor</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">FunctionDeclaration</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 输出函数名</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></div></div></div><p>一般来说，都是直接写到写到 traverse 内。个人推荐这种写法，因为能有 js 的代码提示，如果是 TypeScript 效果也一样。</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token function" style="color:rgb(0, 0, 255)">traverse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function maybe-class-name" style="color:rgb(0, 0, 255)">FunctionDeclaration</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 输出函数名</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>如果我想遍历函数声明与二项式表达式的话，还可以这么写</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token function" style="color:rgb(0, 0, 255)">traverse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token string" style="color:rgb(163, 21, 21)">'FunctionDeclaration|BinaryExpression'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> node </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">isFunctionDeclaration</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 输出函数名 printTips</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">else</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">isBinaryExpression</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">operator</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 输出操作符 +</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>不过要遍历不同类型的代码，那么对应的 node 属性肯定大不相同，其中这里使用了 t（也就是<code>@babel/types</code>库）来进行判断 node 节点是否为该属性，来进行不同的操作，后文会提到 types。</p><p>上述操作将会输出 <code>printTips</code> 与 <code>+</code> 因为 printTips 函数中代码有 <code>Tip ${i}: + tip</code> ，这就是一个二项式表达式。</p><p>此外 visitor 中的属性中，还对应两个生命周期函数 enter(进入节点)和 exit(退出节点)，可以在这两个周期内进行不同的处理操作，演示代码如下。</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token function" style="color:rgb(0, 0, 255)">traverse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">FunctionDeclaration</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token function" style="color:rgb(0, 0, 255)">enter</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'进入函数声明'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token function" style="color:rgb(0, 0, 255)">exit</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'退出函数声明'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>其中 enter 与 exit 还可以是一个数组（当然基本没怎么会用到），比如</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token function" style="color:rgb(0, 0, 255)">traverse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">FunctionDeclaration</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">enter</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'1'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'2'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>path 对象下还有一种方法，针对当前 path 进行遍历 <code>path.traverse</code>，比如下面代码中，我遍历到了 printTips，我想输出函数内的箭头函数中的参数，那么就可以使用这种遍历。</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">printTips</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  tips</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">forEach</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">tip</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> i</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string string" style="color:rgb(163, 21, 21)">Tip </span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">${</span><span class="token template-string interpolation">i</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token template-string string" style="color:rgb(163, 21, 21)">:</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> tip</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>此时的 path.traverse 的第一个参数便不是 ast 对象了，而是一个 visitor 对象</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token function" style="color:rgb(0, 0, 255)">traverse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function maybe-class-name" style="color:rgb(0, 0, 255)">FunctionDeclaration</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">traverse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token function maybe-class-name" style="color:rgb(0, 0, 255)">ArrowFunctionExpression</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">params</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>输出的结果如下</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token maybe-class-name">Node</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">type</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'Identifier'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">start</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">40</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">end</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">43</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">loc</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token maybe-class-name">SourceLocation</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">start</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token maybe-class-name">Position</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">end</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token maybe-class-name">Position</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">filename</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token keyword nil" style="color:rgb(0, 0, 255)">undefined</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">identifierName</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'tip'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">name</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'tip'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token maybe-class-name">Node</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">type</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'Identifier'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">start</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">45</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">end</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">46</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">loc</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token maybe-class-name">SourceLocation</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">start</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token maybe-class-name">Position</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">end</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token maybe-class-name">Position</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">filename</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token keyword nil" style="color:rgb(0, 0, 255)">undefined</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">identifierName</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'i'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">name</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'i'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="types">types<a class="hash-link" href="#types" title="标题的直接链接">​</a></h3><p>该库主要的作用是判断节点类型与生成新的节点。判断节点类型上面已经演示过了，比如判断 node 节点是否是为标识符<code>t.isIdentifier(path.node)</code>，等同于<code>path.node.type === "Identifier"</code></p><p>判断节点类型是很重要的一个环节，有时候混淆需要针对很多节点进行操作，但并不是每个节点都有相同的属性，判断节点才不会导致获取到的节点属性出错，甚至可以写下面的代码（将输出所有函数声明与箭头函数的参数）。</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token function" style="color:rgb(0, 0, 255)">traverse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">enter</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">isFunctionDeclaration</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">&amp;&amp;</span><span class="token plain"> </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">params</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">isArrowFunctionExpression</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">&amp;&amp;</span><span class="token plain"> </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">params</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>types 的主要用途还是构造节点，或者说写一个 Builders（构建器），例如我要生成 <code>let a = 100</code> 这样的变量声明原始代码，通过 types 能轻松帮我们生成。</p><p>不过先别急着敲代码，把<code>let a = 100</code>代码进行 ast 解析，看看每个代码的节点对应的 type 都是什么，这样才有助于生成该代码。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20211216131627955.png" alt="image-20211216131627955" class="img_ev3q"></p><p>body 内的第一个节点便是我们整条的代码，输入<code>t.variableDeclaration()</code>，鼠标悬停在 variableDeclaration 上，或者按 Ctrl 跳转只.d.ts 类型声明文件 查看该方法所需几个参数</p><div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">declare</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">variableDeclaration</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">kind</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'var'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'let'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'const'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> declarations</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(0, 112, 193)">Array</span><span class="token operator" style="color:rgb(0, 0, 0)">&lt;</span><span class="token plain">VariableDeclarator</span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> VariableDeclaration</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>可以看到第一个参数就是关键字，而第二个则一个数组，其中节点为<code>VariableDeclarator</code>，关于<code>variableDeclaration</code>与 <code>VariableDeclarator</code> 在前面已经提及过一次了，就不在赘述了。由于我们这里只是声明一个变量 a，所有数组成员只给一个便可，如果要生成 b，c 这些变量，就传入对应的<code>VariableDeclarator</code>即可</p><p>这时候在查看下 VariableDeclarator 方法参数</p><div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">declare</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">variableDeclarator</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">id</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> LVal</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> init</span><span class="token operator" style="color:rgb(0, 0, 0)">?</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> Expression </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">null</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> VariableDeclarator</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>第一个参数 id 很显然就是标识符了，不过这里的 id 不能简简单单传入一个字符串 a，而需要通过<code>t.identifier('a')</code>生成该节点，在上图中 id 就是对应<code>Identifier</code>节点。然后就是第二个参数了，一个表达式，其中这个<code>Expression</code>是 ts 中的联合类型（Union Types），可以看到有很多表达式</p><div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">declare</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">type</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">Expression</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> ArrayExpression</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> AssignmentExpression</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> BinaryExpression</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> CallExpression</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> ConditionalExpression</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> FunctionExpression</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> Identifier</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> StringLiteral</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> NumericLiteral</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> NullLiteral</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> BooleanLiteral</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> RegExpLiteral</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> LogicalExpression</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> MemberExpression</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> NewExpression</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> ObjectExpression</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> SequenceExpression</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> ParenthesizedExpression</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> ThisExpression</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> UnaryExpression</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> UpdateExpression</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> ArrowFunctionExpression</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> ClassExpression</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> MetaProperty</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> Super</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> TaggedTemplateExpression</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> TemplateLiteral</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> YieldExpression</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> AwaitExpression</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> Import</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> BigIntLiteral</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> OptionalMemberExpression</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> OptionalCallExpression</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> TypeCastExpression</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> JSXElement</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> JSXFragment</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> BindExpression</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> DoExpression</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> RecordExpression</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> TupleExpression</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> DecimalLiteral</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> ModuleExpression</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> TopicReference</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> PipelineTopicExpression</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> PipelineBareFunction</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> PipelinePrimaryTopicReference</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> TSAsExpression</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> TSTypeAssertion</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain"> TSNonNullExpression</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>其中我们所要赋值的数值 100，对应的节点类型<code>NumericLiteral</code>也在其中。在查看 numericLiteral 中的参数，就只给一个数值，那么便传入 100。</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">declare </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">numericLiteral</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter literal-property property">value</span><span class="token parameter operator" style="color:rgb(0, 0, 0)">:</span><span class="token parameter"> number</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token maybe-class-name">NumericLiteral</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>最后整个代码如下，将 t.variableDeclaration 结果赋值为一个变量<code>var_a</code>，这里的 var_a 便是一个 ast 对象，通过 generator(var_a).code 就可以获取到该 ast 的代码，也就是 <code>let a = 100;</code>，默认还会帮你添加分号</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> var_a </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">variableDeclaration</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'let'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">variableDeclarator</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">identifier</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'a'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">numericLiteral</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">100</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> code </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">generator</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">var_a</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">code</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// let a = 100;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>这边再列举一个生成函数声明代码的例子（不做解读），要生成的代码如下</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">b</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">x</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> y</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> x </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> y</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>types 操作</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> param_x </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">identifier</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'x'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> param_y </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">identifier</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'y'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> func_b </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">functionDeclaration</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">identifier</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'b'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">param_x</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> param_y</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">blockStatement</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">returnStatement</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">binaryExpression</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'+'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> param_x</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> param_y</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> code </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">generator</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">func_b</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">code</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>大致步骤可以总结成一下几点</p><p>1、将要生成的 js 代码进行 ast Explorer 查看树结构，理清所要构造的代码节点（很重要）</p><p>2、找到最顶层的结果，如 variableDeclaration，查看该代码所对应的参数</p><p>3、进一步的分析内层节点结构，构造出最终的原始代码。</p><p>types 还有一个方法<code>valueToNode</code>，先看演示</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> arr_c </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">valueToNode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">2</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">3</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">4</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">5</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">arr_c</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">type</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'ArrayExpression'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">elements</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">type</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'NumericLiteral'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">value</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">type</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'NumericLiteral'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">value</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">2</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">type</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'NumericLiteral'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">value</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">3</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">type</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'NumericLiteral'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">value</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">4</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">type</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'NumericLiteral'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">value</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">5</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>如果使用<code>numericLiteral</code>来生成这些字面量的话那要写的话代码可能就要像下面这样</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> arr_c </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">arrayExpression</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">numericLiteral</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">numericLiteral</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">2</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">numericLiteral</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">3</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">numericLiteral</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">4</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">numericLiteral</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">5</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>而<code>valueToNode</code>能很方便地生成各种基本类型，甚至是一些对象类型（RegExp，Object 等）。不过像函数这种就不行。</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">valueToNode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">b</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">x</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> y</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> x </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> y</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// throw new Error("don't know how to turn this value into a node");</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>写到着，其实不难发现，每个 node 节点其实就是一个 json 对象，而 types 只是将其封装好方法，供使用者调用，像下面这样方式定义 arr_c，同样也能生成数组 <!-- -->[1, 2, 3, 4, 5]</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> arr_c </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">type</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'ArrayExpression'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">elements</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">type</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'NumericLiteral'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">value</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">type</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'NumericLiteral'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">value</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">2</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">type</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'NumericLiteral'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">value</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">3</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">type</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'NumericLiteral'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">value</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">4</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">type</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'NumericLiteral'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">value</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">5</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> code </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">generator</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">arr_c</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">code</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>至于生成其他的语句，原理与上述一致，篇幅有限不在做其他例子演示了，Babel 中的 API 很多，最主要的是懂得善用手册与代码提示，没有什么生成不了的语句，更没有还原不了的代码。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="path">Path<a class="hash-link" href="#path" title="标题的直接链接">​</a></h3><p>上述讲了基本的库操作，不难发现，使用到最多的还是 traverse，并且都会传入一个参数 path，并且<code>path.node</code>使用到的频率很多，能理解请两个的区别（Node 与 NodePath），基本上你想遍历到的地方就没有遍历不到的。</p><p>先说说 path 能干嘛，能停止遍历当前节点 （<code>path.stop</code>），能跳过当前节点（<code>path.skip</code>），还可以获取父级 path（<code>path.parentPath</code> ），替换当前节点（<code>path.replaceWith</code>），移除当前节点（<code>path.remove</code>）等等。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="获取-node-节点属性">获取 Node 节点属性<a class="hash-link" href="#获取-node-节点属性" title="标题的直接链接">​</a></h4><p><strong><code>path.node</code></strong> 也就是当前节点所在的 Node 对象，比如<code>loc</code>、<code>id</code>、<code>init</code>，<code>param</code>、<code>name</code>等，这些都是在 node 对象下都是能直接获取到的。</p><p>不过获取到的是 node 对象，就无法使用 path 对象的方法了，如果要获取该属性的 path，就可以使用<code>path.get('name')</code>，获取到的就是 path 对象。不过对于一些特定的属性（name，operator）获取 path 对象就多此一举了。</p><p>一共有两种类型 <code>Node</code> 与 <code>NodePath</code>，记住有<code>Path</code>则是<code>path</code>，如<code>path</code>就属于<code>NodePath</code>，而<code>path.node</code> 属于<code>Node</code>。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20211213021420326.png" alt="image-20211213021420326" class="img_ev3q"></p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="将节点转为代码">将节点转为代码<a class="hash-link" href="#将节点转为代码" title="标题的直接链接">​</a></h4><p>有时候遍历到一系列的代码，想输出一下原始代码，那么有以下两种方式。</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token function" style="color:rgb(0, 0, 255)">traverse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function maybe-class-name" style="color:rgb(0, 0, 255)">FunctionDeclaration</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token function" style="color:rgb(0, 0, 255)">generator</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">code</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">toString</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="替换节点属性">替换节点属性<a class="hash-link" href="#替换节点属性" title="标题的直接链接">​</a></h4><p>与获取节点属性相同，比如我需要修改函数的第一个参数，那么我只要获取到第一个参数，并且将值赋值为我想修改值（node 对象）便可。</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token function" style="color:rgb(0, 0, 255)">traverse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function maybe-class-name" style="color:rgb(0, 0, 255)">FunctionDeclaration</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">params</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">identifier</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'x'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="替换整个节点">替换整个节点<a class="hash-link" href="#替换整个节点" title="标题的直接链接">​</a></h4><p>替换的相关方法有</p><p><code>replaceWith</code> 一对一替换当前节点，且严格替换。</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">replaceWith</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">valueToNode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'kuizuo'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p><code>replaceWithMultiple</code> 则是一对多，将多个节点替换到一个节点上。</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token function" style="color:rgb(0, 0, 255)">traverse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function maybe-class-name" style="color:rgb(0, 0, 255)">ReturnStatement</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">replaceWithMultiple</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">expressionStatement</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">callExpression</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">memberExpression</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">identifier</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'console'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">identifier</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'log'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">stringLiteral</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'kuizuo'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">returnStatement</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">stop</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>要注意的是，替换节点要非常谨慎，就比如上述代码，如果我遍历 return 语句，同时我又替换成了 return 语句，替换后的节点同样是可以进入到遍历里，如果不进行停止，将会造成死循环，所以这里才使用了<code>path.stop</code>完全停止当前遍历，直到下一条 return 语句。</p><p><code>path.skip()</code>跳过遍历当前路径的子路径。<code>path.stop()</code>完全停止当前遍历</p><p><code>relaceInline</code> 接收一个参数，如果不为数组相当于<code>replaceWith</code>，如果是数组相当于<code>replaceWithMultiple</code></p><p><code>replaceWithSoureString</code> 该方式将字符串源码与节点进行替换，例如</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)">// 要替换的函数</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">add</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">a</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> b</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> a </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> b</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token function" style="color:rgb(0, 0, 255)">traverse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function maybe-class-name" style="color:rgb(0, 0, 255)">FunctionDeclaration</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">replaceWithSourceString</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string string" style="color:rgb(163, 21, 21)">function mult(a, b){</span><br></span><span class="token-line" style="color:#000000"><span class="token template-string string" style="color:rgb(163, 21, 21)">      return a * b</span><br></span><span class="token-line" style="color:#000000"><span class="token template-string string" style="color:rgb(163, 21, 21)">    }</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">stop</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// 替换后的结果</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// (function mult(a, b) {</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">//   return a * b;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// });</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="删除节点">删除节点<a class="hash-link" href="#删除节点" title="标题的直接链接">​</a></h4><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token function" style="color:rgb(0, 0, 255)">traverse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function maybe-class-name" style="color:rgb(0, 0, 255)">EmptyStatement</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">remove</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p><code>EmptyStatement</code>指空语句，也就是多余的分号。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="插入节点">插入节点<a class="hash-link" href="#插入节点" title="标题的直接链接">​</a></h4><p><code>insertBefore</code>与<code>insertAfter</code>分别在当前节点前后插入语句</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token function" style="color:rgb(0, 0, 255)">traverse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function maybe-class-name" style="color:rgb(0, 0, 255)">ReturnStatement</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">insertBefore</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">expressionStatement</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">stringLiteral</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'before'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">insertAfter</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">expressionStatement</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">stringLiteral</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'after'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="父级-path">父级 path<a class="hash-link" href="#父级-path" title="标题的直接链接">​</a></h4><p><strong><code>path.parent</code></strong> 表示父级的 node</p><p><strong><code>path.parentPath</code></strong> 表示父级的 path，也就是 NodePath</p><p><code>path.parentPath.node</code> === <code>path.parent</code> 两者效果一样，都是获取 Node 对象。</p><p>此外还有一些方法也可以获取父级 Path</p><p><strong><code>path.findParent</code></strong> 向上遍历每一个父级 Path 并根据条件返回，与数组 find 方式类型。</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token function" style="color:rgb(0, 0, 255)">traverse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function maybe-class-name" style="color:rgb(0, 0, 255)">BinaryExpression</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> parent </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">findParent</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">p</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> p</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">isFunctionDeclaration</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">parent</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">toString</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p><strong><code>path.find</code></strong> 与 findParent 方式类似，不过 find 方法不包括当前节点，而 findParent 不包括。</p><p><strong><code>path.getFunctionParent</code></strong> 向上查找与当前节点最接近的父函数，返回的是 Path 对象。</p><p><strong><code>path.getStatementParent</code></strong> 遍历语法树，直到找到语句节点（带有 Statement），如 return 语句（ReturnStatement），if 语句（IfStatement），块级语句（BlockStatement）</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="同级-path">同级 path<a class="hash-link" href="#同级-path" title="标题的直接链接">​</a></h4><p>path 有一个属性 container，表示当前节点所处于的那个节点下，共有那些同级节点，而 listKey 表示容器名。key 表示索引或是是容器对象的属性名</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token function" style="color:rgb(0, 0, 255)">traverse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function maybe-class-name" style="color:rgb(0, 0, 255)">ReturnStatement</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">key</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">listKey</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">container</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)">// 输出结果</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">body</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token maybe-class-name">Node</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">type</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'ReturnStatement'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">start</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">24</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">end</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">36</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">loc</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token maybe-class-name">SourceLocation</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">start</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token maybe-class-name">Position</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">end</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token maybe-class-name">Position</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">filename</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token keyword nil" style="color:rgb(0, 0, 255)">undefined</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">identifierName</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token keyword nil" style="color:rgb(0, 0, 255)">undefined</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">argument</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token maybe-class-name">Node</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">type</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'BinaryExpression'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">start</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">31</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">end</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">36</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">loc</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token maybe-class-name">SourceLocation</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">left</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token maybe-class-name">Node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">operator</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'+'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">right</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token maybe-class-name">Node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>在 ast 树结构中框中所表示</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20211216200502122.png" alt="image-20211216200502122" class="img_ev3q"></p><p>也并不是说所有节点都有同级节点，也并不是所有的 container 都是一个数组，例如下面这个例子</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> obj </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">name</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'kuizuo'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">init</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword nil" style="color:rgb(0, 0, 255)">undefined</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token maybe-class-name">Node</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">type</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'VariableDeclarator'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">start</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">4</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">end</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">30</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">loc</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token maybe-class-name">SourceLocation</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">start</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token maybe-class-name">Position</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">line</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">column</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">4</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">end</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token maybe-class-name">Position</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">line</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">3</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">column</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">filename</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token keyword nil" style="color:rgb(0, 0, 255)">undefined</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">identifierName</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token keyword nil" style="color:rgb(0, 0, 255)">undefined</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">id</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token maybe-class-name">Node</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">type</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'Identifier'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">start</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">4</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">end</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">7</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">loc</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token maybe-class-name">SourceLocation</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">start</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token maybe-class-name">Position</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">end</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token maybe-class-name">Position</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">filename</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token keyword nil" style="color:rgb(0, 0, 255)">undefined</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">identifierName</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'obj'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">name</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'obj'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">init</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token maybe-class-name">Node</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">type</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'ObjectExpression'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">start</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">10</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">end</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">30</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">loc</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token maybe-class-name">SourceLocation</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">start</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token maybe-class-name">Position</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">end</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token maybe-class-name">Position</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">filename</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token keyword nil" style="color:rgb(0, 0, 255)">undefined</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">identifierName</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token keyword nil" style="color:rgb(0, 0, 255)">undefined</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">properties</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token maybe-class-name">Node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>对应 AST 树结构中所框选</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20211216201242257.png" alt="image-20211216201242257" class="img_ev3q"></p><p>也就是说该节点并没有同级节点</p><p>其中关于同级节点有以下几种方法。</p><p><code>path.inList</code> 判断 container 属性是否为数组</p><p><code>path.getSibling(index)</code> 获取当前节点所在容器中索引对应的同级节点，index 可通过 path.key 获取。</p><p>其中还有<code>unshiftContainer</code>与<code>pushContainer</code>，在容器前与后添加节点，与<code>Array.unshift</code>和<code>Array.push</code>方法类似，不过基本没怎么用过，便不做实例了。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="scope">Scope<a class="hash-link" href="#scope" title="标题的直接链接">​</a></h3><p><strong><code>path.scope</code></strong> 字面名意思为作用域，可以方便查找标识符的引用。如当前变量的哪里被调用了，标识符为参数还是变量。</p><p>演示代码</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">test</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> obj </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">name</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'kuizuo'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> obj</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="获取标识符代码块">获取标识符代码块<a class="hash-link" href="#获取标识符代码块" title="标题的直接链接">​</a></h4><p><code>scope.block</code> 返回 Node 对象，使用方法分为两种情况，变量与函数。</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token function" style="color:rgb(0, 0, 255)">traverse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function maybe-class-name" style="color:rgb(0, 0, 255)">ObjectExpression</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> block </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">scope</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">block</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token function" style="color:rgb(0, 0, 255)">generator</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">block</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">code</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// function test() {</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">//   let obj = {</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">//     name: 'kuizuo'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">//   };</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">//   return obj;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// }</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>返回的是整个函数体代码</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token function" style="color:rgb(0, 0, 255)">traverse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function maybe-class-name" style="color:rgb(0, 0, 255)">ObjectExpression</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> block </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">scope</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">block</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token function" style="color:rgb(0, 0, 255)">generator</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">block</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">code</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// function test() {</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">//   let obj = {</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">//     name: 'kuizuo'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">//   };</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">//   return obj;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// }</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>由于<code>scope.block</code>返回的是 Node 对象，将就无法使用 path.toString()转为原始代码了。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="binding">binding<a class="hash-link" href="#binding" title="标题的直接链接">​</a></h4><p><strong><code>scope.getBinding()</code></strong> 接收一个参数，可用于获取标识符的绑定，这里的 binding 可能会有些抽象，在一开始的例子中初次接触到</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token function" style="color:rgb(0, 0, 255)">traverse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function maybe-class-name" style="color:rgb(0, 0, 255)">VariableDeclarator</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> name </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">name</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">name </span><span class="token operator" style="color:rgb(0, 0, 0)">===</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'tips'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> binding </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">scope</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">getOwnBinding</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">binding</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      binding</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">scope</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">rename</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'_0xabcdef'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>其中这里的 binding 是属性相对较多，下面会一一介绍</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token maybe-class-name">Binding</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">identifier</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token maybe-class-name">Node</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token literal-property property">type</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'Identifier'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">name</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'tips'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">scope</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">&lt;</span><span class="token plain">ref </span><span class="token operator" style="color:rgb(0, 0, 0)">*</span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token plain"> </span><span class="token maybe-class-name">Scope</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">path</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token maybe-class-name">NodePath</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token spread operator" style="color:rgb(0, 0, 0)">...</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">kind</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'let'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">constantViolations</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">constant</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">referencePaths</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token maybe-class-name">NodePath</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token spread operator" style="color:rgb(0, 0, 0)">...</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">referenced</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">references</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">hasDeoptedValue</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">hasValue</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">value</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token keyword null nil" style="color:rgb(0, 0, 255)">null</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>要注意的是，getBinding 中传的值必须是当前节点能够引用到的标识符，如果当前标识符不存在，那么返回 undefined。</p><p>identifier 是标识符 tips 的 Node 的对象，path 则是标识符 Path 对象，constant 为布尔值，表示当前标识符是否为常量，referenced 表示当前节点是否被引用。references 表示引用的次数。</p><p>binding 中的 scope 等同于 path 中的 scope，作用域范围相同。</p><p><strong><code>scope.getOwnBinding()</code></strong> 获取当前节点下的绑定，不包含其他父级中定义的标识符，会包含子函数中定义的标识符绑定。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="referencepaths-与-constantviolations">referencePaths 与 constantViolations<a class="hash-link" href="#referencepaths-与-constantviolations" title="标题的直接链接">​</a></h4><p>假如标识符被引用，referencePaths 中会存放所有引用该标识的 path 对象数组。像下面这样</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token literal-property property">referencePaths</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token maybe-class-name">NodePath</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">contexts</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">state</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token known-class-name class-name" style="color:rgb(38, 127, 153)">Object</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">opts</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token known-class-name class-name" style="color:rgb(38, 127, 153)">Object</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">_traverseFlags</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">skipKeys</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token keyword null nil" style="color:rgb(0, 0, 255)">null</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">parentPath</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token maybe-class-name">NodePath</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">container</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token maybe-class-name">Node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">listKey</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token keyword nil" style="color:rgb(0, 0, 255)">undefined</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">key</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'object'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">node</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token maybe-class-name">Node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">type</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'Identifier'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">parent</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token maybe-class-name">Node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">hub</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token keyword nil" style="color:rgb(0, 0, 255)">undefined</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">data</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token keyword null nil" style="color:rgb(0, 0, 255)">null</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">context</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token maybe-class-name">TraversalContext</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">scope</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token maybe-class-name">Scope</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>而 constantViolations 则是存放所有修改标识符的 Path 对象。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="标识符重命名">标识符重命名<a class="hash-link" href="#标识符重命名" title="标题的直接链接">​</a></h4><p>这在一开始的例子中就简单介绍过了，使用的是 rename 方法，能将该标识符中所有引用的地方重命名，不过上面的例子只是重命名 tips，想要重命名所有标识符的话，就需要遍历 Identifier。不过重命名标识符不能都重命名为相同字符，有一个 api <code>path.scope.generateUidIdentifier</code> 用于生成唯一不重复标识符。</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token function" style="color:rgb(0, 0, 255)">traverse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function maybe-class-name" style="color:rgb(0, 0, 255)">Identifier</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">scope</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">rename</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">scope</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">generateUidIdentifier</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'_0xabcdef'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>最终生成的代码如下</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token operator" style="color:rgb(0, 0, 0)">**</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">*</span><span class="token plain"> </span><span class="token maybe-class-name">Paste</span><span class="token plain"> or drop some </span><span class="token maybe-class-name">JavaScript</span><span class="token plain"> here and explore</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">*</span><span class="token plain"> the syntax tree created by chosen parser</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">*</span><span class="token plain"> </span><span class="token maybe-class-name">You</span><span class="token plain"> can use all the cool </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">features</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">ES6</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">*</span><span class="token plain"> and even more</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain"> </span><span class="token property-access maybe-class-name">Enjoy</span><span class="token operator" style="color:rgb(0, 0, 0)">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">*</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> _0xabcdef11 </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">"Click on any AST node with a '+' to expand it"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Hovering over a node highlights the \</span><br></span><span class="token-line" style="color:#000000"><span class="token string" style="color:rgb(163, 21, 21)">   corresponding location in the source code"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Shift click on an AST node to expand the whole subtree"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">_0xabcdef2</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  _0xabcdef11</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">forEach</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">_0xabcdef10</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> _0xabcdef9</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string string" style="color:rgb(163, 21, 21)">Tip </span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">${</span><span class="token template-string interpolation">_0xabcdef9</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token template-string string" style="color:rgb(163, 21, 21)">:</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> _0xabcdef10</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p><code>scope.hasBinding('a')</code> 查询是否有标识符 a 的绑定</p><p><code>scope.getAllBindings()</code> 获取当前节点下所有绑定，返回一个对象，以标识符名作为属性名，值为 binding。</p><p><code>scope.hasReference('a')</code> 查询当前节点是否有标识符 a 的引用。</p><p>当然大部分的 api 还需要自行翻阅文档，或通过代码提示与动态调试查看方法，举一反三，来达到所想要的目的。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="混淆实战">混淆实战<a class="hash-link" href="#混淆实战" title="标题的直接链接">​</a></h2><p>关于混淆实战的代码都已贴到 Github<a href="https://github.com/kuizuo/AST-obfuscator" target="_blank" rel="noopener noreferrer">kuizuo/AST-obfuscator</a>，在<code>src/obfuscated</code>中便可看到完整的混淆程序。其中也包括一些实战还原的例子，大部分的写法都采用了 ES6 的类来写，方便编写理解。</p><p>大部分混淆的例子在这本书《反爬虫 AST 原理与还原混淆实战》中都有，例如常量混淆，数组混淆与乱序，标识符混淆等等就不细说了，上传的代码中有，不过书中有一些 es6 的代码是没提及到的。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="模板字符串">模板字符串<a class="hash-link" href="#模板字符串" title="标题的直接链接">​</a></h3><p>与<code>StringLiteral</code>不同，模板字符串的 type 是<code>TemplateLiteral</code>，所以是遍历不到模板字符串的。下文将用代码来实现将模板字符串转为字符串拼接</p><p>演示代码</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> a </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'kuizuo'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">${</span><span class="token template-string interpolation">a</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token template-string string" style="color:rgb(163, 21, 21)">nb</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">${</span><span class="token template-string interpolation number" style="color:rgb(9, 134, 88)">12</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token template-string string" style="color:rgb(163, 21, 21)">3</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">${</span><span class="token template-string interpolation string" style="color:rgb(163, 21, 21)">'456'</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>分析 AST 树结构</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20211217161958075.png" alt="image-20211217161958075" class="img_ev3q"></p><p>不难观察出，parser 将其成两部分<code>expressions</code>与<code>quasis</code>。而所要转为的最终代码应该是<code>'' + a + 'nb' + 12 + '3' + '456'+ ''</code>，并且<code>quasis</code>成员个数始终比<code>expressions</code>多一位，所以只需要将<code>expressions</code>插入置<code>quasis</code>成员内，然后通过 binaryExpression 进行拼接即可。大致的思路有了，那么就开始用代码来进行拼接。</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token function" style="color:rgb(0, 0, 255)">traverse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function maybe-class-name" style="color:rgb(0, 0, 255)">TemplateLiteral</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> expressions</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> quasis </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">// 将expressions节点逐个插入到quasis节点上</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">for</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> i </span><span class="token keyword" style="color:rgb(0, 0, 255)">in</span><span class="token plain"> expressions</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> e </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> expressions</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      quasis</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">splice</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">i </span><span class="token operator" style="color:rgb(0, 0, 0)">*</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">2</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> e</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> newExpressions </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> quasis</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">// 循环新的表达式节点构造出二项式表达式</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> binary</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">for</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> i </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"> i </span><span class="token operator" style="color:rgb(0, 0, 0)">&lt;</span><span class="token plain"> newExpressions</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">length</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"> i</span><span class="token operator" style="color:rgb(0, 0, 0)">++</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> left </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> binary</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> right </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> newExpressions</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">i </span><span class="token operator" style="color:rgb(0, 0, 0)">===</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        left </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">valueToNode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">right</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">value</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">raw</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        binary </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> left</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">continue</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">isTemplateElement</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">right</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token comment" style="color:rgb(0, 128, 0)">// if (right.value.raw === '') continue</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        right </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">valueToNode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">right</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">value</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">raw</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      binary </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">binaryExpression</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'+'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> left</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> right</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">replaceWith</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">binary</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>最终输出 <code>"" + a + "nb" + 12 + "3" + "456" + ""</code></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="类声明">类声明<a class="hash-link" href="#类声明" title="标题的直接链接">​</a></h3><p>同样，类名与类方法名同样也是可以混淆的，演示代码如下</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">Test</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  age </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">20</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">constructor</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">name</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> name</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">run</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">name</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">age</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> test </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">Test</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'kuizuo'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">test</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">run</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>复制上述代码，观察 AST 树结构（图就不放了）</p><p>不难发现，其实就是 type <code>ClassDeclaration</code>、<code>ClassProperty</code>、<code>ClassMethod</code>，通过标识符混淆的方法<code>renameIdentifier</code>，将<code>Program|FunctionExpression|FunctionDeclaration</code>新增这两个 type 即可</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token function" style="color:rgb(0, 0, 255)">traverse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token string" style="color:rgb(163, 21, 21)">'Program|FunctionExpression|FunctionDeclaration|ClassDeclaration|ClassProperty|ClassMethod'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token function" style="color:rgb(0, 0, 255)">renameOwnBinding</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>但混淆完的代码并没有把属性名与方法名给混淆到</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">OOOOO0</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  age </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">399100</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">^</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">399080</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">constructor</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter constant" style="color:rgb(129, 31, 63)">OOOOO0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token function" style="color:rgb(0, 0, 255)">atob</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token constant" style="color:rgb(129, 31, 63)">OOOOOO</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">226019</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">^</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">226019</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token constant" style="color:rgb(129, 31, 63)">OOOOO0</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">run</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token function" style="color:rgb(0, 0, 255)">atob</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token constant" style="color:rgb(129, 31, 63)">OOOOOO</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">255772</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">^</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">255772</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token function" style="color:rgb(0, 0, 255)">atob</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token constant" style="color:rgb(129, 31, 63)">OOOOOO</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">982314</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">^</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">982315</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>不过这样混淆肯定远远不够的，方法可是类中很重要的属性，同时类方法与属性还能这么编写（constructor 不行），然后将下面的代码通过混淆程序执行一遍就能成功混淆变量名。</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">Test</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'age'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">20</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">constructor</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">name</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> name</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'run'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">name</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">age</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>所以将<code>run()</code> 转为<code>[‘run’]()</code>便成为了关键。而实现起来也相对简单（与改变对象访问方式一样）</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token function" style="color:rgb(0, 0, 255)">traverse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">ast</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token string" style="color:rgb(163, 21, 21)">'ClassProperty|ClassMethod'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">isIdentifier</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">key</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> name </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">key</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">name</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">name </span><span class="token operator" style="color:rgb(0, 0, 0)">===</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'constructor'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">key</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> t</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">stringLiteral</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    path</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">computed</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>最终运行混淆程序，执行混淆后的代码，成功输出<code>kuizuo20</code></p><hr><p>后续有时间再补充。。。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="混淆心得">混淆心得<a class="hash-link" href="#混淆心得" title="标题的直接链接">​</a></h2><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="混淆前提">混淆前提<a class="hash-link" href="#混淆前提" title="标题的直接链接">​</a></h3><p><strong>不改变原有代码的执行过程与结果</strong>，并不是随便混淆都行了，比如<code>let c = a + b</code> ，总不能混淆成 <code>let OO = Oo - oO</code>吧。其次要懂得利用 js 语法的特性来进行混淆，比如高阶函数，函数传参，jsfuck 等等。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="混淆并非万能">混淆并非万能<a class="hash-link" href="#混淆并非万能" title="标题的直接链接">​</a></h3><p>混淆始终是混淆，只是将代码相对变得难以阅读，但不代表不可阅读。只要程序能运行，那么我就能调试，能调试还能有什么解决不了的（毕竟 bug 都是调试出来）。如果真想保全你的代码，那我的建议是编译成二进制文件，或采用远程调用的形式将执行后的结果返回。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="代码执行效率">代码执行效率<a class="hash-link" href="#代码执行效率" title="标题的直接链接">​</a></h3><p>通常来说，混淆会使你的代码数量增大至 2,3 倍，与加密壳同理，但程序的执行速度也会稍慢下，当然只要不是特别 ex 的混淆，如将函数调用封装至，3,4 层的调用导致调用堆栈过大，那么这种执行效率基本可以忽略不计。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="有混淆就有还原">有混淆就有还原<a class="hash-link" href="#有混淆就有还原" title="标题的直接链接">​</a></h3><p>既然混淆是通过 AST 来进行混淆的，那么还原也同样可以，不过还原就不可能还原出原始开发者所编写的，就如同一些打包工具打包后的代码，比如将 name 压缩成 n，age 压缩成 a，那么就无法推断出 n 为 name，a 为 age，而混淆也是同理，像代码<code>let OOOOOO = atob('a3VpenVv')</code>，能还原的也只能是<code>let OOOOOO = ‘kuizuo’</code>或者是将标识符重新命名<code>let _0x123456 = ‘kuizuo’</code>，相对好看些。大部分的还原工作都只是将代码变得好读一些，比如<code>atob('a3VpenVv')</code>就可以变为<code>‘kuizuo’</code>，这便是基本的还原之一，关于还原还会另出一篇文章来记录，就不在这多废笔舌了。</p><p>整个混淆的过程来看，无非就是多了门技能，对 js 有了更进一步的了解，略懂 js 编译过程中的语法分析，此外也感叹 Babel 提供如此强大的 api。同时也能尝试使用最新的 ECMAScript 语法特性，无需考虑兼容问题，babel 统统都能处理。就如同 babel 官网所说的：</p><p><strong>现在就开始使用下一代 JavaScript 语法吧</strong>。</p>]]></content:encoded>
            <category>javascript</category>
            <category>ast</category>
            <category>reverse</category>
            <category>project</category>
        </item>
        <item>
            <title><![CDATA[JS函数hook]]></title>
            <link>https://kuizuo.cn/js-function-hook</link>
            <guid>js-function-hook</guid>
            <pubDate>Mon, 22 Nov 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[前言]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="前言">前言<a class="hash-link" href="#前言" title="标题的直接链接">​</a></h2><p>我在阅读《JavaScript 设计模式与开发实践》的第 15 章 装饰者模式，突然发现 JS 逆向中 hook 函数和 js 中的装饰者模式有点像，仔细阅读完全篇后更是对装饰器与 hook 有了更深的理解于是便有了这篇文章来记录一下该操作。</p><p>hook 直译的意思为钩子，在逆向领域通常用来针对某些参数，变量进行侦听，打印输出，替换等操作。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="正文">正文<a class="hash-link" href="#正文" title="标题的直接链接">​</a></h2><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="示例代码">示例代码<a class="hash-link" href="#示例代码" title="标题的直接链接">​</a></h3><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">add</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">a</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> b</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> a </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> b</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="hook-代码">hook 代码<a class="hash-link" href="#hook-代码" title="标题的直接链接">​</a></h3><p>这是一个很简单加法函数，通过 Hook 能获取到这两个参数的值，相当于在 return 之前添加了一句代码<code>console.log(a,b)</code>，这样便能输出这两个的值便于分析。那么可以使用如下的方式来复写改函数，而这个方式在 javascript 也就是装饰者模式</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> _add </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> add</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token function-variable function" style="color:rgb(0, 0, 255)">add</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'arguments'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> arguments</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> result </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> _add</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">apply</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> arguments</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'result'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> result</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> result </span><span class="token comment" style="color:rgb(0, 128, 0)">// 如果不需要result 则可直接return _add()</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p><strong>完整代码</strong></p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">add</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">a</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> b</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> a </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> b</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> _add </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> add</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token function-variable function" style="color:rgb(0, 0, 255)">add</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'arguments'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> arguments</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> result </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> _add</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">apply</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> arguments</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'result'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> result</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> result</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token function" style="color:rgb(0, 0, 255)">add</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">2</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>再次调用<code>add(1,2)</code>便会输出 arguments 参数以及结果 3，一个很简单 HOOK 就实现了。</p><p>不过这个例子可能过于简单，我所要表达的意思是，通过 Hook，定位到我们想 Hook 的函数与变量，通过一系列操作（函数复写，元编程），只要触发该函数或使用（取值，修改）该变量，便能将我们想要的结果（前后的结果（如 加密前，加密后））获取到。这才是我们的目的。</p><p>书中给的例子想说明的，想为某个原函数(比如这里的 add)添加一些功能，但该原函数可能是由其他开发者所编写的，那么直接修改原函数本身将可能导致未知 BUG，于是便可以用上面的方式进行复写原函数的同时，还不破坏原函数。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="this-指向问题">this 指向问题<a class="hash-link" href="#this-指向问题" title="标题的直接链接">​</a></h3><p>但并不是什么函数都能这样操作，或者说这样操作会导致原本函数可能执行不了，比如 this 指向，虽说没有修改原函数，但是原函数的 this 已经给我们更改成当前环境下（如<code>window</code>），但有些函数比如<code>document.getElementById()</code> 的内部<code>this</code>指向为<code>document</code>，不妨尝试将下面代码直接复制到控制台中查看会报什么错</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> _getElementById </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token dom variable" style="color:rgb(9, 134, 88)">document</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">getElementById</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token function-variable function" style="color:rgb(0, 0, 255)">getElementById</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">_getElementById</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> div </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">getElementById</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'div'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p><strong>报错:</strong></p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token maybe-class-name">Uncaught</span><span class="token plain"> </span><span class="token known-class-name class-name" style="color:rgb(38, 127, 153)">TypeError</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token maybe-class-name">Illegal</span><span class="token plain"> invocation</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    at </span><span class="token function" style="color:rgb(0, 0, 255)">getElementById</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token operator" style="color:rgb(0, 0, 0)">&lt;</span><span class="token plain">anonymous</span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token number" style="color:rgb(9, 134, 88)">4</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token number" style="color:rgb(9, 134, 88)">9</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    at </span><span class="token operator" style="color:rgb(0, 0, 0)">&lt;</span><span class="token plain">anonymous</span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token number" style="color:rgb(9, 134, 88)">7</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token number" style="color:rgb(9, 134, 88)">11</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p><strong>解决办法:</strong></p><p>只需要将 this 指向设置为 document 即可，代码改写如下</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> _getElementById </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token dom variable" style="color:rgb(9, 134, 88)">document</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">getElementById</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token function-variable function" style="color:rgb(0, 0, 255)">getElementById</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> _getElementById</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">apply</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token dom variable" style="color:rgb(9, 134, 88)">document</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> arguments</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> div </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">getElementById</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'div'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>但这样做略显麻烦，且有些函数你可能都不知道 this 的指向，但又想要复写该函数，书中也提及到用 <strong>AOP 装饰函数</strong></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="用-aop-装饰函数">用 AOP 装饰函数<a class="hash-link" href="#用-aop-装饰函数" title="标题的直接链接">​</a></h3><p>先给出 <code>Function.prototype.before</code> 和 <code>Function.prototype.after</code>方法</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token class-name" style="color:rgb(38, 127, 153)">Function</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">prototype</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method-variable function-variable method function property-access" style="color:rgb(0, 0, 255)">before</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">beforefn</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> __self </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    beforefn</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">apply</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> arguments</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> __self</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">apply</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">arguments</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token class-name" style="color:rgb(38, 127, 153)">Function</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">prototype</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method-variable function-variable method function property-access" style="color:rgb(0, 0, 255)">after</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">afterfn</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> __self </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> ret </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> __self</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">apply</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> arguments</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    afterfn</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">apply</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">ret</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> ret</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>注：这里 after 与书中略有不同，书中的是将<code>arguments</code> 传入<code>afterfn.apply(this, arguments)</code>，而我的做法则是将运行后的结果传入 <code>afterfn.apply(this, [ret])</code></p><p>那么将我们一开始的加法例子便可以替换为</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">add</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">a</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> b</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> a </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> b</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">add </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> add</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">before</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'arguments'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> arguments</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">after</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">result</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'result'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> result</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// 切记 这里不能写箭头函数 不然会指向的不是执行中的this 而是代码环境下的this</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token function" style="color:rgb(0, 0, 255)">add</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">2</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// arguments Arguments(2)&nbsp;[1, 2, callee: ƒ, Symbol(Symbol.iterator): ƒ]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// result 3</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><div class="theme-admonition theme-admonition-danger alert alert--danger admonition_LlT9"><div class="admonitionHeading_tbUL"><span class="admonitionIcon_kALy"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"></path></svg></span>危险</div><div class="admonitionContent_S0QG"><p>注：这种装饰方式叠加了函数的作用域，如果装饰的链条过长，性能上也会受到一定的影响</p></div></div><p>但该方法是直接修改原型方法，有些不喜欢污染原型的方式（用原型方式是真的好写），那么做一些变通，将原函数和新函数作为参数传入，代码如下</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> </span><span class="token function-variable function" style="color:rgb(0, 0, 255)">before</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">fn</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> beforefn</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    beforefn</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">apply</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> arguments</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> fn</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">apply</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> arguments</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>add 函数修改如下</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">add </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">before</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">add</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'arguments'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> arguments</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token function" style="color:rgb(0, 0, 255)">add</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">2</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>同样也能达到所要的目的。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="写后感">写后感<a class="hash-link" href="#写后感" title="标题的直接链接">​</a></h2><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token function-variable function" style="color:rgb(0, 0, 255)">add</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'arguments'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> arguments</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> result </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> _add</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">apply</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> arguments</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'result'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> result</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> result</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">add </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> add</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">before</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'arguments'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> arguments</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">after</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">result</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'result'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> result</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>对比两者方法，前者是对函数进行替换，而后者通过函数原型链将参数与结果通过回调函数的形式进行使用。在不考虑 this 指向，我个人更偏向第一种写法，而第二种写法也确实让我眼前一亮，很巧妙的使用 js 的原型链，从而避免 this 指向的问题。</p>]]></content:encoded>
            <category>javascript</category>
            <category>hook</category>
        </item>
        <item>
            <title><![CDATA[RPC远程调用浏览器函数]]></title>
            <link>https://kuizuo.cn/remote-call-browser-function</link>
            <guid>remote-call-browser-function</guid>
            <pubDate>Sat, 09 Oct 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[早闻 RPC（Remote Procedure Call）远程过程调用，这一词了，应该是在安卓逆向的时候听闻的，当时吹嘘的意思是这样的，通过另一个远端服务器来调用安卓代码中的函数，并将执行后的结果返回。比如有一个加密算法，如果要实现脱机（脱离当前环境）运行的话，就需要扣除相对应的代码，补齐对应的环境（模块，上下文，语言），然而要在补齐该加密算法的环境可不好实现，而通过 RPC 则可以免除扣代码，通过数据通信来达到远程调用的目的，听起来是挺牛逼的，实际上也确实挺骚的。这里我将以浏览器与本地搭建一个 websocket 来实现调用浏览器内的函数。]]></description>
            <content:encoded><![CDATA[<p>早闻 RPC（Remote Procedure Call）远程过程调用，这一词了，应该是在安卓逆向的时候听闻的，当时吹嘘的意思是这样的，通过另一个远端服务器来调用安卓代码中的函数，并将执行后的结果返回。比如有一个加密算法，如果要实现脱机（脱离当前环境）运行的话，就需要扣除相对应的代码，补齐对应的环境（模块，上下文，语言），然而要在补齐该加密算法的环境可不好实现，而通过 RPC 则可以免除扣代码，通过数据通信来达到远程调用的目的，听起来是挺牛逼的，实际上也确实挺骚的。这里我将以浏览器与本地搭建一个 websocket 来实现调用浏览器内的函数。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="算法例子">算法例子<a class="hash-link" href="#算法例子" title="标题的直接链接">​</a></h2><p>这里我所采用的是百度登录的密码加密算法，具体逆向实现就不细写了，借用视频教程<a href="https://www.bilibili.com/video/BV1Kh411r7uR?p=36" target="_blank" rel="noopener noreferrer">志远 2021 全新 js 逆向 RPC</a></p><p>通过关键词<code>password:</code> 便可找到对应的加密地点，找到加密调用的函数所出现的位置（loginv5.js 8944 行），发现通过调用<code>e.RSA.encrypt(s)</code>（其中 s 为明文 <code>a123456</code>），便可得到加密后的结果。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20211008042148653.png" alt="image-20211008042148653" class="img_ev3q"></p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20211008041300534.png" alt="image-20211008041300534" class="img_ev3q"></p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">e</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token constant" style="color:rgb(129, 31, 63)">RSA</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">encrypt</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">s</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token string" style="color:rgb(163, 21, 21)">'Zhge9q9jkiMA0UTfHxwNeyafnuUG8rcAh/gKfQpZiOQq8EYI/tJO83lKr52c4Im3cew3wVcINf2jEGEqH5EimnMI3g6eOjcdqduGyqynA4JjMJ0wltGdL8VUTTJsknsHUQlJXHOm/7zqx4NaBvOzhWzdDBk5cAOJ2DXgPaqoygg='</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>按照往常的做法，需要将<code>e.RSA.encrypt(s)</code>所用的代码处单独抠出来，放在 V8 引擎上测试或使用现有的加密库 如 CryptoJS，找到对应的密钥来进行加密。不过这里使用 RPC 来实现该算法的调用。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="实现">实现<a class="hash-link" href="#实现" title="标题的直接链接">​</a></h2><p>目前调用的环境有了（浏览器环境），只要我们这个浏览器不停止（使用无头浏览器运行），控制台便能一直输出我们想要的加密后结果。所以要实现的目的很简单，就是其他窗口（指其他语言所实现的程序），能远程调用<code>e.RSA.encrypt(s)</code>并将结果输出到其他窗口。</p><p>那么就需要建立通信协议了，这里我所采用的是浏览器自带的 Websocket 客户端与 Nodejs 搭建的 Websocket 服务端来进行通信，众所周知 HTTP 请求是无法双向传输的。所以使用 websocket 这样服务端就可以主动向浏览器发送请求，同时 websocket 在当前这个环境下好实现。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="nodejs-实现-websocket-服务端">Nodejs 实现 Websocket 服务端<a class="hash-link" href="#nodejs-实现-websocket-服务端" title="标题的直接链接">​</a></h3><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="安装-ws-模块">安装 ws 模块<a class="hash-link" href="#安装-ws-模块" title="标题的直接链接">​</a></h4><div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">npm install ws -S</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">npm install @types/ws -D</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>这里之所以选 ws，是因为 ws 对于 Websocket 协议而已，实现方便，且速度最快，并且浏览器可以通过<code>let ws = new Websocket()</code>来创建客户端直接连接，而使用 socket.io 的话，浏览器则需要载入 socket.io 客户端文件，繁琐。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="代码例子">代码例子<a class="hash-link" href="#代码例子" title="标题的直接链接">​</a></h4><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">server.js</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword module" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token imports maybe-class-name">WebSocket</span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token imports"> </span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token imports"> </span><span class="token imports maybe-class-name">WebSocketServer</span><span class="token imports"> </span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'ws'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> ws </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">WebSocketServer</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">port</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">8080</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">ws</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">on</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'connection'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">socket</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">message</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">msg</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'接受到的msg: '</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> msg</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    socket</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">send</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'我接受到你的数据: '</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> msg</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  socket</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">on</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'message'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> message</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>使用 WebSocket 在线测试网站<a href="http://www.websocket-test.com/" target="_blank" rel="noopener noreferrer">websocket 在线测试 (websocket-test.com)</a></p><p>测试结果如下</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20211008043925753.png" alt="image-20211008043925753" class="img_ev3q"></p><p>上面代码写的很简陋，尤其是数据交互的地方，这里可以使用 json 来改进一下。像这样，至于为啥用 try 是防止 json 数据不对导致解析错误（具体代码就不解读了）</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">server.js</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword module" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token imports maybe-class-name">WebSocket</span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token imports"> </span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token imports"> </span><span class="token imports maybe-class-name">WebSocketServer</span><span class="token imports"> </span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'ws'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> ws </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">WebSocketServer</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">port</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">8080</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">ws</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">on</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'connection'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">socket</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'有人连接了'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">message</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">try</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> json </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token known-class-name class-name" style="color:rgb(38, 127, 153)">JSON</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">parse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// data: {"type":"callbackPasswordEnc","value":"a123456"}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> type</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> value </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> json</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">switch</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">type</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword" style="color:rgb(0, 0, 255)">case</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'callbackPasswordEnc'</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token comment" style="color:rgb(0, 128, 0)">// doSomething()</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'得到的加密密文为:'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> value</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">break</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  socket</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">on</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'message'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> message</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token comment" style="color:rgb(0, 128, 0)">// 浏览器通信1秒后向浏览器调用加密算法</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">setTimeout</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> jsonStr </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token known-class-name class-name" style="color:rgb(38, 127, 153)">JSON</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">stringify</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">type</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'getPasswordEnc'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">value</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'a123456'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    socket</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">send</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">jsonStr</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1000</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="浏览器实现-websocket">浏览器实现 websocket<a class="hash-link" href="#浏览器实现-websocket" title="标题的直接链接">​</a></h3><p>既然要实现我们的代码，那么就需要将我们的代码注入到原来的代码上，这里我使用的是 Chrome 的开发者工具中的覆盖功能，选择一个本地文件夹，并允许权限。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20211008054918531.png" alt="image-20211008054918531" class="img_ev3q"></p><p>选择要替换代码的文件，选择保存以备替换（前提得开启覆盖）</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20211008055032125.png" alt="image-20211008055032125" class="img_ev3q"></p><p>接着在覆盖中找到文件，找到加密的代码块，添加如下代码</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">browser.js</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token operator" style="color:rgb(0, 0, 0)">!</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> url </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'ws://127.0.0.1:8080'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> ws </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">WebSocket</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">url</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token comment" style="color:rgb(0, 128, 0)">// 浏览器连接后告诉服务端是浏览器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  ws</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method-variable function-variable method function property-access" style="color:rgb(0, 0, 255)">onopen</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">event</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    ws</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">send</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token known-class-name class-name" style="color:rgb(38, 127, 153)">JSON</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">stringify</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">type</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'isBrowser'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">value</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  ws</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method-variable function-variable method function property-access" style="color:rgb(0, 0, 255)">onmessage</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">event</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> json </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token known-class-name class-name" style="color:rgb(38, 127, 153)">JSON</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">parse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">event</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> type</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> value </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> json</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">switch</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">type</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword" style="color:rgb(0, 0, 255)">case</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'getPasswordEnc'</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> passwordEnc </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> e</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token constant" style="color:rgb(129, 31, 63)">RSA</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">encrypt</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">value</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> jsonStr </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token known-class-name class-name" style="color:rgb(38, 127, 153)">JSON</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">stringify</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token literal-property property">type</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'callbackPasswordEnc'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token literal-property property">value</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> passwordEnc</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">jsonStr</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        ws</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">send</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">jsonStr</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">break</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p><img loading="lazy" src="https://img.kuizuo.cn/image-20211008201809446.png" alt="image-20211008201809446" class="img_ev3q"></p><p>然后就是最关键的地方了，触发加密函数，并将结果返回。触发加密函数只需要向浏览器发送指定数据<code>{"type":"getPasswordEnc","value":"a123456"}</code>，浏览器接受到对应的类型与数据，便调用相应的函数，并将结果<code>{"type":"callbackPasswordEnc","value":"FM6SK3XiL5X0RF9NZi7qhIsu7Pd46mfKnn6YkWUNSGrJO+XXhiXyoG8huaqQW4BnmYuo0JVVQj28C+BK/r6NTNbLcV4gMSREB2hYU/oIYedCJsZ9sbZQ89p1aI9kVcDeRlXBhjNUxkcS9Rh+vKzyNApwpbPcAuGTCSZhKst8vVo="}</code>返回即可。</p><p>服务端的效果如下图</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20211008204247104.png" alt="image-20211008204247104" class="img_ev3q"></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="优化执行流程">优化执行流程<a class="hash-link" href="#优化执行流程" title="标题的直接链接">​</a></h2><p>实现是实现了，但是代码貌似很不优雅，甚至有点别扭。按理来说因为是浏览器作为 websocket 服务端，我们作为客户端，客户端向服务器获取数据才合理，但在这里浏览器当不了 websocket 服务端这个角色，所以只能使用如此别扭的方式来调用。像上面例子的话，如果我的程序要实现一个某度登录的话，那么我这个程序就需要搭建一个 ws 服务器来进行两者的通信，有没有好的办法又不太依赖于 ws 服务端，就像 http 那样，程序只需要发送一个请求，给定类型和数值进行加密处理后返回即可。于是我处理的思路是这样的。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="思路">思路<a class="hash-link" href="#思路" title="标题的直接链接">​</a></h2><p>我的做法是将 websocket 服务端当个中转站，而浏览器的 websocket 客户端作为一个加密算法的服务，再添加一个登录算法实现的客户端简称为用户调用的，所以现在一共有三份代码（websocket 服务端，浏览器端，用户调用端）。这里我还是以 nodejs 为例。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="浏览器端">浏览器端<a class="hash-link" href="#浏览器端" title="标题的直接链接">​</a></h3><p>浏览器 websocket 客户端的代码，在初次连接的时候，告诉 websocket 服务端是不是浏览器。并将于浏览器连接的 socket 句柄存入全局对象，以便用户获取加密参数的时候向浏览器调用。</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">browser.js</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">ws</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method-variable function-variable method function property-access" style="color:rgb(0, 0, 255)">onopen</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">event</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  ws</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">send</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token known-class-name class-name" style="color:rgb(38, 127, 153)">JSON</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">stringify</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">type</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'isBrowser'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">value</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="用户调用端">用户调用端<a class="hash-link" href="#用户调用端" title="标题的直接链接">​</a></h3><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">client.js</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword module" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token imports maybe-class-name">WebSocket</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'ws'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">async</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">getPasswordEnc</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">password</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">Promise</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">resolve</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> reject</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> ws </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">WebSocket</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'ws://127.0.0.1:8080'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    ws</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">on</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'open'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> jsonStr </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token known-class-name class-name" style="color:rgb(38, 127, 153)">JSON</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">stringify</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token literal-property property">type</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'getPasswordEnc'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token literal-property property">value</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> password</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      ws</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">send</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">jsonStr</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    ws</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">on</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'message'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">message</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> json </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token known-class-name class-name" style="color:rgb(38, 127, 153)">JSON</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">parse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">message</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> type</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> value </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> json</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">switch</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">type</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword" style="color:rgb(0, 0, 255)">case</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'callbackPasswordEnc'</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          ws</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">close</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token function" style="color:rgb(0, 0, 255)">resolve</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">value</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">break</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">async</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">run</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> passwordEnc </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">getPasswordEnc</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'a123456'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">passwordEnc</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token function" style="color:rgb(0, 0, 255)">run</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>这里对代码进行解读一下，我自行封装了一个函数，其中函数返回的是一个 Promise 对象，值则是对应的加密后的密文。如果我这边不采用 promise 来编写的话，那么获取到的数据将十分不好返回给我们的主线程。这里对于 js 的 Promise 使用需要花费点时间去理解。总而言之，通过 promise，以及 async await 语法糖，能很轻松的等待 websocket 连接与接收数据。但还是用 websocket 协议</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="websocket-服务端">websocket 服务端<a class="hash-link" href="#websocket-服务端" title="标题的直接链接">​</a></h3><p>同时 websocket 服务端肯定要新增一个类型用于判断是登录算法实现的客户端。同时又新的用户要调用，所以这里使用了 uuid 这个模块来生成唯一的用户 id，同时还定义一个变量 clients 记录所连接过的用户（包括浏览器），完整代码如下</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">server.js</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword module" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token imports maybe-class-name">WebSocket</span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token imports"> </span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token imports"> </span><span class="token imports maybe-class-name">WebSocketServer</span><span class="token imports"> </span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'ws'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword module" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token imports"> v4 </span><span class="token imports keyword module" style="color:rgb(0, 0, 255)">as</span><span class="token imports"> uuidv4 </span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'uuid'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> ws </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">WebSocketServer</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">port</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">8080</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> browserWebsocket </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword null nil" style="color:rgb(0, 0, 255)">null</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> clients </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">ws</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">on</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'connection'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">socket</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> client_id </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">uuidv4</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  clients</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">push</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">id</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> client_id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">socket</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> socket</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  socket</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">on</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'close'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">for</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> i </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"> i </span><span class="token operator" style="color:rgb(0, 0, 0)">&lt;</span><span class="token plain"> clients</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">length</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"> i</span><span class="token operator" style="color:rgb(0, 0, 0)">++</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">clients</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">id</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token plain"> client_id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        clients</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">splice</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">break</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  socket</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">on</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'message'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">message</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">try</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> json </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token known-class-name class-name" style="color:rgb(38, 127, 153)">JSON</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">parse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">message</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> type</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> value </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> json</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">switch</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">type</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword" style="color:rgb(0, 0, 255)">case</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'isBrowser'</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">value</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            browserWebsocket </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> socket</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'浏览器已初始化'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">break</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token comment" style="color:rgb(0, 128, 0)">// 发送给浏览器 让浏览器来调用并返回</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword" style="color:rgb(0, 0, 255)">case</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'callbackPasswordEnc'</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token comment" style="color:rgb(0, 128, 0)">// 根据id找到调用用户的socket,并向该用户发送加密后的密文</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> temp_socket </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> clients</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">find</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">c</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> c</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">id</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token plain"> id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">socket</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          temp_socket</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">send</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">message</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">break</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token comment" style="color:rgb(0, 128, 0)">// 用户发送过来要加密的明文</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword" style="color:rgb(0, 0, 255)">case</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'getPasswordEnc'</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> jsonStr </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token known-class-name class-name" style="color:rgb(38, 127, 153)">JSON</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">stringify</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token literal-property property">id</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> client_id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token literal-property property">type</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> type</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token literal-property property">value</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> value</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token comment" style="color:rgb(0, 128, 0)">// 这里一定要是浏览器的websocket句柄发送，才能调用</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          browserWebsocket</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">send</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">jsonStr</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">break</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">message</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>最终演示效果如下视频（浏览器代码是提前注入进去的）</p><video width="800px" height="450px" controls=""><source id="mp4" src="https://img.kuizuo.cn/rpc.mp4" type="video/mp4"></video><p>其实还是一些是要完善的，这里的 Websocket 只是实现了连接，还有心跳包异常断开，浏览器异常关闭导致 websocket 断开无法调用函数等等，以及浏览器的代码还需要手动注入很不优化，后续如果使用 Chrome 插件开发一个实现注入 js 代码的功能也许会好一些。（正准备编写 Chrome 插件）</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="http-协议调用实现">HTTP 协议调用实现<a class="hash-link" href="#http-协议调用实现" title="标题的直接链接">​</a></h2><p>但是，以上都是基于 WebSocket 协议，就连用户端调用也是，然而用户调用没必要保持长连接且不利于调用（相对一些语言而言），有没有能直接使用 http 协议，通过 POST 请求来实现获取参数，这才是我所要实现的。</p><p>其实要实现也很简单，我只要把用户调用的 <code>getPasswordEnc</code> 这个函数 弄到 node 创建的一个 http 服务端就行了，我这里的做法也是如此。像下面这样</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">server_http.js</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">async</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">getPasswordEnc</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">password</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">Promise</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">resolve</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> reject</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> ws </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">WebSocket</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'ws://127.0.0.1:8080'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    ws</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">on</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'open'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> jsonStr </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token known-class-name class-name" style="color:rgb(38, 127, 153)">JSON</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">stringify</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token literal-property property">type</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'getPasswordEnc'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token literal-property property">value</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> password</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      ws</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">send</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">jsonStr</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    ws</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">on</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'message'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">message</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> json </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token known-class-name class-name" style="color:rgb(38, 127, 153)">JSON</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">parse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">message</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> type</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> value </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> json</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">switch</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">type</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword" style="color:rgb(0, 0, 255)">case</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'callbackPasswordEnc'</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          ws</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">close</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token function" style="color:rgb(0, 0, 255)">resolve</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">value</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">break</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// 创建http服务</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> app </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> http</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">createServer</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">request</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> response</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> pathname</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> query </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> url</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">parse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">request</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">url</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">pathname </span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'/getPasswordEnc'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> passwordEnc </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">getPasswordEnc</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">query</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">password</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    response</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">end</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">passwordEnc</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">app</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">listen</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">8000</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string string" style="color:rgb(163, 21, 21)">服务已运行 http://127.0.0.1:8000/</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>发送 GET 请求 URL 为 <a href="http://127.0.0.1:8000/getPasswordEnc?password=a123456" target="_blank" rel="noopener noreferrer">http://127.0.0.1:8000/getPasswordEnc?password=a123456</a> 实现效果如图</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20211009040704534.png" alt="image-20211009040704534" class="img_ev3q"></p><p>对于用户调用来说相对友好了不少（其实是很好），不用在创建 websocket 客户端，只需要发送 HTTP 请求（GET 或 POST），不过我这边使用的是 Node 自带的 http 模块来搭建的一个 http 服务器，实际使用中将会采用 express 来编写路由提高开发效率和代码可读性，这里只是作为演示。</p><p>至于说我为什么要在 http 内在新建一个 ws 客户端，主要原因还是 websocket 服务端向浏览器发送调用的算法，但只能在 websocket 服务端中的通过 onmessage 接受，无法在 http 服务端接受到，就别说向用户端返回了。这里其实只是不让用户来进行连接 websocket，而是我们本地（服务器）在接受到 getPasswordEnc 请求，复现了一遍上面用户连接 websocket 的例子，并将其转为 http 请求返回给用户而已。</p><p><strong>其实也就是多了一个调用的 HTTP 服务器，而这里将 http 服务器与 websocket 服务器写到一起而已</strong></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="代码地址">代码地址<a class="hash-link" href="#代码地址" title="标题的直接链接">​</a></h2><p><a href="https://github.com/kuizuo/rpc-browser.git" target="_blank" rel="noopener noreferrer">https://github.com/kuizuo/rpc-browser.git</a></p><p>运行方式请查看 README.md</p>]]></content:encoded>
            <category>javascript</category>
            <category>rpc</category>
            <category>browser</category>
        </item>
        <item>
            <title><![CDATA[记 ThinkPHP 项目部署]]></title>
            <link>https://kuizuo.cn/thinkphp-deploy</link>
            <guid>thinkphp-deploy</guid>
            <pubDate>Sat, 25 Sep 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[事情背景]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="事情背景">事情背景<a class="hash-link" href="#事情背景" title="标题的直接链接">​</a></h2><p>用户花了几百块购买了一份 ThinkPHP 一个后台管理的网站源码，要求更换下部分失效接口，或是重写一个类似这样的网站。我想既然都有源码了，我改改不就完事了，这不比重写一个来的省事。虽说我不是主学 PHP 的，但至少我学过一丢丢的 PHP，接触过 ThinkPHP 项目的。不过层面都是局限在本地，部署到生产环境与本地还是有比较大的差别的，于是便有了这篇文章来记录一下自己部署 ThinkPHP 所遇到的一些坑。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="windows-部署">Windows 部署<a class="hash-link" href="#windows-部署" title="标题的直接链接">​</a></h2><p>也可理解为本地部署，本地部署就相对比较简单的了。不过需要一个工具，PHPStudy，来帮助我们配置本地的环境（Apache、Nginx、PHP、Mysql）</p><p><a href="https://www.xp.cn/" target="_blank" rel="noopener noreferrer">小皮面板(phpstudy) - 让天下没有难配的服务器环境！ (xp.cn)</a></p><p>下载安装打开界面，选择网站，创建网站</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20210925143601530.png" alt="image-20210925143601530" class="img_ev3q"></p><p>由于是本机，所以域名就填写 localhost 或 127.0.0.1，端口的话这边所填写的是 4200，别和其他端口冲突即可。</p><p>由于 ThinkPHP 的根目录要选择的是根目录下的 public 目录，不然找不到 index.php 这个文件，所以这里根目录自己指定一下源码的位置，点击确认即可。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="初次启动-not-found">初次启动 Not Found<a class="hash-link" href="#初次启动-not-found" title="标题的直接链接">​</a></h3><p>这时候访问 http://localhost:4200 提示如下</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20210925143752775.png" alt="image-20210925143752775" class="img_ev3q"></p><p>本着不会就百度的原则，很快就找到了解决办法</p><p><a href="https://blog.csdn.net/qq_42940241/article/details/112461625" target="_blank" rel="noopener noreferrer">ThinkPHP 报错 The requested URL /index/index/xxx.html was not found on this server</a></p><p>在入口文件夹 public 下查看.htaccess 是否存在。不存在则新建，存在的话，那内容替换为下面这串代码 就可以解决 Not Fund 问题</p><div class="language-xml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-xml codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">#</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">IfModule</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">mod_rewrite.c</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">#  Options +FollowSymlinks -Multiviews</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">#  RewriteEngine On</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">#</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">#  RewriteCond %{REQUEST_FILENAME} !-d</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">#  RewriteCond %{REQUEST_FILENAME} !-f</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">#  RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L]</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">#</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">IfModule</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">IfModule</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">mod_rewrite.c</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">RewriteEngine on</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">RewriteCond %{REQUEST_FILENAME} !-d</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">RewriteCond %{REQUEST_FILENAME} !-f</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">RewriteRule ^(.*)$ index.php?/$1 [QSA,PT,L]</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">IfModule</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="页面报错-开启-debug">页面报错 开启 Debug<a class="hash-link" href="#页面报错-开启-debug" title="标题的直接链接">​</a></h3><p>上面配置完毕后，再次打开出现如下提示。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20210925144143248.png" alt="image-20210925144143248" class="img_ev3q"></p><p>遇到错误是很正常的，现在要做的就是输出报错信息，而不是简短的文字。到根目录下 config/app.php 中，将调试更改为 true（切记，生产环境中一定要更改为 false，不然用户就能查看报错详情以及对应代码）</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20210925144424361.png" alt="image-20210925144424361" class="img_ev3q"></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="配置数据库">配置数据库<a class="hash-link" href="#配置数据库" title="标题的直接链接">​</a></h3><p>再次访问页面提示</p><p><strong><img loading="lazy" src="https://img.kuizuo.cn/image-20210925144620953.png" alt="image-20210925144620953" class="img_ev3q"></strong></p><p>报错信息倒是很全，不过要关注的是报错行和提示，大致意思就是没有定义数据库用户名 ml 以及密码，毕竟数据库啥的都好像没配置，要是能启动起来那估计就真是一个 bug 了，那就先找到配置文件，看看原本的账号密码是多少，数据库配置文件位置<code>config/database.php</code></p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20210925145740851.png" alt="image-20210925145740851" class="img_ev3q"></p><p>不过 PHPstudy 用户名和密码长度都要在 6 位以上（Linux 倒是不用），所以勉为其难，把用户名和密码都改成 ml1234，接着 Mysql 导入源码给定的数据库文件(sql 文件)，什么，你说源码没有给数据库文件，那我建议直接删源码，并且接下来的内容也可以不用看了。</p><p>数据库导入完毕后，再次访问便能看到正常的首页了，就此就算部署完毕了，这里就不放首页图了。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="linux-部署">Linux 部署<a class="hash-link" href="#linux-部署" title="标题的直接链接">​</a></h2><p>Linux 部署和 Windows 部署是有一丢丢差别的，这里我也列举一下，环境是 CentOS 7.6，安装了宝塔面板</p><p>在宝塔面板出网站，添加网站，如同 PHPstudy，配置大致相同。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20210926050508693.png" alt="image-20210926050508693" class="img_ev3q"></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="关闭防跨站攻击">关闭防跨站攻击<a class="hash-link" href="#关闭防跨站攻击" title="标题的直接链接">​</a></h3><p>情况 1，如图</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20210925155027023.png" alt="image-20210925155027023" class="img_ev3q"></p><p>解决办法：点击网站，设置，将防跨站攻击关闭并保持，如下</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20210925155445084.png" alt="image-20210925155445084" class="img_ev3q"></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="设置伪静态">设置伪静态<a class="hash-link" href="#设置伪静态" title="标题的直接链接">​</a></h3><p>接着再次访问网站会出现 404 页面不存在报错，在设置中找到伪静态，添加一个 thinkphp 的配置，如下</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20210925155705573.png" alt="image-20210925155705573" class="img_ev3q"></p><p>再次访问后，出现的就是数据库配置的问题，配置一下数据库，导入数据，然后再次访问便可。</p><div class="theme-admonition theme-admonition-danger alert alert--danger admonition_LlT9"><div class="admonitionHeading_tbUL"><span class="admonitionIcon_kALy"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"></path></svg></span>危险</div><div class="admonitionContent_S0QG"><p>再次提醒，生产环境下，请将<code>app_debug</code>设置为 false，不然非法用户可以通过人为试错，查询对应报错代码。</p></div></div>]]></content:encoded>
            <category>php</category>
            <category>develop</category>
        </item>
        <item>
            <title><![CDATA[使用JSONPath解析json数据]]></title>
            <link>https://kuizuo.cn/use-jsonpath-to-parse-json-data</link>
            <guid>use-jsonpath-to-parse-json-data</guid>
            <pubDate>Mon, 20 Sep 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[jsonpath 能够帮助我们快速的从json数据中提取想要的数据]]></description>
            <content:encoded><![CDATA[<p>之前学习爬虫的时候，如果是 HTML 的数据，通过 xpath 或是 css 选择器，就能很快的获取我们想要的数据，如果是 json 有没有类似 xpath 这种，能够直接根据条件定位数据，而不需要自行 json 解析在遍历获取。答案是有的，也就是 JSONPath。</p><p>在线测试网址 <a href="https://www.jsonpath.cn/" target="_blank" rel="noopener noreferrer">JSONPath 在线验证</a></p><p>所选用的环境是 Node + JavaScript，用到 jsonpath 这个包 <a href="https://www.npmjs.com/package/jsonpath" target="_blank" rel="noopener noreferrer">jsonpath - npm (npmjs.com)</a></p><blockquote><p>参考链接 <a href="https://www.jianshu.com/p/8c0ade82891b" target="_blank" rel="noopener noreferrer">JsonPath - 根据表达式路径解析 Json - 简书 (jianshu.com)</a></p></blockquote><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="基本语法">基本语法<a class="hash-link" href="#基本语法" title="标题的直接链接">​</a></h2><table><thead><tr><th>JSONPath</th><th>描述</th></tr></thead><tbody><tr><td>$</td><td>根对象或元素.</td></tr><tr><td>@</td><td>当前对象或元素.</td></tr><tr><td>. or []</td><td>子元素操作符.</td></tr><tr><td>..</td><td>递归匹配所有子元素.</td></tr><tr><td>*</td><td>通配符. 匹配所有对象或元素.</td></tr><tr><td>[]</td><td>下标运算符，JsonPath 索引从 0 开始.</td></tr><tr><td>[,]</td><td>连接运算符，将多个结果拼成数组返回，JSONPath 允许使用别名.</td></tr><tr><td>[start:end1:step]</td><td>数组切片运算符.</td></tr><tr><td>?()</td><td>过滤器（脚本）表达式.</td></tr><tr><td>()</td><td>脚本表达式.</td></tr><tr><td>|<!-- -->|</td><td>表达式 或</td></tr><tr><td>&amp;&amp;</td><td>表达式 且</td></tr></tbody></table><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="过滤器表达式">过滤器表达式<a class="hash-link" href="#过滤器表达式" title="标题的直接链接">​</a></h3><p>通常的表达式格式为：<!-- -->[?(@.age &gt; 18)]<!-- --> 表示当前节点属性 age 大于 18</p><table><thead><tr><th>操作符</th><th>描述</th></tr></thead><tbody><tr><td>==</td><td>等于符号，但数字 1 不等于字符 1(note that 1 is not equal to ‘1’)</td></tr><tr><td>!=</td><td>不等于符号</td></tr><tr><td>&lt;</td><td>小于符号</td></tr><tr><td>&lt;=</td><td>小于等于符号</td></tr><tr><td>&gt;</td><td>大于符号</td></tr><tr><td>&gt;=</td><td>大于等于符号</td></tr><tr><td>=~</td><td>判断是否符合正则表达式，例如<!-- -->[?(@.name =~ /foo.*?/i)]</td></tr><tr><td>in</td><td>所属符号，例如[?(@.size in <!-- -->[‘S’, ‘M’]<!-- -->)]</td></tr><tr><td>nin</td><td>排除符号</td></tr><tr><td>size</td><td>size of left (array or string) should match right</td></tr><tr><td>empty</td><td>判空 Null 符号</td></tr></tbody></table><p>语法就这些，不过单单有语法，不实践肯定是不够的。下面就是一些官方简单例子操作，还有一个终极实战</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="代码演示">代码演示<a class="hash-link" href="#代码演示" title="标题的直接链接">​</a></h2><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">var</span><span class="token plain"> jp </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">require</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'jsonpath'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">var</span><span class="token plain"> cities </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">name</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'London'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">population</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">8615246</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">name</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'Berlin'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">population</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">3517424</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">name</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'Madrid'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">population</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">3165235</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">name</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'Rome'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">population</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">2870528</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">var</span><span class="token plain"> names </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> jp</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">query</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">cities</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'$..name'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// [ "London", "Berlin", "Madrid", "Rome" ]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>如果使用 js 来遍历的话，也简单</p><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> names </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> cities</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">map</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">c</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> c</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">name</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>这个数据可能还没那么复杂，在看看下面这个例子，代码来源于<a href="https://goessner.net/articles/JsonPath" target="_blank" rel="noopener noreferrer">https://goessner.net/articles/JsonPath</a></p><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"store"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"book"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"category"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"reference"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"author"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Nigel Rees"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"title"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Sayings of the Century"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"price"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">8.95</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"category"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"fiction"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"author"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Evelyn Waugh"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"title"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Sword of Honour"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"price"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">12.99</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"category"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"fiction"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"author"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Herman Melville"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"title"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Moby Dick"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"isbn"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"0-553-21311-3"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"price"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">8.99</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"category"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"fiction"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"author"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"J. R. R. Tolkien"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"title"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"The Lord of the Rings"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"isbn"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"0-395-19395-8"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token property">"price"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">22.99</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"bicycle"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"color"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"red"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"price"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">19.95</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><table><thead><tr><th>JsonPath</th><th>Result</th></tr></thead><tbody><tr><td><code>$.store.book[*].author</code></td><td>所有 book 的 author 节点</td></tr><tr><td><code>$..author</code></td><td>所有 author 节点</td></tr><tr><td><code>$.store.*</code></td><td>store 下的所有节点，book 数组和 bicycle 节点</td></tr><tr><td><code>$.store..price</code></td><td>store 下的所有 price 节点</td></tr><tr><td><code>$..book[2]</code></td><td>匹配第 3 个 book 节点</td></tr><tr><td><code>$..book[(@.length-1)]</code>，或 <code>$..book[-1:]</code></td><td>匹配倒数第 1 个 book 节点</td></tr><tr><td><code>$..book[0,1]</code>，或 <code>$..book[:2]</code></td><td>匹配前两个 book 节点</td></tr><tr><td><code>$..book[?(@.isbn)]</code></td><td>过滤含 isbn 字段的节点</td></tr><tr><td><code>$..book[?(@.price&lt;10)]</code></td><td>过滤<code>price&lt;10</code>的节点</td></tr><tr><td><code>$..*</code></td><td>递归匹配所有子节点</td></tr></tbody></table><p>对应的语法可直接到在 JSONPath 在线验证网站上进行测试。要提一点的是，jsonpath 是支持使用 || 与 &amp;&amp; 进行过滤的，比如上面要获取 category 为 fiction，price 大于 10 的语法为<code>$..book[?(@.price&gt;10 &amp;&amp; @.category=="fiction")]</code> 结果如下</p><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"category"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"fiction"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"author"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Evelyn Waugh"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"title"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Sword of Honour"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"price"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">12.99</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"category"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"fiction"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"author"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"J. R. R. Tolkien"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"title"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"The Lord of the Rings"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"isbn"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"0-395-19395-8"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"price"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">22.99</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="终极实战">终极实战<a class="hash-link" href="#终极实战" title="标题的直接链接">​</a></h2><p>也许你会觉得上面的例子太过简单了，可能没达到你预期所想要的效果，甚至还不如使用 json 遍历呢，下面我列举一个是我实战中遇到的例子（实际上这样的例子特别多），我先把部分数据展示出来（删除部分没用到的参数，实际参数远比这多），然后通过 js 遍历，以及 jsonpath 来获取我想要的数据。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="结构">结构<a class="hash-link" href="#结构" title="标题的直接链接">​</a></h3><p><img loading="lazy" src="https://img.kuizuo.cn/image-20210919194116296.png" alt="image-20210919194116296" class="img_ev3q"></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="数据">数据<a class="hash-link" href="#数据" title="标题的直接链接">​</a></h3><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"role"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"unit"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"children"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"role"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"section"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"children"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token property">"role"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"node"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token property">"children"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"summary"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"{\"indexMap\": {}, \"questionsList\": []}"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"role"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"group"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"tab_type"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"text"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"name"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Learning objectives"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"scoreDetail"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"u1g2"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"u1g2"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"tags"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token property">"suggestedDuration"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"0"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token property">"name"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"1-1 Learning objectives"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token property">"block_id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"90ed499f91084e2aa1b7032d2e4ecd76"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token property">"url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"u1g1"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token property">"tags"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"name"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Learning objectives"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"tags"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"role"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"section"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"children"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token property">"role"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"node"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token property">"children"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"role"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"node"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"children"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"role"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"group"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"tab_type"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"task"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"name"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Practice-1"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"scoreDetail"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"u1g6"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"u1g6"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"tags"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"role"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"group"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"tab_type"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"task"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"name"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Practice-2"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"scoreDetail"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"u1g7"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"u1g7"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"tags"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"role"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"group"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"tab_type"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"task"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"name"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Practice-3"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"scoreDetail"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"u1g544"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"u1g544"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"tags"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"role"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"group"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"tab_type"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"task"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"name"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Practice-4"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"scoreDetail"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"u1g9"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"u1g9"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"tags"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"name"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Practice"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"block_id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"f6768dc9474746b9ba071e7f211534d9"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"u1g5"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"tags"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token property">"suggestedDuration"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"0"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token property">"name"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"1-2 Sharing"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token property">"block_id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"1c97a87a9feb4a8aa7d6ed39482d866d"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token property">"url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"u1g3"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token property">"tags"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token property">"role"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"node"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token property">"children"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"role"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"group"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"tab_type"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"video"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"name"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Get the skills"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"scoreDetail"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"u1g16"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"u1g16"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"tags"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"role"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"node"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"children"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"role"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"group"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"tab_type"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"task"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"name"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Use the skills-1"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"scoreDetail"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"u1g615"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"u1g615"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"tags"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"role"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"group"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"tab_type"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"task"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"name"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Use the skills-2"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"scoreDetail"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"u1g18"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"u1g18"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"tags"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"role"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"group"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"tab_type"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"task"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"name"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Use the skills-3"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"scoreDetail"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"u1g19"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"u1g19"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"tags"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"name"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Use the skills"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"block_id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"2d8a81799bcc44ccab2646b613557b2b"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"u1g17"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"tags"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"role"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"node"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"children"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"role"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"group"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"tab_type"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"task"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"name"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Think and speak"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"scoreDetail"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"u1g21"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"u1g21"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"tags"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"name"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Think and speak"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"block_id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"5833925c8c5e4ddab7a114b15d610983"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"u1g20"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"tags"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token property">"suggestedDuration"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"0"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token property">"name"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"1-3 Listening"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token property">"block_id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"681817aaf75845468e464e1a8d82f2c8"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token property">"url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"u1g14"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token property">"tags"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token property">"role"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"node"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token property">"children"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"role"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"node"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"children"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"role"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"group"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"tab_type"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"task"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"name"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Get a clue"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"scoreDetail"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"u1g25"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"u1g25"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"tags"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"name"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Get a clue"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"block_id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"b332335ab3554dffb92afcae5f815b5a"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"u1g24"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"tags"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"role"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"node"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"children"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"role"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"group"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"tab_type"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"task"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"name"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"View it-1"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"scoreDetail"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"u1g27"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"u1g27"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"tags"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"role"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"group"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"tab_type"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"task"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"name"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"View it-2"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"scoreDetail"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"u1g545"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"u1g545"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"tags"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"role"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"group"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"tab_type"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"task"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"name"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"View it-3"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"scoreDetail"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"u1g29"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"u1g29"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"tags"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"name"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"View it"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"block_id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"a2ecf6464d5f480e98242ebe4431a73b"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"u1g26"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"tags"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"role"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"node"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"children"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"role"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"group"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"tab_type"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"task"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"name"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Think and speak"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"scoreDetail"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"u1g31"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"u1g31"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                  </span><span class="token property">"tags"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"name"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Think and speak"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"block_id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"120d0784e63c414793f5e648c416144b"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"u1g30"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token property">"tags"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token property">"suggestedDuration"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"0"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token property">"name"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"1-4 Viewing"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token property">"block_id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"765a1be83ac5437aaca8fa150ad5af2e"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token property">"url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"u1g22"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token property">"tags"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"name"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Listening to the world"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"tags"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="需求">需求<a class="hash-link" href="#需求" title="标题的直接链接">​</a></h3><p>可以看到数据比一开始的例子复杂了可不是一点，不过先别管这些数据是干啥的，说说需求，从结构上也能看出来，是有很多<code>children</code>嵌套的，而需求就是<strong>获取<code>role</code>为<code>group</code>的<code>children</code>节点数据</strong></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="js-实现遍历">js 实现遍历<a class="hash-link" href="#js-实现遍历" title="标题的直接链接">​</a></h3><p>先说说 js 如何实现的，我贴一下对应的代码（当时项目的代码，稍微修改的一点），可自己粘贴运行一下。</p><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> groupList </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">for</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> node </span><span class="token keyword" style="color:rgb(0, 0, 255)">of</span><span class="token plain"> json</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">children</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">??</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">role</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'group'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> groupList</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">push</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token spread operator" style="color:rgb(0, 0, 0)">...</span><span class="token plain">node </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">for</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> group </span><span class="token keyword" style="color:rgb(0, 0, 255)">of</span><span class="token plain"> node</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">children</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">??</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">group</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">role</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'group'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> groupList</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">push</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token spread operator" style="color:rgb(0, 0, 0)">...</span><span class="token plain">group </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">for</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> child </span><span class="token keyword" style="color:rgb(0, 0, 255)">of</span><span class="token plain"> group</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">children</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">??</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">child</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">role</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'group'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> groupList</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">push</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token spread operator" style="color:rgb(0, 0, 0)">...</span><span class="token plain">child </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> children4 </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> child</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">children</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">??</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">for</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> child </span><span class="token keyword" style="color:rgb(0, 0, 255)">of</span><span class="token plain"> children4</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">child</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">role</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'group'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> groupList</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">push</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token spread operator" style="color:rgb(0, 0, 0)">...</span><span class="token plain">child </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">groupList</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>因为这些数据中，是存在不确定性的，也就是在当前节点下，二级节点可能有<code>children</code>，而其他节点下的二级很可能没有 <code>children</code>，所以我在这边就加上 <code>?? []</code> （Typescript 中的<code>??</code>语法，你可以把 <code>??</code> 当做 <code>||</code> ）来判断是否有<code>children</code>节点，有些读者可能会思考，为啥不用递归呢。说的是挺轻松的，但是递归是很容易出问题的，万一爬取到后台数据进行了一些修改，很有可能对于的递归算法将失效，甚至导致堆栈溢出，所以我这边值循环 4 级<code>chilren</code>节点（实际遇到的貌似也只有 4 级，谁又能保证爬取到数据就一定只有 4 级呢）。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="jsonpath-获取">jsonpath 获取<a class="hash-link" href="#jsonpath-获取" title="标题的直接链接">​</a></h3><p>于是了解到 jsonpath 后，我第一个时间就开始分析这样的数据，果不其然，得到了我想要的结果 ⬇️</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20210919200826079.png" alt="image-20210919200826079" class="img_ev3q"></p><p>语法：<code>$..children[?(@.role=="group")]</code></p><p>语法意思很明确，根节点下遍历所有<code>children</code>节点，同时<code>role</code>等于<code>group</code>，呈现的效果如上图。</p><p>而回到需求，<strong>就是获取<code>role</code>为<code>group</code>的<code>children</code>节点数据</strong>，而 jsonpath 就帮我轻松实现我想要的效果。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="最终思考">最终思考<a class="hash-link" href="#最终思考" title="标题的直接链接">​</a></h2><p>实际上这样的需求我已经不止遇到一次，二次了，然而我寻求百度与群友的时候，给我的结果都不尽人意。但都没有提及到 jsonpath 来进行获取。也许是我的搜索方式有问题，但千篇一律都是 js 如何解析多层 json，以及遍历所有的子元素，虽然这些办法确实能解决我的问题，但每次遇到这种数据，都需要花上长时间去编写对应的逻辑。</p><p>在回想起当时爬取 HTML 页面数据的时候（数据与上面展示的差不多，都是树结构多层），而我只接触到了正则表达式，没了解过 CSS 选择器与 xpath。怎么办，为了实现目的，只好用现有的技术去实现，于是编写一个正则表达式就花费了近一个下午的时间，而使用 CSS 选择器 10 分钟不到就达到目的。没想到竟然有这么好用的方法，早知道多去了解点技术了。可能现在的心情和当时一样，只不过 HTML 换成了 JSON，编辑器还是那个编辑器，而我依旧还是我</p><p>也许这就是编程，也许这就是人生。</p>]]></content:encoded>
            <category>javascript</category>
            <category>json</category>
            <category>node</category>
        </item>
        <item>
            <title><![CDATA[使用Vue开发Chrome插件]]></title>
            <link>https://kuizuo.cn/vue-chrome-extension</link>
            <guid>vue-chrome-extension</guid>
            <pubDate>Sat, 18 Sep 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[使用 Vue2 开发一个 Chrome 插件]]></description>
            <content:encoded><![CDATA[<p><img loading="lazy" src="https://img.kuizuo.cn/mini.jpg" alt="mini" class="img_ev3q"></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="前言">前言<a class="hash-link" href="#前言" title="标题的直接链接">​</a></h2><p>我当时学习开发 Chrome 插件的时候，还不会 Vue，更别说 Webpack 了，所以使用的都是原生的 html 开发，效率就不提了，而这次就准备使用 vue-cli 来进行编写一个某 B 站获取视频信息,评论的功能（原本是打算做自动回复的），顺便巩固下 chrome 开发（快一年没碰脚本类相关技术了），顺便写套模板供自己后续编写 Chrome 插件做铺垫。</p><p>相关代码开源<a href="https://github.com/kuizuo/vue-chrome-extension" target="_blank" rel="noopener noreferrer">github 地址</a></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="环境搭建">环境搭建<a class="hash-link" href="#环境搭建" title="标题的直接链接">​</a></h2><p><a href="https://vue-web-extension.netlify.app/" target="_blank" rel="noopener noreferrer">Vue Web-Extension - A Web-Extension preset for VueJS (vue-web-extension.netlify.app)</a></p><div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">npm install -g @vue/cli</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">npm install -g @vue/cli-init</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">vue create --preset kocal/vue-web-extension my-extension</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">cd my-extension</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">npm run server</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>会提供几个选项，如 Eslint，background.js，tab 页，axios，如下图</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20210916142751129.png" alt="image-20210916142751129" class="img_ev3q"></p><p>选择完后，将会自动下载依赖，通过 npm run server 将会在根目录生成 dist 文件夹，将该文件拖至 Chrome 插件管理便可安装，由于使用了 webpack，所以更改代码将会热更新，不用反复的编译导入。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="项目结构">项目结构<a class="hash-link" href="#项目结构" title="标题的直接链接">​</a></h3><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">├─src</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">  ├─App</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">vue</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">  ├─background</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">js</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">  ├─main</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">js</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">  ├─manifest</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">json</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">  ├─views</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">   ├─About</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">vue</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">   └Home</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">vue</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">  ├─store</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">   └index</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">js</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">  ├─standalone</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">     ├─App</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">vue</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">     └main</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">js</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">  ├─router</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">   └index</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">js</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">  ├─popup</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">   ├─App</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">vue</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">   └main</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">js</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">  ├─override</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">    ├─App</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">vue</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">    └main</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">js</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">  ├─options</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">    ├─App</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">vue</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">    └main</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">js</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">  ├─devtools</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">    ├─App</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">vue</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">    └main</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">js</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">  ├─content</span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain">scripts</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">        └content</span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain">script</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">js</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">  ├─components</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">     └HelloWorld</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">vue</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">  ├─assets</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token plain">   └logo</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">png</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├─</span><span class="token keyword" style="color:rgb(0, 0, 255)">public</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├─</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">browserslistrc</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├─</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">eslintrc</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">js</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├─</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">gitignore</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├─babel</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">config</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">js</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├─</span><span class="token keyword" style="color:rgb(0, 0, 255)">package</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">json</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├─vue</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">config</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">js</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├─yarn</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">lock</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>根据所选的页面，并在 src 与 vue.config.js 中配置页面信息编译后 dist 目录结构如下</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">├─devtools</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">html</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├─favicon</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">ico</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├─index</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">html</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├─manifest</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">json</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├─options</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">html</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├─override</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">html</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├─popup</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">html</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├─_locales</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├─js</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├─icons</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">├─css</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="安装组件库">安装组件库<a class="hash-link" href="#安装组件库" title="标题的直接链接">​</a></h3><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="安装-elementui">安装 elementUI<a class="hash-link" href="#安装-elementui" title="标题的直接链接">​</a></h4><p>整体的开发和 vue2 开发基本上没太大的区别，不过既然是用 vue 来开发的话，那肯定少不了组件库了。</p><p>要导入 Element-ui 也十分简单，<code>Vue.use(ElementUI); </code>Vue2 中怎么导入 element，便怎么导入。演示如下</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20210916150154078.png" alt="image-20210916150154078" class="img_ev3q"></p><p>不过我没有使用 babel-plugin-component 来按需引入，按需引入一个按钮打包后大约 1.6m，而全量引入则是 5.5 左右。至于为什么不用，因为我需要在 content-scripts.js 中引入 element 组件，如果使用 babel-plugin-component 将无法按需导入组件以及样式（应该是只支持 vue 文件按需引入，总之就是折腾了我一个晚上的时间）</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="安装-tailwindcss">安装 tailwindcss<a class="hash-link" href="#安装-tailwindcss" title="标题的直接链接">​</a></h4><p>不过官方提供了如何使用 TailwindCSS，这里就演示一下</p><p><a href="https://www.tailwindcss.cn/docs/guides/vue-3-vite" target="_blank" rel="noopener noreferrer">在 Vue 3 和 Vite 安装 Tailwind CSS - Tailwind CSS 中文文档</a></p><p>推荐安装低版本，最新版有兼容性问题</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token function" style="color:rgb(0, 0, 255)">npm</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">install</span><span class="token plain"> tailwindcss@npm:@tailwindcss/postcss7-compat postcss@^7 autoprefixer@^9</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>创建 postcss.config.js 文件</p><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">postcss.config.js</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)">// postcss.config.js</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">module</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">exports</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">plugins</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">// ...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token function" style="color:rgb(0, 0, 255)">require</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'tailwindcss'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token function" style="color:rgb(0, 0, 255)">require</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'autoprefixer'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// if you have installed `autoprefixer`</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">// ...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>创建 tailwind.config.js 文件</p><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">tailwind.config.js</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)">// tailwind.config.js</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">module</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">exports</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">purge</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">// Specify the paths to all of the template files in your project</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">content</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'src/**/*.vue'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">// Whitelist selectors by using regular expression</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">whitelistPatterns</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token regex regex-delimiter">/</span><span class="token regex regex-source language-regex">-(leave|enter|appear)(|-(to|from|active))$</span><span class="token regex regex-delimiter">/</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// transitions</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain">data</span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain">v</span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token operator" style="color:rgb(0, 0, 0)">*</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// scoped css</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token comment" style="color:rgb(0, 128, 0)">// ...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>在 src/popup/App.vue 中导入样式，或在新建 style.css 在 mian.js 中<code>import "../style.css";</code></p><div class="language-vue codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">src/popup/App.vue</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-vue codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">&lt;style&gt;</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">/* purgecss start ignore */</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">@tailwind base;</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">@tailwind components;</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">/* purgecss end ignore */</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">@tailwind utilities;</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">&lt;/style&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>从官方例子导入一个登陆表单，效果如下</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20210916152633247.png" alt="image-20210916152633247" class="img_ev3q"></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="项目搭建">项目搭建<a class="hash-link" href="#项目搭建" title="标题的直接链接">​</a></h2><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="页面搭建">页面搭建<a class="hash-link" href="#页面搭建" title="标题的直接链接">​</a></h3><p>页面搭建就没什么好说的了，因为使用的是 element-ui，所以页面很快就搭建完毕了，效果如图</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20210918115438700.png" alt="image-20210918115438700" class="img_ev3q"></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="悬浮窗">悬浮窗<a class="hash-link" href="#悬浮窗" title="标题的直接链接">​</a></h3><p>悬浮窗其实可有可无，不过之前写 Chrome 插件的时候就写了悬浮窗，所以 vue 版的也顺带写一份。</p><p>要注意的是悬浮窗是内嵌到网页的（且在 document 加载前载入，也就是<code>"run_at": "document_start"</code>），所以需要通过 content-scripts.js 才能操作页面 Dom 元素，首先在配置清单 manifest.json 与 vue.confing.js 中匹配要添加的网站，以及注入的 js 代码，如下</p><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">manifest.json</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"content_scripts"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"matches"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">"https://www.bilibili.com/video/*"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"js"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">"js/jquery.js"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"js/content-script.js"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"css"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">"css/index.css"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"run_at"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"document_start"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"matches"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">"https://www.bilibili.com/video/*"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"js"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">"js/jquery.js"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"js/bilibili.js"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token property">"run_at"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"document_end"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">vue.config.js</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">contentScripts</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token literal-property property">entries</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token string-property property">'content-script'</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'src/content-scripts/content-script.js'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token literal-property property">bilibili</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'src/content-scripts/bilibili.js'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>由于是用 Vue，但又要在 js 中生成组件，就使用<code>document.createElement</code>来进行创建元素，Vue 组件如下（可拖拽）</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20210917142340863.png" alt="image-20210917142340863" class="img_ev3q"></p><div class="theme-admonition theme-admonition-danger alert alert--danger admonition_LlT9"><div class="admonitionHeading_tbUL"><span class="admonitionIcon_kALy"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"></path></svg></span>危险</div><div class="admonitionContent_S0QG"><p>如果使用<code>babel-plugin-component</code>按需引入，组件的样式将无法载入，同时自定义组件如果编写了 style 标签，那么也同样无法载入，报错：Cannot read properties of undefined (reading 'appendChild')</p><p>大致就是 css-loader 无法加载对应的 css 代码，如果执意要写 css 的话，直接在 manifest.json 中注入 css 即可</p></div></div><details open="" class="details_lb9f alert alert--info details_b_Ee" data-collapsed="false"><summary>完整代码</summary><div><div class="collapsibleContent_i85q"><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">content-script.js</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)">// 注意，这里引入的vue是运行时的模块，因为content是插入到目标页面，对组件的渲染需要运行时的vue， 而不是编译环境的vue （我也不知道我在说啥，反正大概意思就是这样）</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword module" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token imports maybe-class-name">Vue</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'vue/dist/vue.esm.js'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword module" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token imports maybe-class-name">ElementUI</span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token imports"> </span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token imports"> </span><span class="token imports maybe-class-name">Message</span><span class="token imports"> </span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'element-ui'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token maybe-class-name">Vue</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">use</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token maybe-class-name">ElementUI</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// 注意，必须设置了run_at=document_start此段代码才会生效</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token dom variable" style="color:rgb(9, 134, 88)">document</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">addEventListener</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'DOMContentLoaded'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'vue-chrome扩展已载入'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">insertFloat</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// 在target页面中新建一个带有id的dom元素，将vue对象挂载到这个dom上。</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">insertFloat</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> element </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token dom variable" style="color:rgb(9, 134, 88)">document</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">createElement</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'div'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> attr </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token dom variable" style="color:rgb(9, 134, 88)">document</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">createAttribute</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'id'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  attr</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">value</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'appPlugin'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  element</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">setAttributeNode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">attr</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token dom variable" style="color:rgb(9, 134, 88)">document</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">getElementsByTagName</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'body'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">appendChild</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">element</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> link </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token dom variable" style="color:rgb(9, 134, 88)">document</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">createElement</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'link'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> linkAttr </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token dom variable" style="color:rgb(9, 134, 88)">document</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">createAttribute</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'rel'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  linkAttr</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">value</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'stylesheet'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> linkHref </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token dom variable" style="color:rgb(9, 134, 88)">document</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">createAttribute</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'href'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  linkHref</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">value</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'https://unpkg.com/element-ui/lib/theme-chalk/index.css'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  link</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">setAttributeNode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">linkAttr</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  link</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">setAttributeNode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">linkHref</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token dom variable" style="color:rgb(9, 134, 88)">document</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">getElementsByTagName</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'head'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">appendChild</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">link</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> left </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> top </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> mx </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> my </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> onDrag </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">var</span><span class="token plain"> drag </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token function-variable function" style="color:rgb(0, 0, 255)">inserted</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">el</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">el</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method-variable function-variable method function property-access" style="color:rgb(0, 0, 255)">onmousedown</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">e</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        left </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> el</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">offsetLeft</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        top </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> el</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">offsetTop</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        mx </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> e</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">clientX</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        my </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> e</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">clientY</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">my </span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain"> top </span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">40</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        onDrag </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token dom variable" style="color:rgb(9, 134, 88)">window</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method-variable function-variable method function property-access" style="color:rgb(0, 0, 255)">onmousemove</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">e</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">onDrag</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> nx </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> e</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">clientX</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain"> mx </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> left</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> ny </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> e</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">clientY</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain"> my </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> top</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> width </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> el</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">clientWidth</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> height </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> el</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">clientHeight</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> bodyWidth </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token dom variable" style="color:rgb(9, 134, 88)">window</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">document</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">body</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">clientWidth</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> bodyHeight </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token dom variable" style="color:rgb(9, 134, 88)">window</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">document</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">body</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">clientHeight</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">nx </span><span class="token operator" style="color:rgb(0, 0, 0)">&lt;</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> nx </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">ny </span><span class="token operator" style="color:rgb(0, 0, 0)">&lt;</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> ny </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">ny </span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token plain"> bodyHeight </span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain"> height </span><span class="token operator" style="color:rgb(0, 0, 0)">&amp;&amp;</span><span class="token plain"> bodyHeight </span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain"> height </span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              ny </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> bodyHeight </span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain"> height</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">nx </span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token plain"> bodyWidth </span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain"> width</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              nx </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> bodyWidth </span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain"> width</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            el</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">style</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">left</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> nx </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'px'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            el</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">style</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">top</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> ny </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'px'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">el</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method-variable function-variable method function property-access" style="color:rgb(0, 0, 255)">onmouseup</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">e</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">onDrag</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            onDrag </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token dom variable" style="color:rgb(9, 134, 88)">window</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">kz_vm</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">Vue</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">el</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'#appPlugin'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">directives</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">drag</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> drag</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">template</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string string" style="color:rgb(163, 21, 21)"></span><br></span><span class="token-line" style="color:#000000"><span class="token template-string string" style="color:rgb(163, 21, 21)">      &lt;div class="float-page" ref="float" v-drag&gt;</span><br></span><span class="token-line" style="color:#000000"><span class="token template-string string" style="color:rgb(163, 21, 21)">        &lt;el-card class="box-card" :body-style="{ padding: '15px' }"&gt;</span><br></span><span class="token-line" style="color:#000000"><span class="token template-string string" style="color:rgb(163, 21, 21)">          &lt;div slot="header" class="clearfix" style="cursor: move"&gt;</span><br></span><span class="token-line" style="color:#000000"><span class="token template-string string" style="color:rgb(163, 21, 21)">            &lt;span&gt;悬浮窗&lt;/span&gt;</span><br></span><span class="token-line" style="color:#000000"><span class="token template-string string" style="color:rgb(163, 21, 21)">            &lt;el-button style="float: right; padding: 3px 0" type="text" @click="toggle"&gt;{{ show ? '收起' : '展开'}}&lt;/el-button&gt;</span><br></span><span class="token-line" style="color:#000000"><span class="token template-string string" style="color:rgb(163, 21, 21)">          &lt;/div&gt;</span><br></span><span class="token-line" style="color:#000000"><span class="token template-string string" style="color:rgb(163, 21, 21)">          &lt;transition name="ul"&gt;</span><br></span><span class="token-line" style="color:#000000"><span class="token template-string string" style="color:rgb(163, 21, 21)">            &lt;div v-if="show" class="ul-box"&gt;</span><br></span><span class="token-line" style="color:#000000"><span class="token template-string string" style="color:rgb(163, 21, 21)">              &lt;span&gt; {{user}} &lt;/span&gt;</span><br></span><span class="token-line" style="color:#000000"><span class="token template-string string" style="color:rgb(163, 21, 21)">            &lt;/div&gt;</span><br></span><span class="token-line" style="color:#000000"><span class="token template-string string" style="color:rgb(163, 21, 21)">          &lt;/transition&gt;</span><br></span><span class="token-line" style="color:#000000"><span class="token template-string string" style="color:rgb(163, 21, 21)">        &lt;/el-card&gt;</span><br></span><span class="token-line" style="color:#000000"><span class="token template-string string" style="color:rgb(163, 21, 21)">      &lt;/div&gt;</span><br></span><span class="token-line" style="color:#000000"><span class="token template-string string" style="color:rgb(163, 21, 21)">      </span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token function-variable function" style="color:rgb(0, 0, 255)">data</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token literal-property property">show</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token literal-property property">list</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token literal-property property">user</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token literal-property property">username</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">''</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token literal-property property">follow</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token literal-property property">title</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">''</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token literal-property property">view</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token function" style="color:rgb(0, 0, 255)">mounted</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">methods</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token function" style="color:rgb(0, 0, 255)">toggle</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">show</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">!</span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">show</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></div></div></details><p>因为只能在 js 中编写 vue 组件，所以得用 template 模板，同时使用了 directives，给组件添加了拖拽的功能（尤其是<code>window.onmousemove</code>，如果是元素绑定他自身的鼠标移动事件，那么拖拽鼠标将会十分卡顿），还使用了 transition 来进行缓慢动画效果其中注入的 css 代码如下</p><div class="language-css codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-css codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token selector class">.float-page</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">width</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">400</span><span class="token unit">px</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">border-radius</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">8</span><span class="token unit">px</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">position</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> fixed</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">left</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">50</span><span class="token unit">%</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">top</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">25</span><span class="token unit">%</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">z-index</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1000001</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token selector class">.el-card__header</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">padding</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">10</span><span class="token unit">px</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">15</span><span class="token unit">px</span><span class="token plain"> </span><span class="token important">!important</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token selector class">.ul-box</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">height</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">200</span><span class="token unit">px</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">overflow</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> hidden</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token selector class">.ul-enter-active</span><span class="token selector punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token selector"></span><br></span><span class="token-line" style="color:#000000"><span class="token selector"></span><span class="token selector class">.ul-leave-active</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">transition</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> all </span><span class="token number" style="color:rgb(9, 134, 88)">0.5</span><span class="token unit">s</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token selector class">.ul-enter</span><span class="token selector punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token selector"></span><br></span><span class="token-line" style="color:#000000"><span class="token selector"></span><span class="token selector class">.ul-leave-to</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">height</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>相关逻辑可自行观看，这里不在赘述了，并不复杂。</p><p>也顺带是复习一下 HTML 中鼠标事件和 vue 自定义命令了</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="功能实现">功能实现<a class="hash-link" href="#功能实现" title="标题的直接链接">​</a></h3><p>主要功能</p><ul><li><p>检测视频页面，输出对应 up 主，关注数以及视频标题播放（参数过多就不一一显示了）</p></li><li><p>监控关键词根据内容判断是否点赞，例如文本出现了下次一定，那么就点赞。</p></li></ul><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="输出相关信息">输出相关信息<a class="hash-link" href="#输出相关信息" title="标题的直接链接">​</a></h4><p>这个其实只要接触过一丢丢爬虫的肯定都会知道如何实现，通过右键审查元素，像这样</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20210918104907148.png" alt="image-20210918104907148" class="img_ev3q"></p><p>然后使用 dom 操作，选择对应的元素，输出便可</p><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token plain"> </span><span class="token dom variable" style="color:rgb(9, 134, 88)">document</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">querySelector</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">"#v_upinfo &gt; div.up-info_right &gt; div.name &gt; a.username"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">innerText</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token operator" style="color:rgb(0, 0, 0)">&lt;</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'老番茄'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>当然使用 JQuery 效果也是一样的。后续我都会使用 JQuery 来进行操作</p><p>在 src/content-script/bilibili.js 中写下如下代码</p><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token dom variable" style="color:rgb(9, 134, 88)">window</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method-variable function-variable method function property-access" style="color:rgb(0, 0, 255)">onload</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'加载完毕'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">getInfo</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> username </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">$</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'#v_upinfo &gt; div.up-info_right &gt; div.name &gt; a.username'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">text</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> follow </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">$</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string string" style="color:rgb(163, 21, 21)">#v_upinfo &gt; div.up-info_right &gt; div.btn-panel &gt; div.default-btn.follow-btn.btn-transition.b-gz.following &gt; span &gt; span &gt; span</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">text</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> title </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">$</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string string" style="color:rgb(163, 21, 21)">#viewbox_report &gt; h1 &gt; span</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">text</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> view </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">$</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'#viewbox_report &gt; div &gt; span.view'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">attr</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'title'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">username</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> follow</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> title</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> view</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">getInfo</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>重新加载插件，然后输出查看结果</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">加载完毕</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">bilibili</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">js</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token number" style="color:rgb(9, 134, 88)">19</span><span class="token plain"> 老番茄 </span><span class="token number" style="color:rgb(9, 134, 88)">1606.0</span><span class="token plain">万 顶级画质 总播放数</span><span class="token number" style="color:rgb(9, 134, 88)">2368406</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>这些数据肯定单纯的输出肯定是没什么作用的，要能显示到内嵌悬浮窗口，或者是 popup 页面上（甚至发送 ajax 请求到远程服务器上保存）</p><p>对上面代码微改一下</p><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token dom variable" style="color:rgb(9, 134, 88)">window</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method-variable function-variable method function property-access" style="color:rgb(0, 0, 255)">onload</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'加载完毕'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">getInfo</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> username </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">$</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'#v_upinfo &gt; div.up-info_right &gt; div.name &gt; a.username'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">text</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">trim</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> follow </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">$</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string string" style="color:rgb(163, 21, 21)">#v_upinfo &gt; div.up-info_right &gt; div.btn-panel &gt; div.default-btn.follow-btn.btn-transition.b-gz.following &gt; span &gt; span &gt; span</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">text</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> title </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">$</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string string" style="color:rgb(163, 21, 21)">#viewbox_report &gt; h1 &gt; span</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">text</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> view </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">$</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'#viewbox_report &gt; div &gt; span.view'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">attr</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'title'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">//console.log(username, follow, title, view);</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token dom variable" style="color:rgb(9, 134, 88)">window</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">kz_vm</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">user</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      username</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      follow</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      title</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      view</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">getInfo</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>其中<code>window.kz_vm</code>是通过<code>window.kz_vm = new Vue()</code> 初始化的，方便我们操作 vm 对象，就需要通过 jquery 选择元素在添加属性了。如果你想的话也可以直接在 content-script.js 上编写代码，这样就无需使用 window 对象，但这样导致一些业务逻辑都堆在一个文件里，所以我习惯分成 bilibili.js 然后注入方式为 document_end，然后在操作 dom 元素吗，实现效果如下</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20210918110958104.png" alt="image-20210918110958104" class="img_ev3q"></p><p>如果像显示到 popup 页面只需要通过页面通信就行了，不过前提得先 popup 打开才行，所以一般都是通过 background 来进行中转，一般来说很少 content –&gt; popup（因为操作 popup 的前提都是 popup 要打开），相对更多的是 content –&gt; background 或 popup –&gt; content</p><p><a href="https://www.cnblogs.com/liuxianan/p/chrome-plugin-develop.html#content-script%E4%B8%BB%E5%8A%A8%E5%8F%91%E6%B6%88%E6%81%AF%E7%BB%99%E5%90%8E%E5%8F%B0" target="_blank" rel="noopener noreferrer">content-script 主动发消息给后台 我是小茗同学 - 博客园 (cnblogs.com)</a></p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="实现评论">实现评论<a class="hash-link" href="#实现评论" title="标题的直接链接">​</a></h4><p>这边简单编写了一下页面，通过 popup 给 content，让 content 输入评论内容，与点击发送，先看效果</p><p><img loading="lazy" src="https://img.kuizuo.cn/bilibili_comment.gif" alt="bilibili_comment" class="img_ev3q"></p><p>同样的，找到对应元素位置</p><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)">// 评论文本框</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token function" style="color:rgb(0, 0, 255)">$</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'#comment &gt; div &gt; div.comment &gt; div &gt; div.comment-send &gt; div.textarea-container &gt; textarea'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">val</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'要回复的内容'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// 评论按钮</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token function" style="color:rgb(0, 0, 255)">$</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'#comment &gt; div &gt; div.comment &gt; div &gt; div.comment-send &gt; div.textarea-container &gt; button'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">click</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>接着就是写页面通信的了，可以看到是 popup 向 content 发送请求</p><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">src/content-script/bilibili.js</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token dom variable" style="color:rgb(9, 134, 88)">window</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method-variable function-variable method function property-access" style="color:rgb(0, 0, 255)">onload</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'content加载完毕'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">comment</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    chrome</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">runtime</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">onMessage</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">addListener</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">request</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> sender</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> sendResponse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> cmd</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> message </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> request</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">cmd </span><span class="token operator" style="color:rgb(0, 0, 0)">===</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'addComment'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token function" style="color:rgb(0, 0, 255)">$</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'#comment &gt; div &gt; div.comment &gt; div &gt; div.comment-send &gt; div.textarea-container &gt; textarea'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">val</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">message</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token function" style="color:rgb(0, 0, 255)">$</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'#comment &gt; div &gt; div.comment &gt; div &gt; div.comment-send &gt; div.textarea-container &gt; button'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">click</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token function" style="color:rgb(0, 0, 255)">sendResponse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'我收到了你的消息！'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">comment</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><div class="language-html codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">src/popup/App.vue</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-html codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">template</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">div</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">el-container</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">el-header</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">height</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">24</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain">B站小工具</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">el-header</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">el-main</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">el-row</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">:gutter</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">5</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">el-input</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">type</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">textarea</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">:rows</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">2</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">placeholder</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">请输入内容</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">v-model</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">message</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">class</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">mb-5</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"> </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">el-input</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">div</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">el-button</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">@click</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">addComment</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain">评论</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">el-button</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">div</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">el-row</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">el-main</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">el-container</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">div</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">template</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">script</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">  </span><span class="token script language-javascript keyword module" style="color:rgb(0, 0, 255)">export</span><span class="token script language-javascript"> </span><span class="token script language-javascript keyword module" style="color:rgb(0, 0, 255)">default</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">    </span><span class="token script language-javascript literal-property property">name</span><span class="token script language-javascript operator" style="color:rgb(0, 0, 0)">:</span><span class="token script language-javascript"> </span><span class="token script language-javascript string" style="color:rgb(163, 21, 21)">'App'</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">    </span><span class="token script language-javascript function" style="color:rgb(0, 0, 255)">data</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">      </span><span class="token script language-javascript keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">        </span><span class="token script language-javascript literal-property property">message</span><span class="token script language-javascript operator" style="color:rgb(0, 0, 0)">:</span><span class="token script language-javascript"> </span><span class="token script language-javascript string" style="color:rgb(163, 21, 21)">''</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">        </span><span class="token script language-javascript literal-property property">list</span><span class="token script language-javascript operator" style="color:rgb(0, 0, 0)">:</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">        </span><span class="token script language-javascript literal-property property">open</span><span class="token script language-javascript operator" style="color:rgb(0, 0, 0)">:</span><span class="token script language-javascript"> </span><span class="token script language-javascript boolean">false</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">      </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">    </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">    </span><span class="token script language-javascript function" style="color:rgb(0, 0, 255)">created</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">      chrome</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token script language-javascript property-access">storage</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token script language-javascript property-access">sync</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token script language-javascript method function property-access" style="color:rgb(0, 0, 255)">get</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token script language-javascript string" style="color:rgb(163, 21, 21)">'list'</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token script language-javascript parameter">obj</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">        </span><span class="token script language-javascript keyword" style="color:rgb(0, 0, 255)">this</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token script language-javascript property-access">list</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:rgb(0, 0, 0)">=</span><span class="token script language-javascript"> obj</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token script language-javascript string" style="color:rgb(163, 21, 21)">'list'</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">      </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">    </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">    </span><span class="token script language-javascript function" style="color:rgb(0, 0, 255)">mounted</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">      chrome</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token script language-javascript property-access">runtime</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token script language-javascript property-access">onMessage</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token script language-javascript method function property-access" style="color:rgb(0, 0, 255)">addListener</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token script language-javascript keyword" style="color:rgb(0, 0, 255)">function</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token script language-javascript parameter">request</span><span class="token script language-javascript parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token script language-javascript parameter"> sender</span><span class="token script language-javascript parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token script language-javascript parameter"> sendResponse</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">        </span><span class="token script language-javascript console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token script language-javascript method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token script language-javascript string" style="color:rgb(163, 21, 21)">'收到来自content-script的消息：'</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">        </span><span class="token script language-javascript console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token script language-javascript method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token script language-javascript">request</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token script language-javascript"> sender</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token script language-javascript"> sendResponse</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">        </span><span class="token script language-javascript function" style="color:rgb(0, 0, 255)">sendResponse</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token script language-javascript string" style="color:rgb(163, 21, 21)">'我是后台，我已收到你的消息：'</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:rgb(0, 0, 0)">+</span><span class="token script language-javascript"> </span><span class="token script language-javascript known-class-name class-name" style="color:rgb(38, 127, 153)">JSON</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token script language-javascript method function property-access" style="color:rgb(0, 0, 255)">stringify</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token script language-javascript">request</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">      </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">    </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">    </span><span class="token script language-javascript literal-property property">methods</span><span class="token script language-javascript operator" style="color:rgb(0, 0, 0)">:</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">      </span><span class="token script language-javascript function" style="color:rgb(0, 0, 255)">sendMessageToContentScript</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token script language-javascript parameter">message</span><span class="token script language-javascript parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token script language-javascript parameter"> callback</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">        chrome</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token script language-javascript property-access">tabs</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token script language-javascript method function property-access" style="color:rgb(0, 0, 255)">query</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token script language-javascript"> </span><span class="token script language-javascript literal-property property">active</span><span class="token script language-javascript operator" style="color:rgb(0, 0, 0)">:</span><span class="token script language-javascript"> </span><span class="token script language-javascript boolean">true</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token script language-javascript"> </span><span class="token script language-javascript literal-property property">currentWindow</span><span class="token script language-javascript operator" style="color:rgb(0, 0, 0)">:</span><span class="token script language-javascript"> </span><span class="token script language-javascript boolean">true</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token script language-javascript"> </span><span class="token script language-javascript keyword" style="color:rgb(0, 0, 255)">function</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token script language-javascript parameter">tabs</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">          chrome</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token script language-javascript property-access">tabs</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token script language-javascript method function property-access" style="color:rgb(0, 0, 255)">sendMessage</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token script language-javascript">tabs</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token script language-javascript number" style="color:rgb(9, 134, 88)">0</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token script language-javascript property-access">id</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token script language-javascript"> message</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token script language-javascript"> </span><span class="token script language-javascript keyword" style="color:rgb(0, 0, 255)">function</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token script language-javascript parameter">response</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">            </span><span class="token script language-javascript keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token script language-javascript">callback</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript function" style="color:rgb(0, 0, 255)">callback</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token script language-javascript">response</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">          </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">        </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">      </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">      </span><span class="token script language-javascript function" style="color:rgb(0, 0, 255)">addComment</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">        </span><span class="token script language-javascript keyword" style="color:rgb(0, 0, 255)">this</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token script language-javascript method function property-access" style="color:rgb(0, 0, 255)">sendMessageToContentScript</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token script language-javascript"> </span><span class="token script language-javascript literal-property property">cmd</span><span class="token script language-javascript operator" style="color:rgb(0, 0, 0)">:</span><span class="token script language-javascript"> </span><span class="token script language-javascript string" style="color:rgb(163, 21, 21)">'addComment'</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token script language-javascript"> </span><span class="token script language-javascript literal-property property">message</span><span class="token script language-javascript operator" style="color:rgb(0, 0, 0)">:</span><span class="token script language-javascript"> </span><span class="token script language-javascript keyword" style="color:rgb(0, 0, 255)">this</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token script language-javascript property-access">message</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token script language-javascript"> </span><span class="token script language-javascript keyword" style="color:rgb(0, 0, 255)">function</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">          </span><span class="token script language-javascript console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token script language-javascript method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token script language-javascript string" style="color:rgb(163, 21, 21)">'来自content的回复：'</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:rgb(0, 0, 0)">+</span><span class="token script language-javascript"> response</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">        </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">      </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">    </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript">  </span><span class="token script language-javascript punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#000000"><span class="token script language-javascript"></span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">script</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>代码就不解读了，调用 sendMessageToContentScript 方法即可。相关源码可自行下载查看</p><p>实现类似点赞功能也是同理的。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="相关模板">相关模板<a class="hash-link" href="#相关模板" title="标题的直接链接">​</a></h2><p><a href="https://github.com/antfu/vitesse-webext" target="_blank" rel="noopener noreferrer">vitesse-webext</a></p><p><a href="https://www.plasmo.com/" target="_blank" rel="noopener noreferrer">plasmo</a></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="整体体验">整体体验<a class="hash-link" href="#整体体验" title="标题的直接链接">​</a></h2><p>当时写 Chrome 插件的效率不能说慢，反正不快就是了，像一些 tips，都得自行封装。用过 Vue 的都知道写网页很方便，写 Chrome 插件未尝不是编写一个网页，当时的我在接触了 Vue 后就萌发了使用 vue 来编写 Chrome 的想法，当然肯定不止我一个这么想过，所以我在 github 上就能搜索到相应的源码，于是就有了这篇文章。</p><p>如果有涉及到爬取数据相关的，我肯定是首选使用 HTTP 协议，如果在搞不定我会选择使用 puppeteerjs，不过 Chrome 插件主要还是增强页面功能的，可以实现原本页面不具备的功能。</p><p>本文仅仅只是初步体验，简单编写了个小项目，后期有可能会实现一个百度网盘一键填写提取码，Js 自吐 Hooke 相关的。（原本是打算做 pdd 商家自动回复的，客户说要用客户端而不是网页端（客户端可以多号登陆），无奈，这篇博客就拿 B 站来演示了）</p>]]></content:encoded>
            <category>chrome</category>
            <category>plugin</category>
            <category>vue</category>
            <category>develop</category>
        </item>
        <item>
            <title><![CDATA[尝试云开发]]></title>
            <link>https://kuizuo.cn/try-to-cloud-develop</link>
            <guid>try-to-cloud-develop</guid>
            <pubDate>Mon, 06 Sep 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[在接触一个开源项目的时候，项目的后端采用的是云开发的模式（云函数，云数据库等等），本人又没接触过云开发，于是便有了这篇文章。]]></description>
            <content:encoded><![CDATA[<p>在接触一个开源项目的时候，项目的后端采用的是云开发的模式（云函数，云数据库等等），本人又没接触过云开发，于是便有了这篇文章。</p><p>本文使用是的腾讯云的产品，官方文档（很详细） <a href="https://docs.cloudbase.net/" target="_blank" rel="noopener noreferrer">云开发 CloudBase - 一站式后端云服务</a></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="云开发-cloudbase-环境">云开发 CloudBase 环境<a class="hash-link" href="#云开发-cloudbase-环境" title="标题的直接链接">​</a></h2><p><a href="https://docs.cloudbase.net/quick-start/create-env.html" target="_blank" rel="noopener noreferrer">开通环境 | 云开发 CloudBase - 一站式后端云服务</a></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="本地安装-cli-工具">本地安装 CLI 工具<a class="hash-link" href="#本地安装-cli-工具" title="标题的直接链接">​</a></h2><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="安装-nodejs">安装 Nodejs<a class="hash-link" href="#安装-nodejs" title="标题的直接链接">​</a></h3><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="安装-cloudbase-cli">安装 CloudBase CLI<a class="hash-link" href="#安装-cloudbase-cli" title="标题的直接链接">​</a></h3><p><a href="https://docs.cloudbase.net/cli-v1/install.html" target="_blank" rel="noopener noreferrer">安装 | 云开发 CloudBase - 一站式后端云服务</a></p><p>使用 NPM</p><div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">npm i -g @cloudbase/cli</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>或使用 Yarn</p><div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">yarn global add @cloudbase/cli</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>测试是否安装成功</p><div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">tcb -v</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="登录方式">登录方式<a class="hash-link" href="#登录方式" title="标题的直接链接">​</a></h2><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="腾讯云-云开发控制台授权">腾讯云-云开发控制台授权<a class="hash-link" href="#腾讯云-云开发控制台授权" title="标题的直接链接">​</a></h3><p>在您的终端中输入下面的命令</p><div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">tcb login</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>CloudBase CLI 会自动打开云开发控制台获取授权，您需要点击同意授权按钮允许 CloudBase CLI 获取授权。如您没有登录，您需要登录后才能进行此操作。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20210905085929546.png" alt="image-20210905085929546" class="img_ev3q"></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="腾讯云-云-api-密钥授权">腾讯云-云 API 密钥授权<a class="hash-link" href="#腾讯云-云-api-密钥授权" title="标题的直接链接">​</a></h3><p><a href="https://docs.cloudbase.net/cli-v1/login.html" target="_blank" rel="noopener noreferrer">登录方式 | 云开发 CloudBase - 一站式后端云服务</a></p><p>首先您需要到腾讯云官网获取<a href="https://console.cloud.tencent.com/cam/capi" target="_blank" rel="noopener noreferrer">云 API 密钥 (opens new window)</a>，然后在终端中输入下面的命令：</p><div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">tcb login --key</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>回车后，请按提示输入云 API 密钥的 SecretId 和 SecretKey 既可完成登录。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="ci-中的登录">CI 中的登录<a class="hash-link" href="#ci-中的登录" title="标题的直接链接">​</a></h3><p>在 CI（持续集成）构建中，您可以使用下面的方式通过 API 秘钥直接登录，避免交互式输入</p><div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">tcb login --apiKeyId xxx --apiKey xxx</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="临时秘钥登录">临时秘钥登录<a class="hash-link" href="#临时秘钥登录" title="标题的直接链接">​</a></h3><p>通过腾讯云临时秘钥登录，可以在某些比较敏感的场景下使用，使用短期有效的秘钥</p><div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">tcb login --apiKeyId xxx --apiKey xxx --token xxx</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="开始体验">开始体验<a class="hash-link" href="#开始体验" title="标题的直接链接">​</a></h2><p><a href="https://docs.cloudbase.net/api-reference/server/node-sdk/introduction.html" target="_blank" rel="noopener noreferrer">介绍 | 云开发 CloudBase - 一站式后端云服务</a></p><p>所采用的是<code>Nodejs SDK API</code>进行体验</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="安装">安装<a class="hash-link" href="#安装" title="标题的直接链接">​</a></h3><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">npm install </span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token plain">save @cloudbase</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain">node</span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain">sdk</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="初始化">初始化<a class="hash-link" href="#初始化" title="标题的直接链接">​</a></h3><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)">// 初始化示例</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> tcb </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">require</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'@cloudbase/node-sdk'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// 初始化资源</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">//云函数下使用默认环境</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> app </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> tcb</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">init</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="云函数">云函数<a class="hash-link" href="#云函数" title="标题的直接链接">​</a></h3><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="创建云函数">创建云函数<a class="hash-link" href="#创建云函数" title="标题的直接链接">​</a></h4><p><a href="https://docs.cloudbase.net/cloud-function/introduce.html" target="_blank" rel="noopener noreferrer">概述 | 云开发 CloudBase - 一站式后端云服务</a></p><p>创建一个项目，在项目的根目录创建 <strong>functions</strong> 文件夹。在 <strong>functions</strong> 下创建 <strong>hello_world</strong> 文件夹，包含 <strong>index.js</strong> 与 <strong>package.json</strong> 两个文件。</p><p>此时目录结构如下：</p><div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">└── functions</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    └── hello_world</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        ├── index.js</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        └── package.json</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p><strong>index.js</strong> 内容如下：</p><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">exports</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method-variable function-variable method function property-access" style="color:rgb(0, 0, 255)">main</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">async</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'Hello World!'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p><strong>package.json</strong> 内容如下：</p><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"name"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"hello_world"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"version"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"1.0.0"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"main"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"index.js"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="发布云函数">发布云函数<a class="hash-link" href="#发布云函数" title="标题的直接链接">​</a></h4><p>通过前面安装的 CLI 工具，在<strong>项目根目录</strong>运行以下命令，并且使用<strong>默认配置</strong>：</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">cloudbase fn deploy hello_world -e </span><span class="token operator" style="color:rgb(0, 0, 0)">&lt;</span><span class="token plain">env-id</span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p><code>&lt;env-id&gt;</code>为环境 id，可在云开发 CloudBase 中环境查看，部署结果如下</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20210905093035131.png" alt="image-20210905093035131" class="img_ev3q"></p><p>在控制面板中也能看到对应的云函数列表</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20210905093757875.png" alt="image-20210905093757875" class="img_ev3q"></p><p>后台也是能完整看到对应的代码的</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20210905094146730.png" alt="image-20210905094146730" class="img_ev3q"></p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="调用云函数">调用云函数<a class="hash-link" href="#调用云函数" title="标题的直接链接">​</a></h4><h5 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="使用-http-调用">使用 HTTP 调用<a class="hash-link" href="#使用-http-调用" title="标题的直接链接">​</a></h5><p>执行以下命令创建一条 HTTP 服务路由，路径为 <code>/hello</code>，指向的云函数为 <code>hello_world</code>：</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">cloudbase </span><span class="token function" style="color:rgb(0, 0, 255)">service</span><span class="token plain"> create -p hello -f hello_world -e </span><span class="token operator" style="color:rgb(0, 0, 0)">&lt;</span><span class="token plain">env-id</span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>随后便可以通过 <code>https://&lt;env-id&gt;.service.tcloudbase.com/hello</code> 调用云函数，并获得返回结果。如下图</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20210905093505618.png" alt="image-20210905093505618" class="img_ev3q"></p><h5 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="nodejs-调用">Nodejs 调用<a class="hash-link" href="#nodejs-调用" title="标题的直接链接">​</a></h5><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> tcb </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">require</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'@cloudbase/node-sdk'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> app </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> tcb</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">init</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">secretId</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'xxxxxx'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">secretKey</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'xxxxxx'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">env</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'env-id'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">app</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">callFunction</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">// 云函数名称</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">name</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'hello_world'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">// 传给云函数的参数</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">data</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">a</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">then</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">catch</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>输出</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">result</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'Hello World!'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">requestId</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> 'xxxxx‘</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="云数据库">云数据库<a class="hash-link" href="#云数据库" title="标题的直接链接">​</a></h3><p><a href="https://docs.cloudbase.net/database/introduce.html" target="_blank" rel="noopener noreferrer">概述 | 云开发 CloudBase - 一站式后端云服务</a></p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="实例代码如下">实例代码如下<a class="hash-link" href="#实例代码如下" title="标题的直接链接">​</a></h4><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> tcb </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">require</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'@cloudbase/node-sdk'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> app </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> tcb</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">init</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">secretId</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'xxxxx'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">secretKey</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'xxxxx'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">env</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'env-id'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> db </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> app</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">database</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">async</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">run</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token comment" style="color:rgb(0, 128, 0)">// 创建集合</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> res </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> db</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">createCollection</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'books'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token comment" style="color:rgb(0, 128, 0)">// // 插入一条数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> res1 </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> db</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">collection</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'books'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">add</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">category</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'Computer'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">name</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'Thinking in Java'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">onSale</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">sales</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">100</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">res1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token comment" style="color:rgb(0, 128, 0)">// 获取数据库中的数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> res2 </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> db</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">collection</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'books'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">get</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">res2</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token function" style="color:rgb(0, 0, 255)">run</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>运行结果如下</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">requestId</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'17bb3e26ecb_1'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">message</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'success'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">id</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'14139e12613431c809b949933c3209de'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">requestId</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'17bb3e27010_2'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">data</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">_id</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'14139e12613431c809b949933c3209de'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">category</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'Computer'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">name</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'Thinking in Java'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">onSale</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">sales</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">100</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">requestId</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'17bb3e270ca_3'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="云存储">云存储<a class="hash-link" href="#云存储" title="标题的直接链接">​</a></h3><p>暂时用不到，就没体验</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="登录鉴权">登录鉴权<a class="hash-link" href="#登录鉴权" title="标题的直接链接">​</a></h3><p>暂时用不到，就没体验</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="体验感受">体验感受<a class="hash-link" href="#体验感受" title="标题的直接链接">​</a></h2><p>除了要钱外，我目前是找不到第二个缺点，我个人体验下来，整体流程可以说是非常爽的那种。因为部署项目是一件特别折腾的一件事情，而使用云开发门槛瞬间减少一半，只要会写 js 函数，会调用数据库，就足够搞定一个后端服务了。如果是搞小程序的，又要搞服务这些，直接上手云开发，微信用户，微信支付直接一条龙服务。</p><p>当然了如果要搞什么分布式，集群啥的，那还是老老实实的用后端框架吧。</p>]]></content:encoded>
            <category>develop</category>
            <category>cloud</category>
        </item>
        <item>
            <title><![CDATA[MongoDB按时间分组]]></title>
            <link>https://kuizuo.cn/mongodb-time-grouping</link>
            <guid>mongodb-time-grouping</guid>
            <pubDate>Mon, 30 Aug 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[需求]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="需求">需求<a class="hash-link" href="#需求" title="标题的直接链接">​</a></h2><p>需求是这样的，要统计每一周的各个商品的销售记录，使用 echarts 图表呈现，如下图</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20210830214556262.png" alt="image-20210830214556262" class="img_ev3q"></p><p>说实话，一开始听到这个需求的时候，我是有点慌的，因为 MongoDB 的分组玩的比较少（Mysql 也差不多），又要按照对应的星期来进行分组，这在之前学习 MongoDB 的时候还没接触过，于是就准备写了这篇文章，来记录下我是如何进行分组的</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="mongodb-的一些时间操作符">MongoDB 的一些时间操作符<a class="hash-link" href="#mongodb-的一些时间操作符" title="标题的直接链接">​</a></h2><p>时间操作符（专业术语应该不是这个，后文暂且使用这个来描述），<strong>后面会用到的</strong></p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token literal-property property">$dayOfYear</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> 返回该日期是这一年的第几天。（全年</span><span class="token number" style="color:rgb(9, 134, 88)">366</span><span class="token plain">天）</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token literal-property property">$dayOfMonth</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> 返回该日期是这一个月的第几天。（</span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token plain">到</span><span class="token number" style="color:rgb(9, 134, 88)">31</span><span class="token plain">）</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token literal-property property">$dayOfWeek</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> 返回的是这个周的星期几。（</span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token plain">：星期日，</span><span class="token number" style="color:rgb(9, 134, 88)">7</span><span class="token plain">：星期六）</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token literal-property property">$year</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> 返回该日期的年份部分</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">$month： 返回该日期的月份部分（between </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token plain"> and </span><span class="token number" style="color:rgb(9, 134, 88)">12.</span><span class="token plain">）</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">$week： 返回该日期是所在年的第几个星期（between </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token plain"> and </span><span class="token number" style="color:rgb(9, 134, 88)">53</span><span class="token plain">）</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">$hour： 返回该日期的小时部分</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token literal-property property">$minute</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> 返回该日期的分钟部分</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token literal-property property">$second</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> 返回该日期的秒部分（以</span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token plain">到</span><span class="token number" style="color:rgb(9, 134, 88)">59</span><span class="token plain">之间的数字形式返回日期的第二部分，但可以是</span><span class="token number" style="color:rgb(9, 134, 88)">60</span><span class="token plain">来计算闰秒。）</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">$millisecond：返回该日期的毫秒部分（between </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token plain"> and </span><span class="token number" style="color:rgb(9, 134, 88)">999.</span><span class="token plain">）</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">$dateToString：</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$dateToString</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">format</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">&lt;</span><span class="token plain">formatString</span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">date</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">&lt;</span><span class="token plain">dateExpression</span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="日期分组">日期分组<a class="hash-link" href="#日期分组" title="标题的直接链接">​</a></h2><p><a href="https://blog.csdn.net/wangshu_liang/article/details/95326578?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-0.essearch_pc_relevant&amp;spm=1001.2101.3001.4242" target="_blank" rel="noopener noreferrer">mongdb 聚合查询日期 统计每天数据</a></p><p>关于日期分组的话，我是借鉴了这篇文章，也确实带我解惑了下如何按照日期分组。这里贴下我的代码</p><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> list </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">goodsModel</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">aggregate</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$project</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">date</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$dateToString</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'$created_at'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">10</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$group</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">_id</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'$date'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">count</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$sum</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$project</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">date</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'$_id'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">_id</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">count</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 再使用$project将_id改名为date</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$sort</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">date</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 根据日期倒序</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">exec</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>或者使用时间操作符（更准确一点）</p><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> list </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">goodsModel</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">aggregate</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">$project</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">date</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$dateToString</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">format</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'%Y-%m-%d'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">date</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'$created_at'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$group</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">_id</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'$date'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">count</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$sum</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$project</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">date</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'$_id'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">_id</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">count</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 再使用$project将_id改名为date</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$sort</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">date</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 根据日期倒序</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">exec</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>通过</p><blockquote><p>要注意的是，$group 里的属性必须为<!-- -->_<!-- -->id，不然无法分组</p></blockquote><p>获取到的数据如下（这里只显示一周）</p><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token property">"count"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">54</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"date"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"2021-08-30"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token property">"count"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">29</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"date"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"2021-08-29"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token property">"count"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">16</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"date"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"2021-08-28"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token property">"count"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">17</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"date"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"2021-08-27"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token property">"count"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">12</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"date"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"2021-08-26"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token property">"count"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">6</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"date"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"2021-08-25"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token property">"count"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"date"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"2021-08-24"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>如果只是日期和总商品的话，上面就足以显示对应的数据了，可我要根据星期进行分组的话，就需要替换 MongoDB 的时间转化函数了</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="星期分组">星期分组<a class="hash-link" href="#星期分组" title="标题的直接链接">​</a></h2><p>星期分组的话，其实也挺简单的，只需要把上面的</p><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token literal-property property">$project</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">day</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$dateToString</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">format</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"%Y-%m-%d"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">date</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"$created_at"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>替换成</p><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token literal-property property">$project</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">week</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">$dayOfWeek</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">date</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'$created_at'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>完整代码如下</p><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)">// 要获取的是一周前的零点时间</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> lastweekDay </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">dayjs</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token function" style="color:rgb(0, 0, 255)">dayjs</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">add</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token number" style="color:rgb(9, 134, 88)">7</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'day'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">format</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'YYYY-MM-DD'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">valueOf</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> list </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">goodsModel</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">aggregate</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$match</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">created_at</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$gte</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">Date</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">lastweekDay</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">//范围时间</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$project</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">week</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$dayOfWeek</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">date</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'$created_at'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$group</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">_id</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'$week'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">count</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$sum</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$project</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">week</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'$_id'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">_id</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">count</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 再使用$project将_id改名为week</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$sort</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">week</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 根据星期正序</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">exec</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>获取的结果如下</p><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">count</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">29</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">week</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 星期七(日)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">count</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">54</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">week</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">2</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 星期一</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">count</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">week</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">3</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 星期二</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">count</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">9</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">week</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">4</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 星期三</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">count</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">12</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">week</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">5</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 星期四</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">count</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">17</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">week</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">6</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 星期五</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">count</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">16</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">week</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">7</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 星期六</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>但是，细心的你可能会发现，貌似数据对不上，注当天时间为 2021-08-30，星期一</p><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token property">"count"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">54</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"date"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"2021-08-30"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 星期一</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token property">"count"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">29</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"date"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"2021-08-29"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 星期七(日)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token property">"count"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">16</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"date"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"2021-08-28"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 星期六</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token property">"count"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">17</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"date"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"2021-08-27"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 星期五</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token property">"count"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">12</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"date"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"2021-08-26"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 星期四</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token property">"count"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">9</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"date"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"2021-08-25"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 星期三</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token property">"count"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"date"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"2021-08-24"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 星期二</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>其实只需要把星期向后排序一位就行，因为星期本来就是将星期日作为第一天的，至此，按照星期分组总商品就算完毕了。同理，要按照月份，年份，甚至小时，分钟，都可以直接利用时间操作符转化时间来进行分组。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="多商品">多商品<a class="hash-link" href="#多商品" title="标题的直接链接">​</a></h2><p>上述只是获取了总商品了，要细分为多个商品的话，就需要再次利用聚合函数来进行分组了。</p><p>这里先演示分组多个商品先，就和正常分组一样</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> list </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">goodsModel</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">aggregate</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$group</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">_id</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"$type"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">count</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$sum</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">exec</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>结果如下（这里输出<!-- -->_<!-- -->id，是因为没有进行$project 改别名，商品所采用的是数字表示）</p><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token property">"_id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"count"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">111</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token property">"_id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">2</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"count"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">18</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token property">"_id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">4</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"count"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">2</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token property">"_id"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">3</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"count"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">16</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>可以看到统计的是直接是所有商品的总和。</p><p>但问题来了，怎么样能分组星期的同时，又对每个商品所在星期进行分组，并且到底是优先分组星期期呢，还是优先分组商品呢，这让我陷入深深的思考。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="最终实现">最终实现<a class="hash-link" href="#最终实现" title="标题的直接链接">​</a></h2><p>首先，绝对不可能使用两次<code>$group</code>，要么没有星期分组，要么没有商品分组，于是我就把思路放在<code>$project</code>与<code>$group</code>内，看看内部是否有其他方法可以实现。</p><p>其中<code>$group</code>可以将属性添加为数组，注意 <code>goods: { $push: "$goods" }</code></p><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> list </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">goodsModel</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">aggregate</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$match</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">created_at</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$gte</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">Date</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">lastweekDay</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$project</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">week</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$dayOfWeek</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">date</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'$created_at'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">goods</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$group</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">_id</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'$week'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">goods</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$push</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'$goods'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$project</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">week</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'$_id'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">_id</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">goods</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$sort</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">week</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">exec</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>可得到的数据却是这样的</p><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"goods"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">4</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">4</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">4</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"week"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"goods"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">5</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">4</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">4</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">4</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"week"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">2</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"goods"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"week"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">3</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"goods"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">3</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">3</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">3</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">3</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">3</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">3</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">3</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">3</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">4</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"week"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">4</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"goods"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">3</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">3</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">4</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"week"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">5</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"goods"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">3</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">3</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"week"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">6</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"goods"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">4</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">3</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">3</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">3</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">3</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">3</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">3</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"week"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">7</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>数据很接近了，如果我能把对应的商品总和算起来就行了，但问题是怎么合起来。。。</p><p>待会，goods 既然是数组的话，那我能不能<code>$unwind</code>全部展开，然后我再来一次聚合，说干就干！</p><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> list </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">goodsModel</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">aggregate</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$match</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">created_at</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$gte</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">Date</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">lastweekDay</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$project</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">week</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$dayOfWeek</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">date</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'$created_at'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">goods</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$group</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">_id</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'$week'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">goods</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$push</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'$goods'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$project</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">week</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'$_id'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">_id</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">goods</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$sort</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">week</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$unwind</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'$goods'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">exec</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>得到的数据（省略一堆）</p><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token property">"goods"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">4</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"week"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token property">"goods"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">4</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"week"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token property">"goods"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"week"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token property">"goods"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"week"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token property">"goods"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"week"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">2</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token property">"goods"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"week"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">3</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token property">"goods"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"week"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">4</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>然后我就卡住了，因为我无论如何都无法分组一个字段的时候，又加以限制条件，要么分组商品的时候，统计的是一周各商品总数据，要么就是分组星期的时候，统计的是总的商品数据。在搜索大量资料后，查看官方一些文档也未果，于是我决定自行写一个 js 函数来进行排序（实在是折腾不动了，能力有限 🥱）</p><p>最终完整代码</p><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> lastweekDay </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">dayjs</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token function" style="color:rgb(0, 0, 255)">dayjs</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">add</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token number" style="color:rgb(9, 134, 88)">7</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'day'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">format</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'YYYY-MM-DD'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">valueOf</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> list </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">goodsModel</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">aggregate</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$match</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">created_at</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$gte</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">Date</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">lastweekDay</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$project</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">week</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$dayOfWeek</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">date</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'$created_at'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">goods</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$group</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">_id</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'$week'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">goods</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$push</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'$goods'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$project</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">week</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'$_id'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">_id</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">goods</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">$sort</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">week</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">// { $unwind: "$goods" },</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">exec</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">getEleNums</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">var</span><span class="token plain"> map </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">forEach</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">e</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">map</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">e</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      map</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">e</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">+=</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">else</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      map</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">e</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> map</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">list </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> list</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">map</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">l</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  l</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">goods</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">getEleNums</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">l</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">goods</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> l</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">cosnole</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">list</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>运行后的 list 结果为</p><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token property">"goods"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token property">"1"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">26</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"4"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">3</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"week"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token property">"goods"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token property">"1"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">53</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"4"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">3</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"5"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"week"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">2</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token property">"goods"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token property">"1"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"week"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">3</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token property">"goods"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token property">"3"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">8</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"4"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"week"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">4</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token property">"goods"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token property">"1"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">9</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"3"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">2</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"4"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"week"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">5</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token property">"goods"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token property">"1"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">15</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"3"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">2</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"week"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">6</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token property">"goods"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token property">"1"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">9</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"3"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">6</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"4"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"week"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">7</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>如果是要 goods 为分组的话，只需要把上面聚合代码中 week 和 goods 替换一下便可。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="另一种实现方式">另一种实现方式<a class="hash-link" href="#另一种实现方式" title="标题的直接链接">​</a></h2><p>专门新建一个表，用于统计每天的销售记录，然后分组的时候就根据该表就行了，具体代码就实现了，思路是挺简单的，但是需要新建一个表，增加记录的时候有需要增加代码，如果业务复杂的话。。。</p>]]></content:encoded>
            <category>mongodb</category>
        </item>
        <item>
            <title><![CDATA[基于Axios封装HTTP类库]]></title>
            <link>https://kuizuo.cn/axios-http-class-library</link>
            <guid>axios-http-class-library</guid>
            <pubDate>Thu, 26 Aug 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[基于 Axios 封装 HTTP 类库，并发布到 npm 仓库中]]></description>
            <content:encoded><![CDATA[<p>一个基于 Axios 封装 HTTP 类库</p><p>源代码 <a href="https://github.com/kuizuo/kz-http" target="_blank" rel="noopener noreferrer">kz-http</a></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="使用方法">使用方法<a class="hash-link" href="#使用方法" title="标题的直接链接">​</a></h2><p>npm 安装</p><div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">npm i kz-http -S</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="请求">请求<a class="hash-link" href="#请求" title="标题的直接链接">​</a></h3><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword module" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token imports maybe-class-name">Http</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'kz-http'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> http </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">Http</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">http</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">get</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'https://www.example.com'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">then</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="能解决什么">能解决什么<a class="hash-link" href="#能解决什么" title="标题的直接链接">​</a></h2><p>axios 明明那么好用，为啥又要基于 axios 重新造一个轮子。首先不得否认的是 axios 确实好用，Github 能斩获近 90k 的 star，且基本已成为前端作为数据交互的必备工具。但是它对我所使用的环境下还是存在一定的问题，也就是我为什么要重新造一个轮子。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="node-环境下无法自动封装-set-cookie">Node 环境下无法自动封装 Set-Cookie<a class="hash-link" href="#node-环境下无法自动封装-set-cookie" title="标题的直接链接">​</a></h3><p>如果 axios 是运行在浏览器那还好说，就算你无论怎么请求，浏览器都会自动将你的所有请求中的响应包含 set-cookie 参数，提供给下一次同域下的请求。但是，Node 环境并不是浏览器环境，在 Node 环境中运行并不会自动保存 Cookie，还需要手动保存，并将 Cookie 添加至协议头给下一个请求。（如果是 Python 的话，request 有个 session 方法可以自动保存 cookie，十分方便）</p><p>一开始我是自行封装，将响应中的 set-cookie 全都存在实例对象 http.cookies 上，但封装的不彻底，如果有的网站</p><p>间请求存在跨域，那么会将携带不该属于该域下的 Cookies。于是乎，我在 github 仓库找到了一个库可达到我的目的</p><p><a href="https://github.com/3846masa/axios-cookiejar-support" target="_blank" rel="noopener noreferrer">3846masa/axios-cookiejar-support: Add tough-cookie support to axios. (github.com)</a></p><p>具体安装可以直接点击链接查看，这里贴下我<strong>之前</strong>的封装代码</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> tough </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">require</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'tough-cookie'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> axiosCookieJarSupport </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">require</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'axios-cookiejar-support'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token keyword module" style="color:rgb(0, 0, 255)">default</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token function" style="color:rgb(0, 0, 255)">axiosCookieJarSupport</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">axios</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">Http</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">public</span><span class="token plain"> cookieJar</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">public</span><span class="token plain"> </span><span class="token literal-property property">instance</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token maybe-class-name">AxiosInstance</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">construction</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">cookieJar</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">tough</span><span class="token class-name punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token class-name" style="color:rgb(38, 127, 153)">CookieJar</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword null nil" style="color:rgb(0, 0, 255)">null</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">allowSpecialUseDomain</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">instance</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> axios</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">create</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">jar</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">cookieJar</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">ignoreCookieErrors</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">withCredentials</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>这样 axios 就会自动将响应中的 set-cookie 封装起来，供下次使用</p><p>但是正是由于导入了这个包，导致每次请求都需要处理，就会导致请求速度变慢，实测大约是在 100ms 左右，同时导入这个包之后，实例化的对象都将会携带对应 cookies，想要删除又得对应 Url，于是决定自行封装相关代码可查看 request 方法，实测下来大约有 10ms 左右的差距（前提都通过创建实例来请求），不过有个缺陷，我封装的代码是不进行同源判断的，如何你当前站点请求的是 api1.test.com，获取到 cookie1，那么请求 api2.test.com 的时候也会将 cookie1 携带，这边不做判断是不想在请求的时候耗费时间，比如网页与手机协议，一般这种情况建议实例化两个对象，如</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> http_api1 </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">Http</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> http_api2 </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">Http</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="请求失败无法自动重试">请求失败无法自动重试<a class="hash-link" href="#请求失败无法自动重试" title="标题的直接链接">​</a></h3><p>在高并发的情况下，偶尔会出现请求超时，请求拒绝的情况，但是默认下 axios 是不支持自动重试请求的，不过可以借助插件<code>axios-retry</code>来达到这个目的</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> axiosRetry </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">require</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'axios-retry'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">Http</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">constructor</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">retryConfig</span><span class="token parameter operator" style="color:rgb(0, 0, 0)">?</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">instance</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> axios</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">create</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">retryConfig</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token function" style="color:rgb(0, 0, 255)">axiosRetry</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">instance</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token literal-property property">retries</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> retryConfig</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">retry</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 设置自动发送请求次数</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token function-variable function" style="color:rgb(0, 0, 255)">retryDelay</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">retryCount</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> retryCount </span><span class="token operator" style="color:rgb(0, 0, 0)">*</span><span class="token plain"> retryConfig</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">delay</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 重复请求延迟</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token literal-property property">shouldResetTimeout</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 重置超时时间</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token function-variable function" style="color:rgb(0, 0, 255)">retryCondition</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">axiosRetry</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">isNetworkOrIdempotentRequestError</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">code</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'ECONNABORTED'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">&amp;&amp;</span><span class="token plain"> error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">message</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">indexOf</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'timeout'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">!=</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'ECONNRESET'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'ETIMEDOUT'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">includes</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">code</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token comment" style="color:rgb(0, 128, 0)">// , 'ENOTFOUND'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>这边判断重新发送请求条件是连接拒绝，连接重置，和连接超时的情况。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="配置拦截器">配置拦截器<a class="hash-link" href="#配置拦截器" title="标题的直接链接">​</a></h3><p>有时候一个网站的协议是这样的，每一条 Post 都自动将所有参数进行拼接，然后进行 MD5 加密，并添加为 sign 参数，于是，不得不给每一条请求都进行这样的操作，那么有没有什么能在每次请求的时候，都自动的对参数进行 MD5 加密。如果使用过 axios 来配置过 JWT 效验，那自然就会熟悉给每条请求协议头都携带 JWT 数值。同样的，这里的加密例子同样使用，具体配置实例对象 http 的请求拦截器即可，如</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> http </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">Http</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// axios实例instance是公开的</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">http</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">instance</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">interceptors</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">request</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">use</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">config</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">// 执行每条请求都要处理的操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> config</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>同样的，响应拦截器也同理，例如请求返回的响应都进行加密处理，那么就可以通过响应拦截器进行统一解密，这里就不做过多描述，具体场景具体分析。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="封装一些常用方法">封装一些常用方法<a class="hash-link" href="#封装一些常用方法" title="标题的直接链接">​</a></h3><p>比如设置伪造 IP（setFakeIP），自动补全 referer 和 orgin 参数，禁止重定向等等，更详细的查看源码便可</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="发布-npm-包">发布 npm 包<a class="hash-link" href="#发布-npm-包" title="标题的直接链接">​</a></h2><p>如果要让别人使用的话，总不可能让他去下载源码然后编译吧，这里就借助 npm。</p><div class="theme-admonition theme-admonition-tip alert alert--success admonition_LlT9"><div class="admonitionHeading_tbUL"><span class="admonitionIcon_kALy"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>提示</div><div class="admonitionContent_S0QG"><p>在使用 npm 之前，请先使用<code>npm install -g npm@latest</code>升级为最新版，否则可能会提示 <strong>ERR! 426 Upgrade Required</strong>。原文 <a href="https://github.blog/2021-08-23-npm-registry-deprecating-tls-1-0-tls-1-1/" target="_blank" rel="noopener noreferrer">The npm registry is deprecating TLS 1.0 and TLS 1.1 | The GitHub Blog</a></p></div></div><p>创建 npm 账号，创建 package.json</p><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockTitle_Ktv7">package.json</div><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"name"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"kz-http"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"version"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"0.1.0"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"description"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"An HTTP class library based on axios"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"main"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"dist/index.js"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"scripts"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"build"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"tsc"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"author"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"kuizuo"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"license"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"ISC"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"dependencies"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"axios"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"^0.21.1"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"axios-retry"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"^3.1.9"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"devDependencies"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"typescript"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"^4.3.5"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"repository"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"type"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"git"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"url"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"git+https://github.com/kuizuo/kz-http.git"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"keywords"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">"node"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"axios"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"http"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>然后通过<code>npm login</code>登录 npm 账号，接着输入<code>npm publish --access public</code>发布即可</p><p>发布的是要注意以下几点</p><ul><li><p>如果 npm 镜像必须是官方的，否则无法登录，镜像还原</p><div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">npm config set registry https://registry.npmjs.org/</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>查看镜像配置地址</p><div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">npm get registry</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></li><li><p>如果包有重名，那么就无法发布，就必须要要改名</p></li><li><p>邮箱必须要验证（会接受一条下图邮箱），不然就会发布失败
<img loading="lazy" src="https://img.kuizuo.cn/image-20210826212258752.png" alt="image-20210826212258752" class="img_ev3q"></p></li><li><p><strong>请勿随意删包，否则同名的包将需要 24 小时后才能发布（亲测）</strong></p><blockquote><p>npm ERR! 403 403 Forbidden - PUT <a href="http://registry.npmjs.org/kz-http" target="_blank" rel="noopener noreferrer">http://registry.npmjs.org/kz-http</a> - kz-http cannot be republished until 24 hours have passed.</p></blockquote></li></ul><p>发布完成后，别人只需要通过<code>npm i kz-http</code>就可成功将模块下载至本地 node_modules 文件夹下</p>]]></content:encoded>
            <category>node</category>
            <category>http</category>
            <category>axios</category>
        </item>
        <item>
            <title><![CDATA[第二个博客搭建之Docusaurus]]></title>
            <link>https://kuizuo.cn/second-blog-is-docusaurus</link>
            <guid>second-blog-is-docusaurus</guid>
            <pubDate>Fri, 20 Aug 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[博客地址: 愧怍的小站]]></description>
            <content:encoded><![CDATA[<p>博客地址: <a href="https://kuizuo.cn/" target="_blank" rel="noopener noreferrer">愧怍的小站</a></p><p>源码地址：<a href="https://github.com/kuizuo/blog" target="_blank" rel="noopener noreferrer">kuizuo/blog</a></p><p>时隔近半年没好好整理文章，博客也写的不像个人样。😂</p><p>大半年没更新博客，一直忙着写项目（写到手软的那种），然后无意间在 B 站看到一个 Up 主 <a href="https://zxuqian.cn/" target="_blank" rel="noopener noreferrer">峰华前端工程师 </a> 基于 React 驱动的静态网站生成器搭建的个人博客。第一眼看到该站点的时候惊艳到我了，于是也想着搭建一个，作为个人站点使用。</p><p>不过国内 docusaurus 的使用者是真的少。Vuepress 都快烂大街了...</p><p>关于主题魔改可以看 <a href="/docs/docusaurus-guides">Docusaurus 主题魔改</a></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="安装">安装<a class="hash-link" href="#安装" title="标题的直接链接">​</a></h2><p>下载代码，根据相应命令运行即可，在本地运行还是相对比较容易的。</p><p>修改了下个人信息，然后将之前的博客文章迁移过来即可。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="额外功能页面">额外功能页面<a class="hash-link" href="#额外功能页面" title="标题的直接链接">​</a></h2><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="归档页"><a href="/archive">归档页</a><a class="hash-link" href="#归档页" title="标题的直接链接">​</a></h3><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220804052418993.png" alt="image-20220804052418993" class="img_ev3q"></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="网址导航"><a href="/website">网址导航</a><a class="hash-link" href="#网址导航" title="标题的直接链接">​</a></h3><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220804052016538.png" alt="image-20220804052016538" class="img_ev3q"></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="评论">评论<a class="hash-link" href="#评论" title="标题的直接链接">​</a></h3><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220804052746803.png" alt="image-20220804052746803" class="img_ev3q"></p><p>相关文章: <a href="/docusaurus-gitalk-plugin">Docusaurus 配置 Gitalk 评论插件</a></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="项目"><a href="/project">项目</a><a class="hash-link" href="#项目" title="标题的直接链接">​</a></h3><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220804052117492.png" alt="image-20220804052117492" class="img_ev3q"></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="部署">部署<a class="hash-link" href="#部署" title="标题的直接链接">​</a></h2><p>由于我是有个人的域名和服务器，所以之前部署项目都是直接将编译后的文件直接上传至服务器上，然后通过 nginx 就可以直接通过域名访问了，优点的话就是方便，但缺点很明显，每次更新一篇博客的话，就需要重新编译，然后重新拉去文件，并不能做到自动化编译部署。于是就想着采用第三方服务进行部署。</p><p>这里推荐使用 Vercel，我写过一篇 <a href="/vercel-deploy-blog">Vercel 部署个人博客</a> 的文章，部署十分简单。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="最后">最后<a class="hash-link" href="#最后" title="标题的直接链接">​</a></h2><p>我个人是比较满意该博客的，搜索，SEO，暗黑模式，博客列表，没有其他博客系统那么花里胡哨的，该有的整洁都有了，最主要是我个人不喜欢文章配背景图，尤其是那种与文章毫不相干的图，图片也许能减少阅读疲倦感，但欣赏的是内容的，而不是背景。</p><p>而且又是基于 Docusaurus，到时候是用来做一个项目的文档也方便许多。</p><p>还是要感谢下所开源的代码，同时 B 站视频教程也非常好，让我学到了一些前沿的前端技术。😄</p><p>也就不多浪费口舌了，博客既然搭建好了，那么接下来就可以专心的编写文章了。</p>]]></content:encoded>
            <category>blog</category>
            <category>docusaurus</category>
            <category>project</category>
        </item>
        <item>
            <title><![CDATA[记一次git丢失代码找回]]></title>
            <link>https://kuizuo.cn/lost-code-find-by-git</link>
            <guid>lost-code-find-by-git</guid>
            <pubDate>Sun, 15 Aug 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[记录 git 操作失误导致代码丢失与找回的过程]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="场景复现">场景复现<a class="hash-link" href="#场景复现" title="标题的直接链接">​</a></h2><p>今晚，我和往常一样对着电脑撸着代码，这时候我灵光一现，想到了一个好的功能，于是乎我就开始增加代码文件，更改之前已有的问题，当我实现完这个功能的时候，觉得可有可无，我想通过 Git 直接回退到我没有这个新功能的版本，把新增的文件和更改的文件全都给还原回去，然而在编写新功能的时候我忘记 Commit 了！！！（正常操作应该是新建一个分支，在新分支编写新功能），于是乎我点了如图操作（这里仅作为事件发生展示，并不为实际丢失个数）</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20210815141808996.png" alt="image-20210815141808996" class="img_ev3q"></p><p>没错，清空所有更改过的代码。导致这些文件直接丢失（并不在回收站），包括写新功能前的代码和写新功能后的代码全都丢失了 😭！！！</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="找回前提">找回前提<a class="hash-link" href="#找回前提" title="标题的直接链接">​</a></h2><p>庆幸的时候，写新功能前的代码我成功 add 到了暂存区，只是未 Commit 而已，那么就能找回对应的文件（仅仅只是文件，并且没有文件名，项目结构都无法还原 ）。如果有 Commit 的话非常好找回，直接回退上一个版本即可，如果连 add 操作都没有的话，除非像 VScode 插件 Local History 或一些 IDE 有记录本地文件，不然恐怕是真的找不回了。。。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="开始找回">开始找回<a class="hash-link" href="#开始找回" title="标题的直接链接">​</a></h2><p>故，此次目的是找回 add 过而未 commit 的文件，首先打开 git bash 输入</p><div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">git fsck --lost-found</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p><img loading="lazy" src="https://img.kuizuo.cn/image-20210815150520759.png" alt="image-20210815150520759" class="img_ev3q"></p><p>进入<code>.git\lost-found\other</code></p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20210815153556495.png" alt="image-20210815153556495" class="img_ev3q"></p><p>然后通过文本编辑器打开即可，如果是代码的话重命名对应的后缀，如果是图片这些就得对应删除前所对应的文件链接。名字是找不回来了，只能手动重命名。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="事后回想">事后回想<a class="hash-link" href="#事后回想" title="标题的直接链接">​</a></h2><p>可能这次丢失的仅仅只是几十个文件，下次丢失的可能就是一个项目了。所以在每次更改代码前做好备份才是首要做的，同时也感谢 git 这么好用的版本控制系统，不然这篇博客可能也不存在。</p>]]></content:encoded>
            <category>git</category>
            <category>code</category>
        </item>
        <item>
            <title><![CDATA[Redis获取六位不重复数字（邀请码）]]></title>
            <link>https://kuizuo.cn/redis-get-six-digit-number-invitation-code</link>
            <guid>redis-get-six-digit-number-invitation-code</guid>
            <pubDate>Wed, 11 Aug 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[需求]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="需求">需求<a class="hash-link" href="#需求" title="标题的直接链接">​</a></h2><p>针对每一个用户（用户量在 10w 以下）随机生成的邀请码（仅限六位数字），<strong>且不重复</strong></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="思考">思考<a class="hash-link" href="#思考" title="标题的直接链接">​</a></h2><p>如果能把这个不重复条件去除，那么只需要使用<code>Math.random</code>然后取小数点后六位就行了，但可惜要求就是不能重复， 要是重复还得了，到时候注册的时候都不知道奖励给那个邀请码账号。同时还要求邀请码在六位且数字，这就导致即使随机生成的，会有一定的可能出现相同的邀请码。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="解决方案">解决方案<a class="hash-link" href="#解决方案" title="标题的直接链接">​</a></h2><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="方案-1">方案 1<a class="hash-link" href="#方案-1" title="标题的直接链接">​</a></h3><p>先随机生成一个六位随机数字，然后在存的时候判断数据库是否存在该邀请码，如果存在那么就重新生成一个，直到该邀请码不存在，便存入。</p><p>优点：方便，如果用户量不大，完全可以
缺点：用户量上来的情况下，判断邀请码是否存在有可能需要一段时间，并且由于需要判断，故性能欠缺</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="方案-2">方案 2<a class="hash-link" href="#方案-2" title="标题的直接链接">​</a></h3><p>利用 redis 的 set 数据类型，先将所有的邀请码存入到 set 中，然后通过 srandmember 随机获取一个数值，在通过 srem 删除该元素即可。</p><p>或者也可以通过 list 队列，将预先随机生成的六位不重复数字的所有集合统统添加到队列中，然后获取的时候通过 rpop 或 lpop 获取</p><p>优点：相当于空间换时间，无需判断，后期即便用户量上来的，也完全可以重新生成一批（七位或字母）重新导入</p><p>缺点：过于依赖 Redis，redis 服务一旦停止，便无法正常获取数据。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="实现">实现<a class="hash-link" href="#实现" title="标题的直接链接">​</a></h2><p>既然想都想了，那怎么能不实现呢。我这边仅仅是一个测试 Demo，利用的是方案 2，通过 set 数据类型进行获取相关代码如下</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="预先存入数据">预先存入数据<a class="hash-link" href="#预先存入数据" title="标题的直接链接">​</a></h3><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> key </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'code'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">genCode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> num </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">999999</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">for</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> i </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">100000</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"> i </span><span class="token operator" style="color:rgb(0, 0, 0)">&lt;</span><span class="token plain"> num</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"> i</span><span class="token operator" style="color:rgb(0, 0, 0)">++</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    client</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">sadd</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">key</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> i</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">err</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'数据导入完毕'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token function" style="color:rgb(0, 0, 255)">genCode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="获取数据并删除">获取数据并删除<a class="hash-link" href="#获取数据并删除" title="标题的直接链接">​</a></h3><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)">// 输出所有成员</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">client</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">smembers</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">key</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">err</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// 随机获取一个数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">client</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">srandmember</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">key</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">err</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  client</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">srem</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">key</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">err</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>整体耗时不会超过 3 分钟</p><p>通过<code>console.time()</code>获取数据耗时如下</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword module" style="color:rgb(0, 0, 255)">default</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">174ms</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>]]></content:encoded>
            <category>redis</category>
        </item>
        <item>
            <title><![CDATA[Api接口风格]]></title>
            <link>https://kuizuo.cn/api-style</link>
            <guid>api-style</guid>
            <pubDate>Fri, 06 Aug 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[前后端数据交互，经常要和 Api 打交道，于是关于 Api 接口的设计，有必要好好写一写]]></description>
            <content:encoded><![CDATA[<p>前后端数据交互，经常要和 Api 打交道，于是关于 Api 接口的设计，有必要好好写一写</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="restful-api-风格">Restful api 风格<a class="hash-link" href="#restful-api-风格" title="标题的直接链接">​</a></h2><p>首先还是得说一下<strong>REST 是设计风格而不是标准</strong>，也就是在写 api 接口的时候，喜欢就遵循。</p><p>这里举一个常见的 api 接口设计</p><p>常见的 CRUD 操作</p><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token constant" style="color:rgb(129, 31, 63)">POST</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain">user</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain">list </span><span class="token comment" style="color:rgb(0, 128, 0)">// 获取列表</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token constant" style="color:rgb(129, 31, 63)">POST</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain">user</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token keyword" style="color:rgb(0, 0, 255)">get</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 获取用户</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token constant" style="color:rgb(129, 31, 63)">POST</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain">user</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain">add </span><span class="token comment" style="color:rgb(0, 128, 0)">// 添加用户</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token constant" style="color:rgb(129, 31, 63)">POST</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain">user</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain">edit </span><span class="token comment" style="color:rgb(0, 128, 0)">// 编辑用户</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token constant" style="color:rgb(129, 31, 63)">POST</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain">user</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token keyword" style="color:rgb(0, 0, 255)">delete</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 删除用户</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>与之对应 Restful Api 风格</p><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token constant" style="color:rgb(129, 31, 63)">GET</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain"> user </span><span class="token comment" style="color:rgb(0, 128, 0)">// 获取列表</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token constant" style="color:rgb(129, 31, 63)">GET</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain"> user </span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> id </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 获取用户</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token constant" style="color:rgb(129, 31, 63)">POST</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain"> user </span><span class="token comment" style="color:rgb(0, 128, 0)">// 添加用户</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token constant" style="color:rgb(129, 31, 63)">PUT</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain"> user </span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> id </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 编辑用户</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token constant" style="color:rgb(129, 31, 63)">DELETE</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain"> user </span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> id </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 删除用户</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// {id} 通过后端路由 参数Params可以获取到</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>可以看到 Restful 风格相比于正常的 POST 而言，少了请求的路径，而同时使用请求方法字段（GET,POST,PUT,DELETE） 要与之表明的意思也很明确（前提：在增删改查的时候），也就只是增删改查而已。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="我何时使用-restful">我何时使用 Restful<a class="hash-link" href="#我何时使用-restful" title="标题的直接链接">​</a></h2><p>这里我要说说我个人使用情况下，如果单单只是增删改查的话，我会使用 Restful 风格，好用是一方面，不必在修改数据的还要在 body 中添加 id 这个字段。其次 restful 确实也算广泛，但也仅仅只是在增删改查中。</p><p>实际业务中复杂情况太多了，有的时候仅仅这四个请求方法不能很明确的表达所要的意思，例如下面一些业务逻辑</p><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token constant" style="color:rgb(129, 31, 63)">POST</span><span class="token plain"> user</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain">login  发送登录请求</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token constant" style="color:rgb(129, 31, 63)">POST</span><span class="token plain"> user</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain">register  发送注册请求</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token constant" style="color:rgb(129, 31, 63)">POST</span><span class="token plain"> user</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain">info 获取个人信息</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token constant" style="color:rgb(129, 31, 63)">POST</span><span class="token plain"> user</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain">forget 忘记个人密码</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token constant" style="color:rgb(129, 31, 63)">POST</span><span class="token plain"> user</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token plain">getCode  获取验证码</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>此外还有充值，获取消费记录、登录记录等等就不一一列举了，总之这时候我毫不犹豫会使用 POST，可能有人会好奇，为啥获取信息和获取验证码的时候要使用 POST 请求，用 GET 不好吗？好，但后文会说为什么。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="易猜测-api-接口">易猜测 api 接口<a class="hash-link" href="#易猜测-api-接口" title="标题的直接链接">​</a></h2><p>实际上，采用了 Restful 风格，几乎一猜就能猜到对应的 api。比如商品管理，无非就是获取商品列表，添加商品，编辑商品，删除商品。同时又传入的是对应的 ID，这要是 Mysql，ID 基本都是按顺序的，万一 api 鉴权没做好，都不知道数据怎么变动的。当然这种情况一般都是比较少见的了。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="不易加密">不易加密<a class="hash-link" href="#不易加密" title="标题的直接链接">​</a></h2><p>上文不是说到为啥都要使用 POST 请求，原因也挺简单的，就是加密，GET 请求一般都不会携带过多参数，针对数据效验的话最多也就一个 MD5 效验，然而是远远不够的，而 POST 所能携带的数据不仅仅是 MD5 效验，还能携带风控算法，二次效验，浏览器指纹算法等等，能保证一定的防破解性。一些看似用 GET 请求方便的接口，但实际都要考虑所包含的风险，就如上面那个发送验证码的接口，如果不加以加密，特别容易仿造出与之对应的协议请求，再次仿造发送也不难。当然，对于这种限制类的业务，还是得要后端进行限制，例如 1 分钟只能发送一条，一天一号只能发送 10 条。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="最后">最后<a class="hash-link" href="#最后" title="标题的直接链接">​</a></h2><p>其实可以发现绝大多数的网站基本上都不是采用 Restful 风格（貌似用的最多的也就是管理系统了），因为所涉及的业务逻辑实在是太复杂了，不单单只能使用请求方法来表明意思，有时候 Url 路径更能表达明确意思。</p><p>Restful 风格想的太美好了，然而实际业务中 很多时候并不能单纯的通过 get post put delete 这四种请求发送来表明真实意义，所以我在增删改查的时候才会使用 Restful api 风格。</p><p>在我写项目中遇到一些复杂业务逻辑，我是毫不犹豫使用 Post 请求的，然后通过 url 路径表明 api 所要请求的路径，同时编写 Swagger Api 文档。什么样的风格都因人而异，主要自己用的习惯就行，毕竟 api 接口只是风格，并不作为标准来衡量。</p>]]></content:encoded>
            <category>随笔</category>
            <category>api</category>
        </item>
        <item>
            <title><![CDATA[为什么我不用七牛云]]></title>
            <link>https://kuizuo.cn/why-i-dont-use-qiniu-cloud</link>
            <guid>why-i-dont-use-qiniu-cloud</guid>
            <pubDate>Wed, 23 Dec 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[七牛云是国内鲜有的免费提供对象存储服务的一个云服务商，和腾讯云，阿里云一样，但这两者收费，而七牛云不收费，当然也不是绝对免费，对象存储免费空间 10g，每个月还有 10g 的 cdn 加速服务（多数人基本用不完），超出部分额外收费，此外 https 收费。]]></description>
            <content:encoded><![CDATA[<p>七牛云是国内鲜有的免费提供对象存储服务的一个云服务商，和腾讯云，阿里云一样，但这两者收费，而七牛云不收费，当然也不是绝对免费，对象存储免费空间 10g，每个月还有 10g 的 cdn 加速服务（多数人基本用不完），超出部分额外收费，此外 https 收费。</p><p>我<strong>之前</strong>使用七牛云的主要原因，就是业内太多人推荐了，免费还带加速，存储博客图片好的不行，然而发生了如下的事情：</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="事情经过">事情经过<a class="hash-link" href="#事情经过" title="标题的直接链接">​</a></h2><p>让我不用七牛云的罪魁祸首其实是 Chrome 浏览器，先看一张图片。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20201214211848873.png" alt="image-20201214211848873" class="img_ev3q"></p><p>What？图片呢？第一时间毫不犹豫打开控制台查看问题所在，有这样几行报错</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20201214212056058.png" alt="image-20201214212056058" class="img_ev3q"></p><p>关注第一行</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token maybe-class-name">Mixed</span><span class="token plain"> </span><span class="token maybe-class-name">Content</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token maybe-class-name">The</span><span class="token plain"> page at </span><span class="token string" style="color:rgb(163, 21, 21)">'&lt;URL&gt;'</span><span class="token plain"> was loaded over </span><span class="token constant" style="color:rgb(129, 31, 63)">HTTPS</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> but requested an insecure element </span><span class="token string" style="color:rgb(163, 21, 21)">'&lt;URL&gt;'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain"> </span><span class="token property-access maybe-class-name">This</span><span class="token plain"> request was automatically upgraded to </span><span class="token constant" style="color:rgb(129, 31, 63)">HTTPS</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token maybe-class-name">For</span><span class="token plain"> more information see </span><span class="token operator" style="color:rgb(0, 0, 0)">&lt;</span><span class="token constant" style="color:rgb(129, 31, 63)">URL</span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>翻译过来就是：网页混合内容:页面是通过 HTTPS 加载，但却请求一个不安全元素 HTTP。该请求被自动升级为 HTTPS，更多信息请参见。</p><p>管他啥意思，先百度，然后才了解到，在 Chrome 浏览器高版本中（具体多少忘了），如果当前站点是 https，那么会自动将页面请求的 http 升级为 https，也就是说，我当前站点是 https 协议，访问不了 http 的资源，然而这可坑惨我了，我的图片全都放在七牛云上，然而七牛云的 HTTPS 是收费的，那时候我也抱着白嫖的心态，去嫖了七牛云的对象存储来做图床，现在我将<a href="http://kzcode.cn" target="_blank" rel="noopener noreferrer">http://kzcode.cn</a> 升级为<a href="https://kzcode.cn" target="_blank" rel="noopener noreferrer">https://kzcode.cn</a> 的时候，就意味这我不能白嫖了？也就是出现了如上画面，然后又去相关了一些百度相关的知道，看看有没有解决办法，如下</p><ul><li>使用其他浏览器</li></ul><p>这个问题只有 Chrome 浏览器内才有，在 https 站点会将 http 请求自动升级为 https，在其他浏览器不会，上面的图片也会正常显示。</p><ul><li>要么都用 HTTP，要么都用 HTTPS</li></ul><p>http 站点去请求 https 资源会不安全，而 https 站点去请求 http 会自动升级为 https，而这没有很好的有效方法去让两者兼容。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="选择">选择<a class="hash-link" href="#选择" title="标题的直接链接">​</a></h2><p>既然搜到解决办法后，我心想，这网站怎么能不上 HTTPS，怎么能让左上角的锁不安全呢。用了 HTTPS 是不可能回去的了，同时怎么能保证别人用的浏览器不是 Chrome 浏览器呢，于是毅然决然的将所有将图片升级为 HTTPS 了，然而在对比后各家的对象存储服务，我选择了腾讯云，先放一张比对图：</p><table><thead><tr><th>运营商</th><th>价格(元/GB)</th><th>活动</th></tr></thead><tbody><tr><td>阿里云</td><td>HTTP 0.24<br>HTTPS 需要额外加一点请求费</td><td>无</td></tr><tr><td>腾讯云</td><td>HTTP 和 HTTPS <strong>统一 0.21</strong></td><td>前 6 个月每个月送 20GB 国内流量</td></tr><tr><td>七牛云</td><td>HTTP <strong>0.24</strong> (超出免费 10GB)<br>HTTPS <strong>0.28</strong></td><td>每个月送 <strong>10GB HTTP 流量</strong> (国内外均可使用) 以及 5 万次动态加速请求数</td></tr></tbody></table><p>可以看到如果你每个月的请求流量都在 10GB 以内，且不用 HTTPS，七牛云肯定是最好的选择，然而我目前的站点是需要 HTTPS 的，并且七牛的 HTTPS 费用高出其他两家，甚至可以说，用了 HTTPS，就没必要选择七牛云！一没优势，速度优化不到哪里去，二是你完全可以相信大厂，三是服务费用还比两者贵。同时我云服务器也是腾讯云的，肯定优先选择腾讯，于是把对象存储换为了腾讯云，早知道就一开始就直接用腾讯的对象存储服务，果然还是花钱实在，白嫖太麻烦了。</p><blockquote><p>参考链接 <a href="https://blog.txzhou.com/website/compare-cdn.html" target="_blank" rel="noopener noreferrer">阿里云、腾讯云、七牛云 CDN 对比</a></p></blockquote><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="最后">最后<a class="hash-link" href="#最后" title="标题的直接链接">​</a></h2><p>本文的标题并不是说七牛云不好，而是我所遇到的情形让我放弃了使用七牛云，相信你看完了上面所说的，能对你的网站有个存储有个明确的配置，你在哪买服务器了，还是在哪去买其他相关的业务，没必要花费时间去折腾，说到底还是花钱实在。并且价格实际上对一个小网站来说，已经是可以非常低了（当然还是有些人会想着白嫖）</p><p>总结下来其实就是，如果你的网站不准备挂 SSL 证书，也就是通过 http 请求访问，那么白嫖七牛云，没问题，好用，但如果你的网站一旦挂了 SSL 证书，我的建议是直接删了七牛云的对象存储。</p>]]></content:encoded>
            <category>随笔</category>
            <category>cloud-service</category>
        </item>
        <item>
            <title><![CDATA[腾讯云之CDN与SSL配置]]></title>
            <link>https://kuizuo.cn/tencent-cloud-cdn-and-ssl</link>
            <guid>tencent-cloud-cdn-and-ssl</guid>
            <pubDate>Tue, 15 Dec 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[如题，本人所购买的服务器，以及对象存储，CDN，和 SSL 都是腾讯云的。]]></description>
            <content:encoded><![CDATA[<p>如题，本人所购买的服务器，以及对象存储，CDN，和 SSL 都是腾讯云的。</p><p>在这篇文章我会简单明细的讲一下我花了一个整个晚上都在腾讯云-控制台做了些什么，也助于自己到时候忘记腾讯云服务器相关操作做个笔记。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="云服务器">云服务器<a class="hash-link" href="#云服务器" title="标题的直接链接">​</a></h2><p>先看看我的云服务器配置</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20201215004521965.png" alt="image-20201215004521965" class="img_ev3q"></p><p>腾讯云那时候做活动，花了 298 块买了 3 年 1 核 2g 内存 1m 带宽，够了，这里我要提一点，如果了解过云服务器的话，可能还会看到轻量应用服务器，而且这个轻量应用服务器竟然配置和云服务器差不多，并且价格还便宜，我先放两张图看看</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20201215005635518.png" alt="image-20201215005635518" class="img_ev3q"></p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20201215005553889.png" alt="image-20201215005553889" class="img_ev3q"></p><p>可以看到云服务器可以安装 Window，Linux 系统，而轻量应用服务器则是这些的分支，就这么说的，如果我的服务端只涉及到 nodejs 相关的，那么我大可购买轻量应用服务器，然而多数都是去买云服务器，毕竟可拓展高。两者价格在不是新用户的情况下，云服务器 1g1h1m 一年 662 元，而轻量应用服务器才 408 元。没错，不是新用户服务器就是这么贵。。。</p><p>说了这么多题外话，说下云服务器有一个重要的地方就是安全组<img loading="lazy" src="https://img.kuizuo.cn/image-20201215011238478.png" alt="image-20201215011238478" class="img_ev3q"></p><p>这里在宝塔面板中，设置了放行端口，此外腾讯云安全组也要设置，不过这里我是入站和出站都设置一键放通，主要方便，也懒得设置了。</p><p>此外云服务器大致就如此，基本上宝塔安装后，就没腾讯云的云服务器面板什么事情了，有关云服务器与域名备案我在另一篇文章也写到过 <a href="/server-and-domain-beian">云服务器与域名备案</a></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="cdn">CDN<a class="hash-link" href="#cdn" title="标题的直接链接">​</a></h2><p>关于 CDN 的介绍，本人不敢多言，怕讲不好。简单来说，挂了 CDN，你的网站就能加速，然而实际原理没这么简单，就不过多叙述这些了，外面也有很多关于 CDN 的相关资料，可以自行翻阅。</p><p>首先，你需要开通 CDN，进入内容分发网络页面会有提示开启。此外到腾讯云有个优惠，新用户 6 个月每个月免费送 20g 回溯流量，此外付费的流量包中，一年也才 19 块，不说，先买了。</p><p>在腾讯云-控制台中，主要关注两个点</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20201215013943201.png" alt="image-20201215013943201" class="img_ev3q"></p><p>一个是要加速网站的域名，还有一个就是网站的 SSL 证书，这在下文会说到。</p><p>在这里可以添加一个域名，比如<code>test.kzcode.cn</code>（后文也会以这个二级域名为例）</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20201215014206851.png" alt="image-20201215014206851" class="img_ev3q"></p><p>根据相应的业务需求来填写，点击下方的确认提交即可。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20201215014459988.png" alt="image-20201215014459988" class="img_ev3q"></p><p>接着点击 DNS 解析页面，将 CNAME 的值复制到对应的 DNS 解析，如</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20201215014619557.png" alt="image-20201215014619557" class="img_ev3q"></p><p>点击保存，然后回到 CDN 页面（内容分发网络），可以看到此时的状态已变为已启动。这时候你的网站就成功加速了，而不是用那 1m 的带宽去从服务器内拉去大的一笔的静态资源。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="ssl-证书">SSL 证书<a class="hash-link" href="#ssl-证书" title="标题的直接链接">​</a></h2><p>现在你的网站能访问速度得到了提升，但是出现了下面的这样警告（原谅我实在不想用 test.kzcode.cn 来测试）</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20201215012031362.png" alt="image-20201215012031362" class="img_ev3q"></p><p>如果你不希望你的网站出现像这样的不安全警告，那么就很有必要设置 SSL 证书，请求的时候就是 https 而不是 http，好在 SSL 证书不算太难，并且上面 CDN 加速你也弄了，这里我把腾讯云的 SSL 证书简单复刻一遍。</p><p>在 SSL 证书，点击申请免费证书</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20201215012211483.png" alt="image-20201215012211483" class="img_ev3q"></p><p>点击确定，输入要绑定的域名，如<code>test.kzcode.cn</code>，和正常注册一样，默认下一步，下一步，接着稍等片刻，等待免费证书签发。SSL 证书有效期一年，一年后就需要重新部署了。然后返回到我的证书，看到成功添加了一条证书</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20201215013035429.png" alt="image-20201215013035429" class="img_ev3q"></p><p><strong>先点击下载，下载到桌面，后面会用到的</strong>，不然待会还要回来下载。然后点击右边的部署。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20210808150559353.png" alt="image-20210808150559353" class="img_ev3q"></p><p>部署类型选择内容分发网络（CDN），点击确定
随后会跳转到证书配置页面，刚刚设置的域名 test.kzcode.cn 还有申请的免费 SSL 证书 test，选择腾讯云托管证书，向下图这样提交</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20201215015319153.png" alt="image-20201215015319153" class="img_ev3q"></p><p>提示配置成功，这时候打开宝塔面板。添加一个站点</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20201215015549597.png" alt="image-20201215015549597" class="img_ev3q"></p><p>点击设置，在左侧侧边栏中的 SSL 中的选其他证书，上面叫你下载的证书下了吧，好的，打开它，其中一个文件为 Nginx，将里面的两个文件通过文本来打开（<strong>是通过文本，而不是双击直接打开</strong>），将.key 文件的内容放到密钥上，将.crt 文件的内容放到证书上，然后点击保存，顺便把右上角强制 HTTPS 勾选上</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20201215020231348.png" alt="image-20201215020231348" class="img_ev3q"></p><p>打开网页，现在你访问<a href="https://test.kzcode.cn" target="_blank" rel="noopener noreferrer">test.kzcode.cn</a>，就能得到如下结果</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20201215020429502.png" alt="image-20201215020429502" class="img_ev3q"></p><p>连接是安全的，证书有效，恭喜，站点创建成功！</p><hr><p>至此，一个二级域名 test.kzcode.cn，并带有 SSL 证书与 CDN 加速的站点便成功部署！</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="总结">总结<a class="hash-link" href="#总结" title="标题的直接链接">​</a></h2><p>整个过程写下来，其实给我的感受就是写给未来某一时刻去重新折腾腾讯云的一篇文章，从头到尾，我也只是把这些操作重新复刻一遍，然后写成这篇文章。</p><p>在折腾了一晚上的云服务器，腾讯云给我的一大特点就是好用，并且文档详细。果然这就是大厂的资本吗，爱了爱了。并且新用户所涉及的金额并不多，甚至我都没感觉到我到底有没有花钱在网站部署上（等到时候网站人流量来的，估计就要花大价钱了）。并且执行了上面的操作，我的网站确实有所提高速度，不过还没完，云服务中还有一个挺重要的一部分还没讲到，也就是对象存储，留个小坑，有时间在写。</p>]]></content:encoded>
            <category>cloud-services</category>
        </item>
        <item>
            <title><![CDATA[HTTP请求之Content-Type]]></title>
            <link>https://kuizuo.cn/content-type-of-http-request</link>
            <guid>content-type-of-http-request</guid>
            <pubDate>Sat, 12 Dec 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Content-type]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="content-type">Content-type<a class="hash-link" href="#content-type" title="标题的直接链接">​</a></h2><p>先看一条 HTTP 请求</p><div class="language-http codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-http codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">POST https://xxx.kuizuo.cn/v2/login HTTP/1.1</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">Host: xxx.kuizuo.cn</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">Connection: keep-alive</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">Content-Length: 121</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">// Content-Type: application/json;charset=UTF-8</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">Accept: application/json, text/plain, */*</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">{"username":"kuizuo","password":"a12345678"}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>上面那个请求发送到我的服务器，服务器却接收到的是这样一串值</p><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token property">"{\"username\":\"kuizuo\",\"password\":\"a12345678\"}"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">""</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>很显然，它把 json 格式解析成了 x-www-form-urlencoded。</p><p>一个很简单的登录请求，注意一个协议头<code>Content-Type</code>，它决定了你的数据发送到服务端上会是什么格式。</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">类型格式：type</span><span class="token operator" style="color:rgb(0, 0, 0)">/</span><span class="token function" style="color:rgb(0, 0, 255)">subtype</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain">parameter</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token operator" style="color:rgb(0, 0, 0)">?</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">type 主类型，任意的字符串，如text，如果是</span><span class="token operator" style="color:rgb(0, 0, 0)">*</span><span class="token plain">号代表所有；</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">subtype 子类型，任意的字符串，如html，如果是</span><span class="token operator" style="color:rgb(0, 0, 0)">*</span><span class="token plain">号代表所有；</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">parameter 可选，一些参数，如Accept请求头的q参数， </span><span class="token maybe-class-name">Content</span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token maybe-class-name">Type的charset参数。</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>常见的媒体格式类型如下：</p><ul><li><p>text/html ： HTML 格式</p></li><li><p>text/plain ：纯文本格式</p></li><li><p>text/xml ： XML 格式</p></li><li><p>image/gif ：gif 图片格式</p></li><li><p>image/jpeg ：jpg 图片格式</p></li><li><p>image/png：png 图片格式</p><p>以 application 开头的媒体格式类型：</p></li><li><p>application/xhtml+xml ：XHTML 格式</p></li><li><p>application/xml ： XML 数据格式</p></li><li><p>application/atom+xml ：Atom XML 聚合格式</p></li><li><p>application/json ： JSON 数据格式</p></li><li><p>application/pdf ：pdf 格式</p></li><li><p>application/msword ： Word 文档格式</p></li><li><p>application/octet-stream ： 二进制流数据（如常见的文件下载）</p></li><li><p>application/x-www-form-urlencoded ： form 表单数据被编码为 key/value 格式（通过=与&amp;拼接）发送到服务器（表单默认的提交数据的格式）格式如: username=kuizuo&amp;password=a12345678</p><p>另外一种常见的媒体格式是上传文件之时使用的：</p></li><li><p>multipart/form-data ： 需要在表单中进行文件上传时，就需要使用该格式</p></li></ul><p>实际上遇到最多的也就是 text/html，text/plain，application/json，application/x-www-form-urlencoded 这几个。</p><blockquote><p>参考资料 <a href="https://www.cnblogs.com/klb561/p/10090540.html" target="_blank" rel="noopener noreferrer">Http 请求中 Content-Type</a></p></blockquote><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="说说我那时候的情况">说说我那时候的情况<a class="hash-link" href="#说说我那时候的情况" title="标题的直接链接">​</a></h3><p>这是在我帮别人分析登录算法的时候，由于协议头中少添加了一个<code>Content-Type</code>，导致我发送的数据，服务端解析不了，收到了这样的响应</p><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token property">"code"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">500001</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"message"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"亲，我们的系统目前忙碌中或无法回应，请将此问题回报给我们的客服人员。 错误代碼(68523)"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"data"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token null keyword" style="color:rgb(0, 0, 255)">null</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>然而实际响应应该是这样的</p><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token property">"code"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">400020</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"message"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"密码错误"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token property">"data"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"验证码错误"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>原因就是因为协议头没有添加<code>Content-Type: application/json;charset=UTF-8</code>所导致的。因为这个，坑了我近一个小时，还一直以为是数据错误，没想到仅仅只是少加了一些协议头导致的请求数据格式错误。</p><p>一个印象很深刻的教训，模拟 HTTP 请求的时候，一定不要吝啬补全协议头，不然坑的就是自己了。我已经给坑过两次了，所以在特意想借此记录一下，免得下次又是一番折腾。写个注意，醒目一点。</p><div class="theme-admonition theme-admonition-danger alert alert--danger admonition_LlT9"><div class="admonitionHeading_tbUL"><span class="admonitionIcon_kALy"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"></path></svg></span>危险</div><div class="admonitionContent_S0QG"><p>发送的是 JSON 格式数据，切记一定要添加上协议头<code>Content-Type: application/json;charset=UTF-8</code>！！！</p></div></div>]]></content:encoded>
            <category>http</category>
        </item>
        <item>
            <title><![CDATA[node与浏览器中的cookie]]></title>
            <link>https://kuizuo.cn/cookie-of-node-and-browser</link>
            <guid>cookie-of-node-and-browser</guid>
            <pubDate>Thu, 10 Dec 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[前言]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="前言">前言<a class="hash-link" href="#前言" title="标题的直接链接">​</a></h2><p>记录一下自己在 nodejs 中使用 http 请求库 axios 中的一些坑（针对 Cookie 操作）</p><p>不敢说和别人封装的 axios 相比有多好，但绝对是你能收获到 axios 的一些知识，话不多说，开始</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="封装">封装<a class="hash-link" href="#封装" title="标题的直接链接">​</a></h2><p>一般而言，很少有裸装使用 axios 的，就我涉及的项目来说，我都会将 axios 的 request 封装成一个函数使用，接着在 api 目录下，引用该文件。项目结构一般是这样的：</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token plain"> src</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token plain"> api</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token plain"> user</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">js</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token plain"> goods</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">js</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token plain"> utils</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token operator" style="color:rgb(0, 0, 0)">|</span><span class="token operator" style="color:rgb(0, 0, 0)">--</span><span class="token plain"> request</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">js</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="requestjs">request.js<a class="hash-link" href="#requestjs" title="标题的直接链接">​</a></h4><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword module" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token imports">axios</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'axios'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">var</span><span class="token plain"> instance </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> axios</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">create</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">baseURL</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> process</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">env</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token constant" style="color:rgb(129, 31, 63)">API</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// node环境变量获取的Api地址</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">withCredentials</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 跨域携带Cookies</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">timeout</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">5000</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// 设置请求拦截器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">instance</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">interceptors</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">request</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">use</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">config</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">// 在config可以添加自定义协议头 例如token</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    config</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">headers</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'x-token'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'xxxxxxxx'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> config</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token known-class-name class-name" style="color:rgb(38, 127, 153)">Promise</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">instance</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">interceptors</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">response</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">use</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">response</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> res </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> response</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">data</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">// 根据对应的业务代码 对返回数据进行处理</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> res</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> response </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> error</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">// 状态码为4或5开头则会报错</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">// 根据根据对应的错误,反馈给前端显示</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">response</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">response</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">status</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">404</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'请求资源路径不存在'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token known-class-name class-name" style="color:rgb(38, 127, 153)">Promise</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">reject</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">response</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">else</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token comment" style="color:rgb(0, 128, 0)">// 断网......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword module" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">default</span><span class="token plain"> instance</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>实际上，上面那样的封装就够了，相对于的业务代码就不补充了，如果你的宿主环境是浏览器的话，很多东西你就没必要在折腾的，甚至下面的文章都没必要看（不过还是推荐你看看，会有帮助的）。不过没完，再看看 api 里怎么使用的</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="apiuserjs">api/user.js<a class="hash-link" href="#apiuserjs" title="标题的直接链接">​</a></h4><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword module" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token imports">request</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'@/utils/request'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword module" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">login</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">request</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">url</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'/user/login'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">method</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'post'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword module" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">info</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">request</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">url</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'/user/info'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">method</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'get'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword module" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">logout</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">request</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">url</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'/user/logout'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">method</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'post'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>看来很简单，没错，就是这么简单，由于是运行在浏览器内的，所以像 cookies，headers 等等都没必要设置，浏览器会自行携带该有的设置，其实想设置也设置不了，主要就是浏览器内置跨域问题。<a href="https://fetch.spec.whatwg.org/#concept-header-name" target="_blank" rel="noopener noreferrer">XMLHttpRequest</a></p><p>就这？感觉你写的跟别人没什么区别啊</p><p>别急，下面才是重头戏。也是我为啥标题只写 axios，而不写 vue-axios 或者 axios 封装的原因。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="踩坑-cookies-获取与设置">踩坑 Cookies 获取与设置<a class="hash-link" href="#踩坑-cookies-获取与设置" title="标题的直接链接">​</a></h2><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="浏览器">浏览器<a class="hash-link" href="#浏览器" title="标题的直接链接">​</a></h3><p>运行环境在浏览器中，axios 是无法设置与获取 cookie，获取不到 set-cookies 这个协议头的（即使服务器设置了也没用），先看代码与输出</p><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">instance</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">interceptors</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">request</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">use</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">config</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  config</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">headers</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'cookie'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'cookie=this_is_cookies;username=kuizuo;'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'config.headers'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> config</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">headers</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> config</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">instance</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">interceptors</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">response</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">use</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">response</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'response.headers'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> response</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">headers</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> res</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>控制台结果：</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20201210060704240.png" alt="image-20201210060704240" class="img_ev3q"></p><p>首先，就是圈的这个，浏览器是不许允许设置一些不安全的协议头，例如 Cookie，Orgin，Referer 等等，即便你看到控制台 config.headers 确实有刚刚设置 cookie，但我们输出的也只是 headers 对象，在 Network 中找到这个请求，也同样看不到 Cookie 设置的（这就不放图了）。</p><p>同样的，通过响应拦截器中输出的 headers 中也没有 set-cookies 这个字样。网络上很多都是说，添加这么一行代码 <code>withCredentials: true</code>，确实，但是没说到重点，都没讲述到怎么获取 cookies 的，因为在<strong>浏览器环境中 axios 压根就获取不到 set-cookies 这个协议头</strong>，实际上 axios 就没必要，因为浏览器会自行帮你获取服务器返回的 Cookies，并将其写入在 Storage 里的 Cookies 中，再下次请求的时候根据同源策略携带上对应的 Cookie。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20201210061627824.png" alt="image-20201210061627824" class="img_ev3q"></p><p>要获取也很简单，vue 中通过<code>js-cookie</code>模块即可，而在 electron 中通过<code>const { session } = require('electron').remote</code> （electron 可以设置允许跨域，好用）有关更多可以自行查看文档。</p><p>那我就是想要设置 Cookies，来跳过登录等等咋办，我的建议是别用浏览器来伪装 http 请求。跨域是浏览器内不可少的一部分，并且要允许跨域过于麻烦。有关跨域，我推一篇文章<a href="https://juejin.cn/post/6844904126246027278" target="_blank" rel="noopener noreferrer">10 种跨域解决方案（附终极大招）</a></p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="完整封装代码">完整封装代码<a class="hash-link" href="#完整封装代码" title="标题的直接链接">​</a></h4><p>::: details 查看代码</p><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword module" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token imports">axios</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'axios'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword module" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token imports"> </span><span class="token imports maybe-class-name">MessageBox</span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token imports"> </span><span class="token imports maybe-class-name">Message</span><span class="token imports"> </span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'element-ui'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword module" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token imports">store</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'@/store'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword module" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token imports"> getToken </span><span class="token imports punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'@/utils/auth'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> service </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> axios</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">create</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">baseURL</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> process</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">env</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token constant" style="color:rgb(129, 31, 63)">VUE_APP_BASE_API</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">withCredentials</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">timeout</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">5000</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">service</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">interceptors</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">request</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">use</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">config</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">store</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">getters</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">token</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      config</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">headers</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'x-token'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">getToken</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> config</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token maybe-class-name">Message</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token known-class-name class-name" style="color:rgb(38, 127, 153)">Promise</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">reject</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">service</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">interceptors</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">response</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">use</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">response</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> res </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> response</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">data</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">code</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">!==</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">200</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token maybe-class-name">Message</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">msg</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">||</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'Error'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token known-class-name class-name" style="color:rgb(38, 127, 153)">Promise</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">reject</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">Error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">msg</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">||</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'未知错误'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">else</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> res</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">response</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> res </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">response</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">switch</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">status</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword" style="color:rgb(0, 0, 255)">case</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">400</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token maybe-class-name">Message</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">msg</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">||</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'非法请求'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">break</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword" style="color:rgb(0, 0, 255)">case</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">401</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token maybe-class-name">MessageBox</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">alert</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'当前登录已过期，请重新登录'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'提示'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token literal-property property">confirmButtonText</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'重新登录'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token literal-property property">type</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'warning'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">then</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            store</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">dispatch</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'user/logout'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">then</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">              </span><span class="token dom variable" style="color:rgb(9, 134, 88)">location</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">reload</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword" style="color:rgb(0, 0, 255)">case</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">403</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token maybe-class-name">Message</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">msg</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">||</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'非法请求'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          router</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">push</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'/401'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword" style="color:rgb(0, 0, 255)">case</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">404</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token maybe-class-name">Message</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">msg</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">||</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'请求资源不存在'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">break</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword" style="color:rgb(0, 0, 255)">case</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">500</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token maybe-class-name">Message</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">msg</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">||</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'服务器开小差啦'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">break</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword module" style="color:rgb(0, 0, 255)">default</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token maybe-class-name">Message</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">msg</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">||</span><span class="token plain"> res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">statusText</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">else</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token maybe-class-name">Message</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">msg</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">||</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'请检查网络连接状态'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> </span><span class="token known-class-name class-name" style="color:rgb(38, 127, 153)">Promise</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">reject</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword module" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">default</span><span class="token plain"> service</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>:::</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="nodejs">Nodejs<a class="hash-link" href="#nodejs" title="标题的直接链接">​</a></h3><p>作为 nodejs 的主流 http 框架怎么能只用在浏览器上，nodejs 自然而然可以，不过 nodejs 需要配置的可就多了，在 nodejs 环境中，自然没有浏览器的同源策略，像上面设置不了的 Cookie，现在随便设置，先看看我是怎么封装的：</p><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword module" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token imports">axios</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'axios'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword module" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token imports operator" style="color:rgb(0, 0, 0)">*</span><span class="token imports"> </span><span class="token imports keyword module" style="color:rgb(0, 0, 255)">as</span><span class="token imports"> http</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'http'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword module" style="color:rgb(0, 0, 255)">import</span><span class="token plain"> </span><span class="token imports operator" style="color:rgb(0, 0, 0)">*</span><span class="token imports"> </span><span class="token imports keyword module" style="color:rgb(0, 0, 255)">as</span><span class="token imports"> https</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(0, 0, 255)">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'https'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword module" style="color:rgb(0, 0, 255)">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">async</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">request</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">opt</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> url</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> method </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'get'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> headers </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> cookies</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> data </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword null nil" style="color:rgb(0, 0, 255)">null</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> opt</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  headers</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'User-Agent'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  headers</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'Referer'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> url</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">typeof</span><span class="token plain"> cookies </span><span class="token operator" style="color:rgb(0, 0, 0)">===</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'object'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    headers</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'Cookie'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token known-class-name class-name" style="color:rgb(38, 127, 153)">Object</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">keys</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">cookies</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">map</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">k</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">encodeURIComponent</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">k</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'='</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">encodeURIComponent</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">cookies</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">k</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">join</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'; '</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">else</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">typeof</span><span class="token plain"> cookies </span><span class="token operator" style="color:rgb(0, 0, 0)">===</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'string'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    headers</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'Cookie'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> cookies</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> options </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">url</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> url</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">method</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> method</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">headers</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> headers</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">data</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> queryString</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">stringify</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">httpAgent</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">http</span><span class="token class-name punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token class-name" style="color:rgb(38, 127, 153)">Agent</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">keepAlive</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">httpsAgent</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">https</span><span class="token class-name punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token class-name" style="color:rgb(38, 127, 153)">Agent</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">keepAlive</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">rejectUnauthorized</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">timeout</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">5000</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">try</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> res </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">axios</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">request</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">options</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> res</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">e</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">e</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> e</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">message</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)">// test.js</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">const</span><span class="token plain"> request </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">require</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'./request'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">test</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> url </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'https://passport2.chaoxing.com/fanyalogin'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> data </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">fid</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'-1'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">uname</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'15212345678'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">password</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'a12345678'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">refer</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'http%253A%252F%252Fi.mooc.chaoxing.com'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">t</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'true'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> headers </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> cookies </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'username=kuizuo;uid=123;'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> res </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">await</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">request</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">url</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> url</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    headers</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    cookies</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'test -&gt; res.headers'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">headers</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token function" style="color:rgb(0, 0, 255)">test</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>测试一下，顺便抓一下包，看看请求包</p><div class="language-http codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-http codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">GET /fanyalogin HTTP/1.1</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">Accept: application/json, text/plain, */*</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">Referer: https://passport2.chaoxing.com/fanyalogin</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">Cookie: username=kuizuo;uid=123;</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">Host: passport2.chaoxing.com</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">Connection: keep-alive</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">Content-Length: 100</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">....</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>有我们自定义的 Cookie，在看看响应的协议头</p><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">test </span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token plain"> res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">headers</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">server</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'Tengine'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">date</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'Thu, 10 Dec 2020 00:24:15 GMT'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token string-property property">'content-type'</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'text/html'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token string-property property">'content-length'</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'1852'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">connection</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'keep-alive'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">vary</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'Accept-Encoding'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token string-property property">'set-cookie'</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token string" style="color:rgb(163, 21, 21)">'JSESSIONID=4365A6B9FD8E0CBADDBDD7E7DA468F7E; Path=/; HttpOnly'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token string" style="color:rgb(163, 21, 21)">'route=b2eda164bddd148142a54809ef404926;Path=/'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token string-property property">'accept-ranges'</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'bytes'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">etag</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'W/"1852-1606444212000"'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>同样能获取到 set-cookie，设置与获取都是这么 so easy ，不同于上面浏览器的配置。</p><p>这里我要说明一些东西，在封装代码中有个 httpAgent 与 httpsAgent，你可以字面翻译就是 http 代理，设置它用来干嘛呢，其中有这么个属性 <code>keepAlive: true</code> ，如果设置了协议头中的将会有 <code>Connection: keep-alive</code>，而不设置则 <code>Connection: close</code>，这里也不想过多说明 http 相关知识，如果只是请求一次,那么两者没有太大区别</p><p>然而如果我请求一次,过一会(几秒内)又要请求了,那么 keep-alive 一次连接就可以处理多个请求，而 close 则是一次请求后就断开，下次就需要再次连接。说白了就是快一点，而 close 需要不断连接，断开，自然而然就慢。一般来说设置 keep-alive 就对了。</p><p>其中在 httpsAgent 中，还有一个属性<code>rejectUnauthorized: false</code>，说简单点，就是不抛出验证错误，在抓 nodejs 包的时候，如果不通过设置代理服务器（Fiddler，Charles），而是通过网卡（HTTP Analyzer，Wireshark）就会抛出异常，一般就会出现这种错误。</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token known-class-name class-name" style="color:rgb(38, 127, 153)">Error</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> unable to verify the first certificate</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>然而问题就来了，服务端的返回的 set-cookie 该怎么保存。如果只是涉及客户端层面的，想写一个模拟 http 请求的，直接将获取到的 cookies 与原有的 cookie 合并即可。我那时候的代码就是这样：</p><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> newCookie </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">header</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'set-cookie'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">?</span><span class="token plain"> res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">header</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">'set-cookie'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">map</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">a</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> a</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">split</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">';'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">join</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'; '</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">''</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// mergeCookie 就是将两者cookie 拼接而成</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> newCookies </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">mergeCookie</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">cookies</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> newCookie</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">cookie</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> newCookies</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"> res</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>然后返回响应中携带 res.cookies 即可，下次请求的时候再将其在带上。</p><p>如果只是，利用 nodejs 来实现类似爬虫，模拟登录，然后利用登录后的 cookie，来获取用户信息。如果不希望手动处理 cookies 的话，我其实还是推荐一个 http 模块，superagent，做一些小爬虫和模拟请求挺好用的，就不做过多介绍了。不过由于 nestjs 中自带 axios 模块，加上需要转发 http 请求，于是我就自行封装了一个 axios。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="总结">总结<a class="hash-link" href="#总结" title="标题的直接链接">​</a></h2><p>实际上，axios 会根据当前环境，来创建 xhr 对象（浏览器）还是 http 对象（nodejs），在我那时候都以为 axios 是两个共用的，初学 electron 的时候，一直卡在 http 请求的配置</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token comment" style="color:rgb(0, 128, 0)">// `adapter` allows custom handling of requests which makes testing easier.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token comment" style="color:rgb(0, 128, 0)">// Return a promise and supply a valid response (see lib/adapters/README.md).</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function-variable function" style="color:rgb(0, 0, 255)">adapter</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">config</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">/* ... */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>在 axios 中也有这么一段配置，翻看了 lib/adapters 下目录我才瞬间醒悟过来，两者环境是不同的。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20201210214055696.png" alt="image-20201210214055696" class="img_ev3q"></p><p>就我使用而言，在浏览器环境下 axios 处理的特别好，允许设置拦截器处理请求与响应，但在 nodejs 下在处理模拟请求确实不如 Python 的 request 模块，奈何 axios 最大的便携就是能直接在浏览器中，尤大推荐的 http 请求库也是 axios。</p><p>实际上还涉及到了 nodejs 中转发请求的，再给自己留一个坑。</p><p>在写这篇文章的时候，我其实都没读过 axios 的源码，说实话，那时候遇到问题，就不应该愚昧的去搜索，去不断尝试，有时候直接通过翻看底层代码，可以一目了然自己所面临问题的解决方式。</p>]]></content:encoded>
            <category>node</category>
            <category>axios</category>
            <category>cookie</category>
        </item>
        <item>
            <title><![CDATA[服务器与域名备案]]></title>
            <link>https://kuizuo.cn/server-and-domain-beian</link>
            <guid>server-and-domain-beian</guid>
            <pubDate>Tue, 17 Nov 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[云服务器]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="云服务器">云服务器<a class="hash-link" href="#云服务器" title="标题的直接链接">​</a></h2><p>服务器说白就是全天 24 小时不停歇的运行一台电脑，同时分配一个公网 IP 给这个电脑，你只需要把你要的资源放置到这台电脑上，别人通过访问该 IP 就能访问到这台电脑的资源，比如你放一个网页部署在这台服务器上，别人访问 这个IP就能访问到网页的内容。</p><p>你可以根据需求来安装服务器的系统，这些在云服务厂商中都是可以选择的。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="服务器的配置">服务器的配置<a class="hash-link" href="#服务器的配置" title="标题的直接链接">​</a></h3><p>一般来说，一些提供云服务器的厂商都会给新用户一个新用户价，差不多也就是 100 左右一年的云服务器,配置一般都是 2g 内存,1 核,1m 带宽,50g 硬盘说实话对于没有特殊需求的服务器够用了。而不是新用户的价格，这样的配置一个月差不多 70 元，算一下一年打折后 700 元，这还算便宜的了，服务器贵这很正常，全天不间断运行，电费，网费和一些服务费用，其实就已经非常值了。</p><p>其他几个配置没什么可说的，如果要说服务器哪个配置最贵的话，无疑就是带宽了。1M 的带宽理论上传速度为 128kB/s，也就是我从服务器中下载一个 10m 的软件，需要 80 秒，这还只是理论速度，我实测过平均速度不到 100kB/s。如果搭建网站的话 1m 有些慢，虽说一个页面一般都不会超过 100kb，但背后加载的图片 css js资源可就不只是kb大小了，用户访问网页就需要花费一定时间等待加载，体验非常不好。个人建议带宽5m起步，否则就不建议购买。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="云服务器和轻量应用服务">云服务器和轻量应用服务<a class="hash-link" href="#云服务器和轻量应用服务" title="标题的直接链接">​</a></h3><p>关于服务器的选择很多人不知道云服务器和轻量应用服务的区别，这里两种服务器我都买过，且目前都在役。主要区别和优势请参考下表（腾讯云文档）</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_CO_V_ghsyo.png" class="img_ev3q"></p><p>更具体的可以查看对应云服务商的介绍</p><p><a href="https://developer.aliyun.com/article/1023850?spm=5176.21213303.J_6704733920.7.432353c9DbykNf%5C&amp;scm=20140722.S_community@@%E6%96%87%E7%AB%A0@@1023850._.ID_community@@%E6%96%87%E7%AB%A0@@1023850-RL_%E9%98%BF%E9%87%8C%E4%BA%91ecs%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%92%8C%E8%BD%BB%E9%87%8F%E5%BA%94%E7%94%A8%E6%9C%8D%E5%8A%A1%E6%9C%89%E4%BB%80%E4%B9%88%E5%8C%BA%E5%88%AB%E5%8F%8A%E9%80%89%E6%8B%A9%E6%96%B9%E6%B3%95-LOC_main-OR_ser-V_2-P0_0" target="_blank" rel="noopener noreferrer" title="阿里云ECS云服务器和轻量应用服务有什么区别及选择方法-阿里云开发者社区 (aliyun.com)">阿里云ECS云服务器和轻量应用服务有什么区别及选择方法-阿里云开发者社区 (aliyun.com)</a></p><p><a href="https://cloud.tencent.com/document/product/1207/49819" target="_blank" rel="noopener noreferrer" title="轻量应用服务器 与云服务器 CVM 对比-产品简介-文档中心-腾讯云 (tencent.com)">轻量应用服务器 与云服务器 CVM 对比-产品简介-文档中心-腾讯云 (tencent.com)</a></p><p><strong>总结：买轻量应用服务器是最实惠的</strong></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="github学生认证送服务器">github学生认证送服务器<a class="hash-link" href="#github学生认证送服务器" title="标题的直接链接">​</a></h3><p>如果你不想花钱买一个服务器的话，可以考试github学生认证，会送你一个服务器。具体可到官方中查看 <a href="https://education.github.com/experiences/virtual_event_kit" target="_blank" rel="noopener noreferrer" title="https://education.github.com/experiences/virtual_event_kit">https://education.github.com/experiences/virtual<!-- -->_<!-- -->event<!-- -->_<!-- -->kit</a></p><p><img loading="lazy" src="https://img.kuizuo.cn/image_Rsh8Y_TBfe.png" class="img_ev3q"></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="windows-和-linus-服务器的区别">windows 和 Linus 服务器的区别<a class="hash-link" href="#windows-和-linus-服务器的区别" title="标题的直接链接">​</a></h3><p>这里可能会说的不对，毕竟我接触服务器相关等配置也没太多时间，但是我觉得有必要说一下，我那时候用 windows 服务器的时候，只要通过 windows<strong>专业版</strong>（一定要专业版才能远程连接别人的电脑）自带的远程桌面（cmd 中输入<code>mstsc</code>即可），然后输入 ip 地址，接着在输入相应的账号密码即可，但有可能无法连接，原因是防火墙和 ip 白名单没有配置好，服务器不允许连接。</p><p>而对于 Linux，用的最多的就是宝塔面板了，但是连接不是通过 windows 远程桌面，而是通过像终端那样连接登录，我一般是用 Xshell 来连接。但是连接完就开始输入命令安装宝塔面板，然后会有对应的面板地址和登录宝塔面板的账号密码，只要访问给定的面板地址加上用户密码即可登录。像对应的界面如下</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20200918141519472.png" alt="image-20200918141519472" title="image-20200918141519472" class="img_ev3q"></p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="选择哪家云服务器厂商">选择哪家云服务器厂商<a class="hash-link" href="#选择哪家云服务器厂商" title="标题的直接链接">​</a></h2><p>目前市场上主要有阿里云和腾讯云的服务器，这两者的服务器质量和操作体验上都属于大厂级别。不分上下，都可以选择购买，不过最好有个原则，你域名在哪购买，服务器就买哪一家的，因为到时候备案是需要服务器才能备案的。</p><h1>域名</h1><p>正常来说你访问你一个网站肯定不是访问一个ip地址，而是一个域名，比方说访问kuizuo.cn，baidu.com。但其实访问域名就相当于访问这个ip，过程如下：首先访问域名会经过DNS解析，DNS（域名系统）会找到你要访问的域名所解析的ip，然后访问这个ip。</p><p>但有遗憾的地方就是很多时候想要注册自己想要的域名非常难，因为已经被别人现行注册了。比如我的现在的kuizuo.cn这个域名是从他人手里购买而来的。所以域名这东西请优先准备好，备案解析啥的完全不急，一年也就是几十块钱，但是你不先买就很有可能给别人先注册，到时候想买都没得买，要不然就要花大价格购买，因此也有很多人去做域名买卖的生意。</p><p>一般一个域名够用了，需要的话在域名解析中去添加域名的子域名（二级，三级等等），比如我的一些个人项目就是使用二级域名来访问的，这里我也就不在列举了。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="为啥要备案">为啥要备案<a class="hash-link" href="#为啥要备案" title="标题的直接链接">​</a></h3><p>首先备案要提交负责人的身份信息（身份证正反，手持，人脸，手机号，住址等），记录你这个域名内的网站的负责人和单位，主要为了防止在网上从事非法的网站经营活动，打击不良互联网信息的传播，能给予警告和封禁。（网站备案只针对国内服务器）</p><p>总之不要去搞违规违法行为，天网恢恢疏而不漏，网警要找总归有方法。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="icp-备案">ICP 备案<a class="hash-link" href="#icp-备案" title="标题的直接链接">​</a></h3><p>9 月 3 号购买的腾讯云与域名，然后进行初步的服务器简单部署配置，第二天开始域名实名认证，接着实名后需要 3 天时间才可以进行开始域名备案，等了 3 天开始域名备案提交网站的用途信息等等，然后拍身份证，人脸，手持，接着到 9 月 9 日腾讯云服务器的客服打电话给我要我修改一些信息，比如网站详情写的不行，资料不全，过不了备案等等，然后修改重新提交一次，最终等待收到腾讯云助手的通知，直到 9 月 18 号，如下结果</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20200918113449612.png" alt="image-20200918113449612" title="image-20200918113449612" class="img_ev3q"></p><p>至此 ICP 备案就搞定了，ICP 还算轻松，身份信息真实，来访电话及时接听，等就行了。</p><p>只要ICP 备案，就可以通过域名 <a href="https://kuizuo.cn" target="_blank" rel="noopener noreferrer" title="kuizuo.cn">kuizuo.cn</a> 访问到我的个人博客。(当然前提需要到域名管理中的DNS解析添加)</p><p><img loading="lazy" src="https://img.kuizuo.cn/image_nuVA2RTh_b.png" class="img_ev3q"></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="公安备案">公安备案<a class="hash-link" href="#公安备案" title="标题的直接链接">​</a></h3><p>但还有一个公安备案，虽说不是强制的，但一般都是建议去公安备案一下。我之前的域名kzcode.cn就有公安备案，但现在的kuizuo.cn 并没有。主要原因还是太过于繁琐，比ICP备案复杂多了。</p><p>首先需要登录 <a href="http://www.beian.gov.cn" target="_blank" rel="noopener noreferrer" title="http://www.beian.gov.cn">http://www.beian.gov.cn</a> 注册并且登录填写的信息也比上面的多，如下图</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20201119191204222.png" alt="image-20201119191204222" title="image-20201119191204222" class="img_ev3q"></p><p>填写资料折腾了半小时左右的时间，才提交上去，而且过了快两周后，我收到了如下的短信</p><blockquote><p>【公安网站服务平台】尊敬的用户:您开办的网站(互联网技术文章分享:kzcode.cn)审核未通过，原因：网站信息检查有误，审核不通过，请尽快登录www<!-- -->.<!-- -->beian.gov.cn网站，在草稿中修改并重新提交网站备案申请，如有疑问可在工作日（上午8:30-11:30、下午14:00-17:00）联系网警，联系电话：059xxxxxxxx，谢谢您的配合。</p></blockquote><p>工作人员电话和我联系是说我户籍转了，需要在我转入地去申请，于是又重新提交改数据，反正就是照着腾讯云的帮助文档填写自己的个人信息，中途有几次就这么磨着磨着到了 11 月 17 号，短信收到了这一条</p><blockquote><p>【公安网站服务平台】尊敬的用户:您的开办主体已经审核通过，如果存在自动关联的待备案或待认领网站，请尽快核对归属，进行新网站备案以及已备案网站认领的申请。如有疑问可在工作时间（周一至周五上午 9:00-12:00、下午 14:00-17:00）联系网警，联系电话：059xxxxxxxx，谢谢您的配合。</p></blockquote><p>然而，我登录了网站却没有看到已备案的网站，于是联系工作人员 ，然后叫我重新提交一次，这次不到半小时就搞定，最终短信结果如下</p><blockquote><p>【公安网站服务平台】尊敬的用户:您开办的网站(互联网技术文章分享:kzcode.cn)已经审核通过，请尽快登录www<!-- -->.<!-- -->beian.gov.cn网站,下载备案号码，附在网站底部，如有疑问可在工作日（上午9:00-12:00、下午14:00-17:00）联系网警，联系电话：059xxxxxxxx，谢谢您的配合。</p></blockquote><p>然后登录公安备案网站，查看备案结果如下图，帅的不谈！</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20201117152619474.png" alt="image-20201117152619474" title="image-20201117152619474" class="img_ev3q"></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="悬挂备案号">悬挂备案号<a class="hash-link" href="#悬挂备案号" title="标题的直接链接">​</a></h3><p>如果上面都已经弄好了也别太高兴，要在网页源代码将公安联网备案信息放置在网页底部。简单的说完成两项备案后都需要在网站页面底部显示备案号，并指明转到链接。在我的个人博客页面最下方，就会看到如下图这样。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20201117153209037.png" alt="image-20201117153209037" title="image-20201117153209037" class="img_ev3q"></p><p><a href="http://www.gov.cn/gongbao/content/2005/content_93018.htm" target="_blank" rel="noopener noreferrer" title="工信部原文">工信部原文</a> 第十三条和第二十五条</p><blockquote><p><strong>第十三条</strong> 非经营性互联网信息服务提供者应当在其网站开通时在主页底部的中央位置标明其备案编号，并在备案编号下方按要求链接信息产业部备案管理系统网址，供公众查询核对。</p></blockquote><blockquote><p><strong>第二十五条</strong> 违反本办法第十三条的规定，未在其备案编号下方链接信息产业部备案管理系统网址的，或未将备案电子验证标识放置在其网站指定目录下的，由住所所在地省通信管理局责令改正，并处5千元以上1万元以下罚款。</p></blockquote><p>当然也有很多网站并没有这么做，具体还是需要看网站的性质，是否经营性网站。像个人博客这种，只需要悬挂一个ICP备案号即可，但对于绝大多数的国内网站是肯定悬挂公安备案，并且除了备案信息外，还有一堆相关证件，如营业执照，许可证，资格证等等，国内的网站监管非常严格的。</p>]]></content:encoded>
            <category>server</category>
            <category>cloud</category>
        </item>
        <item>
            <title><![CDATA[易语言]]></title>
            <link>https://kuizuo.cn/easy-language</link>
            <guid>easy-language</guid>
            <pubDate>Thu, 08 Oct 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[好歹自己学习易语言也快有一年了，也用易语言写了一些软件，特此记录一下以及对易语言的个人看法。]]></description>
            <content:encoded><![CDATA[<p>好歹自己学习易语言也快有一年了，也用易语言写了一些软件，特此记录一下以及对易语言的个人看法。</p><p>该文章有可能过于啰嗦，可吐槽的点太多了，也正有感悟才能写的这么多。</p><p>补: 2021 年 3 月，也就是我最后一次编写易语言项目，因为我已经好久不写 exe 项目了。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="易语言介绍">易语言介绍<a class="hash-link" href="#易语言介绍" title="标题的直接链接">​</a></h2><p>还是简单介绍一些易语言吧，毕竟肯定有很多即使学过编程也没听过易语言的，易语言是一门以<strong>中文</strong>作为程序代码编程语言，简称 E 语言，创始人吴涛，2000 年一个人独立开发。有关易语言的特点如下：</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="易语言不开源">易语言不开源<a class="hash-link" href="#易语言不开源" title="标题的直接链接">​</a></h3><p>不像主流的编程语言 C，Java，Python 等是开源的，易语言是一款纯正的商业编程软件，易语言正版加密狗 618 元，不过有破解版，不然多数人都不会去接触易语言了。但不开源就已经注定了易语言的在整个生态就不行，并且易语言已不在维护了，也就是很久很久没更新过，或者说不会再更新了，作者也已不再管易语言了，目前也就一些易友去开发一些相关的插件模块库这些。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="全中文界面可视化-ui填表式的声明">全中文界面，可视化 UI，填表式的声明<a class="hash-link" href="#全中文界面可视化-ui填表式的声明" title="标题的直接链接">​</a></h3><p>我这里放几张图展示一下</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20200914010759872.png" alt="image-20200914010759872" class="img_ev3q"></p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20200914011112087.png" alt="image-20200914011112087" class="img_ev3q"></p><p>首先要吐槽一下，2000 年的页面与 2020 年的页面可以说是完全一模一样的。开发界面是真的丑，但有一点是，页面的语言命令都是全中文的，比如<code>if</code>所对应的的就是<code>如果</code>，<code>MessageBox</code>所对的就是<code>信息框</code>，很多命令都中文化就再举例了，并且每个函数都是以表格似的填写，也就是代码的格式都定死死的了，如果你学过其他的编程语言在来和易语言比对，你多半会学的够呛，很难理解为啥要这样。不过也正是填表式声明，导致易语言过于简单，后文也会提及。</p><p>在比对一些 C#的开发界面</p><p><img loading="lazy" src="https://img.kuizuo.cn/20200924135324.png" alt="image-20200924125428023" class="img_ev3q"></p><p><img loading="lazy" src="https://img.kuizuo.cn/20200924135325.png" alt="image-20200924125907216" class="img_ev3q"></p><p>可以看到页面肯定比易语言好看 100 倍，但是随之而来的就是难度的提升，先不说好写与不好写，你让一个没学过编程的看，多半看的云里雾里，这时候就会劝退很多人瞬间不想学了，相信很多学编程的都有这样的经历。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="上手容易可以做到极速开发">上手容易，可以做到极速开发<a class="hash-link" href="#上手容易可以做到极速开发" title="标题的直接链接">​</a></h4><p>接着再来说一下上手学习，正是由于有上面那个前提，易语言可以做到上手特别快，可以说会用电脑，有逻辑，会识中文，易语言好学的一批，基本上学个几天自行写个软件完全没问题。对于国人一点编程基础都没有的新手，并且英语还不好的话来说，易语言可能是真的好上手，我当初学易就有一部分就是给英文劝退了。</p><p>首先我要提的是可视化界面设计，你只需要将旁边的组件拖拽至窗口页面上即可，相对于的属性，例如内容，宽高，颜色在旁边显而易见，要修改只需要点击修改对应的数值即可，而对于其他的 IDE 来说，如果英文不咋好，并且还是第一次用，找可能都要找几分钟。而正是这个可视化界面，让我当初有信心学下去易语言，如果你学过 C 或者其他编程语言，一开始都是在那黑不溜秋的控制台显示，我就只是想写个软件用用，你给我讲那么多理论知识，甚至我还听不懂的那种有个嘚用。</p><p>同时还可以直接打包成 exe 文件，直接在 windows 上运行，发给别人也能运行，哇，瞬间感觉到写软件的牛逼之处了，直接小有成就一波。这里我放几张我当初学易语言写的一些界面吧：</p><p>例如写一个骗骗小学生的 2020 年最新刷 Q 币软件（用到了浏览器的填表功能改了 q 币的值）</p><p><img loading="lazy" src="https://img.kuizuo.cn/20200924135326.gif" alt="demo" class="img_ev3q"></p><p>在比如做一个音乐播放器（是有声音的，只是我录制的是 gif）</p><p><img loading="lazy" src="https://img.kuizuo.cn/20200927031909.gif" alt="demo1" class="img_ev3q"></p><p>在比如一些自动添加好友的</p><p><img loading="lazy" src="https://img.kuizuo.cn/20200927031910.png" alt="image-20200924191526221" class="img_ev3q"></p><p>在比如写一个注册机模板</p><p><img loading="lazy" src="https://img.kuizuo.cn/20200927031911.png" alt="image-20200924192403210" class="img_ev3q"></p><p>网络验证</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20210819233054879.png" alt="image-20210819233054879" class="img_ev3q"></p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20210819232928124.png" alt="image-20210819232928124" class="img_ev3q"></p><p>还有特别特别多的例子我就不举例了，这些用其他的编程语言肯定能写，但是与之对应的就是学习成本，很多人学其他编程语言，甚至还没学到界面设计就开始放弃了，原因很简单，没兴趣学呗，易语言界面好设计，但是基本都是原生 windows 组件，对于新手来说这完全足够设计出自己的软件了。</p><p><strong>要是没能在最想学习的时候，满足自我的成就感，那很有可能就会学不下去</strong>。</p><p>我当初学易语言也是这样的，暑假学了两个月，其中第一个月学基础到还没什么，也就开始学习易语言的基本语法和编写一些程序来玩玩，但这些说实话没什么可看的，或者说没什么可用的，就想上面那个骗骗小学生的刷 q 币软件有用吗，没用呗。初学的一个月就都开始写这些可以说毫无软用的东西，直到我照着视频一个字一个字的模仿着敲一遍扫雷一键秒杀的代码，没错，就是这个激起了我对编程，让我感受到编程的魅力。放上一张 gif 图片。</p><p><img loading="lazy" src="https://img.kuizuo.cn/20200927031912.gif" alt="demo2" class="img_ev3q"></p><p>当初照着视频一步一步来最终完成了该软件，但那时候的我其实根本不知道为什么可以这样，直到后续了解到汇编与游戏内存相关的知识，我才算真正懂的当初扫雷外挂的原理。</p><p>也正是因这个扫雷的外挂，让我接下来的几个天疯狂的学习，去写其他的游戏外挂，比如连连看的一键秒杀，消消乐，植物大战僵尸等等。这里我也放一张图吧（还特意去下载 qq 游戏）</p><p><img loading="lazy" src="https://img.kuizuo.cn/20200927031913.gif" alt="demo3" class="img_ev3q"></p><p>不过后面就没怎么学习游戏外挂相关的，一是所看的教程是 11 年的，中途没更新了，二是目前热门游戏以我目前能力写不出来，只要加上了检测，就过不了，并且容易封号（注：我 QQ 可不是开外挂给搞封了，就算开外挂最多也只是封游戏账号），最近接触的也就是 CF 越南服的外挂，有教程于是就学了点皮毛，不过教程又教到一半，就没深入去学习。这里提醒一句，写游戏外挂并销售是可是会给抓的。</p><p>不过有点扯远了，就凭这一手界面设计，易语言其实就足以容易上手写出个软件出来。在叙述几点易语言容易上手的地方，自带提示，全中文文档，比如下图</p><p><img loading="lazy" src="https://img.kuizuo.cn/20200927031914.png" alt="image-20200924220413124" class="img_ev3q"></p><p>只要你鼠标选到对应的函数上，按下 F1 或者点击提示，就有对应的函数提示，对应其他语言也有，但是纯英文的，门槛就高一个档次。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="精易模块">精易模块<a class="hash-link" href="#精易模块" title="标题的直接链接">​</a></h4><p>如果没有这个模块也就易语言跟其他语言的区别可能就是一个是中文一个是英文了。我就举我用的最多的一个命令<code>文本_取出中间文本</code></p><p><img loading="lazy" src="https://img.kuizuo.cn/20200927031915.png" alt="image-20200924220908502" class="img_ev3q"></p><p>而对于其他的编程语言，这类语言还需要自行编写一个函数来调用，而精易模块则是直接封装好好的供你使用。你都没必要去了解底层的函数，直接把门槛降了一个大档次。</p><p>至于相关的程序编写我也不多概述，下面就是易语言的缺点。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="易语言的缺点">易语言的缺点<a class="hash-link" href="#易语言的缺点" title="标题的直接链接">​</a></h3><p>我说说我用易语言的缺点，也是我最不推荐别人学易语言的了</p><p>我上面也说到过 2000 年的页面与 2020 年的页面可以说是完全一模一样的。虽然有易友开发了仿 VS 界面的，但启动起来影响运行速度，我就没安装了。虽说我不是强迫症，但用多了 vscode 与其他的 IDE 相比，看到易语言就能想到是几年前的软件了。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="占用空间与运行">占用空间与运行<a class="hash-link" href="#占用空间与运行" title="标题的直接链接">​</a></h4><p>易语言毕竟还是一种封装过的语言，带来的方便，同时也牺牲了性能空间，与原生的桌面级开发相比易语言是无法比的。就比如用 C#开发的所占用空间肯定比易语言少，相关的性能优化更好，这里我就不放图了。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="软件报毒即使没毒也会给杀毒软件报">软件报毒，即使没毒也会给杀毒软件报<a class="hash-link" href="#软件报毒即使没毒也会给杀毒软件报" title="标题的直接链接">​</a></h4><p>这里我有必要说说关于易语言的一段故事，这里我放几个链接，可以去了解一番 <a href="https://www.bilibili.com/video/BV1WE411E7mQ/?spm_id_from=333.788.videocard.0" target="_blank" rel="noopener noreferrer">刷枪改图强登游戏 CF 外挂</a></p><p><a href="https://www.zhihu.com/question/20690643?sort=created" target="_blank" rel="noopener noreferrer">为什么多数外挂都用易语言？</a></p><p>如果你在 2010 年左右接触过网络游戏，你肯定遇到过各种各样的外挂，而这类外挂多数都是出自易语言之手，甚至你现在在外面遇到的很多游戏脚本外挂，易语言也能占据多数。你随便百度一些易语言，相关的评论都是有关外挂这些。但事实上你只会易语言是根本不够写外挂的，我学过相关外挂制作，虽然学的浅，但至少学过。是需要汇编这类基础，但又为什么会很多外挂是用易语言写,，而且都是些水平不是特别高的人，原因很简单，因为那些写挂的很多都不会真正写挂，只是调用别人封装好了的库，甚至就连易语言自身都带了外挂库这些。让他们写一款新游戏的外挂，他们多半是写不出来了，原因就是他们不懂汇编这些，但是调用写好的库就 6 的飞起。当然这其中还是有些利益相关的方面，我也不多提了。</p><p>如我上面所的我一个初中同学，要不是我接触了编写外挂这些，我还真信了他当初能写的，实际上都是修改外面的源码，或者是直接调用写好的库，直接偷源码用。</p><p>因为外挂行业的崛起，导致一些厂商不得不进行一定的处理。总之，目前易语言写过的项目，多数是会报毒的，即便没毒，也已经给杀毒软件的厂商给拉入黑名单了，所以可以说没公司要易语言的程序员，即使软件没毒，但是还是报毒，你是信杀毒软件还是易语言？</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="说说我用到的一些坑">说说我用到的一些坑<a class="hash-link" href="#说说我用到的一些坑" title="标题的直接链接">​</a></h4><p>我在做一些网页数据获取的时候，竟然连个 DOM 对象都没有提供，当时没接触前端，不知道有 DOM 对象，还是用正则去匹配，那时候是真的 nc。接触了前端，发现易语言竟然没提供 DOM 对象操作，我还是用别人封装的 DOM 类，并且还有可能出现匹配不到情况。</p><p>其次是调试的时候，对于变量值长度过长竟然无法直接查看，还需要保存为文本才能查看，并且我调试的时候常常崩溃，导致我每次找一个 bug 的时候都需要重启易语言好几遍才行。</p><p>由于是类似表格式的填写变量，参数与类型，也就导致了无法在其他编辑器上进行编写易语言代码比如我复制一个函数，给我的结果是</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">版本</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">2</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">子程序</span><span class="token plain"> 子程序</span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> 整数型</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">参数</span><span class="token plain"> 参数</span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> 文本型</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">局部变量</span><span class="token plain"> 变量</span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> 整数型</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">变量</span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token plain"> ＝ </span><span class="token function" style="color:rgb(0, 0, 255)">到整数</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">参数</span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token function" style="color:rgb(0, 0, 255)">返回</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">变量</span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>而在易语言所对的是</p><p><img loading="lazy" src="https://img.kuizuo.cn/20200927031916.png" alt="image-20200924222319462" class="img_ev3q"></p><p>在易语言中的引号<code>""</code>，只能通过常量<code>#引号</code>，或者通过常量表，就比如下面这个 jsoin 字符串 <code>{"a"="123","b"="321"}</code>，而易语言的写法就是，<code>"{”+#引号+“a”+#引号+“=”+#引号+“123”+#引号+“,”+#引号+“b”+#引号+“=”+#引号+“321”+#引号+“}"</code>，一个个通过字符串来拼接，巨麻烦，也是我最想吐槽易语言的，不过也可以通过常量表来替换，但依旧很麻烦。</p><p>还有易语言自身是不支持 utf-8 编码显示，原因很简单，当初只是为了给国人用，gbk 显然是更好的选择。但有时需要 utf-8 的，这时候就莫得办法。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="没公司要易语言程序员">没公司要易语言程序员<a class="hash-link" href="#没公司要易语言程序员" title="标题的直接链接">​</a></h4><p>几乎没有公司招聘易语言程序员，实际上上面所说的就足以证明易语言不行了。并且很多人都不看好易语言，黑易语言，至于为什么黑，百度或者知乎想必会有更好的答案，这里我也就不再赘述了。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="小总结">小总结<a class="hash-link" href="#小总结" title="标题的直接链接">​</a></h3><p>写到这，我其实有点想把介绍易语言的一部分给删了， 我不推荐新手去学易语言，因为易语言相比于其他语言，它还是太弱了。但如果没有这半年的易语言学习，让我天真的以为编程的简单，又怎么鼓舞真正入坑，让我去学习更多更深奥的知识。</p><p>不过就目前而已，我已经很少用易语言写东西了，但如果要写桌面级软件，我还是会首选易语言（因为只会易语言），毕竟写了也有半年了，开发效率也高。如果有机会的话，会深入学一下 C#还有 Qt，不过也不知道是什么时候才会有机会。</p><p>关于英语方面的话，我是挺惧怕英语的，我高中英语就没怎么及格过，甚至我大学英语还挂科了，但易语言给我带来了编程希望。就我目前学习来说，编程还真的不怎么吃英语，看不懂英语文档，翻译成中文文档不就完事，而且学多了就会发现太多都是死代码，需要的时候翻阅文档直接 Ctrl C V 使用即可。英语对编程来说只是为辅，英语好并不能提高编程的上限，同时也决定不了下限，就这么说吧，你让一个学英语专业的人来看一份几百行的代码，基本注释写得在详细，他没学过编程，能看的懂吗？但有很多开源的项目都是英文的，会英文固然是好，但不会就不行了吗，看不懂英文文档，我翻译还不行吗？说这些，就是希望别用自己的短处来阻劝自己的目标，很多时候都是学了才知道这个有没有用，没学有锤子用！</p><p>易语言是我接触过的第一款编程语言。那时候曾是我最喜欢的编程语言，也是最能让我感到成就感的编程语言，不过在这行学多了，还是不得不放弃易语言开发，原因就是因为易语言不够强大，但也莫得办法，如今易语言的生态就是如此。</p><p><strong>如果易语言不是我的第一门编程语言，那么其他编程语言就是最后一门。</strong></p>]]></content:encoded>
            <category>随笔</category>
            <category>easy-language</category>
        </item>
        <item>
            <title><![CDATA[2019.7-2020.7编程年记]]></title>
            <link>https://kuizuo.cn/2019.7-2020.7-log</link>
            <guid>2019.7-2020.7-log</guid>
            <pubDate>Thu, 08 Oct 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[前言]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="前言">前言<a class="hash-link" href="#前言" title="标题的直接链接">​</a></h2><p>写篇年记，记录一下自己这一年的所学。</p><p>能有幸在这个行业有两点关键因素</p><ol><li><p>QQ 永久冻结</p></li><li><p>易语言</p></li></ol><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="qq-永久冻结">QQ 永久冻结<a class="hash-link" href="#qq-永久冻结" title="标题的直接链接">​</a></h3><p>有些认识我的人可能会知道我的 QQ804493238 给永久冻结了，可以说这个号码是不可能再搞回来的。一个幸幸苦苦养了十年的 QQ ，说没就没的那种，与之相对应的就是游戏账号没了，没了游戏能干嘛，当然不能干嘛，生活还是得过的，但又要有个东西来打发时间，没错就是编程。于是高中毕业后的暑假，就开始了学习编程。不过这里要先介绍一下易语言，作为我的第一门编程语言。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="初识易语言">初识易语言<a class="hash-link" href="#初识易语言" title="标题的直接链接">​</a></h3><p>初识易语言的时候还是在初中，那时候有个同学给我讲诉了他用易语言刷 CF 永久枪，用易语言写游戏外挂的故事，也是那时候我也才刚接触网络游戏，一把永久枪 888 还免费刷，别说有多牛逼了好吧。可以说从那时候开始，下了个目标，以后有时间一定要学易语言！（不过那时候没条件学或者说是给游戏耽搁了）果不其然，在高中毕业后，就开始了易语言的学习（最主要的原因就是号没了，完全没有心思再玩游戏）。</p><p>有关易语言的详细介绍我划分在另一篇文章 <a href="/easy-language">易语言</a></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="http-请求">HTTP 请求<a class="hash-link" href="#http-请求" title="标题的直接链接">​</a></h3><p>这里我需要简单说一下这门技术，就是因为这门技术才能让我能写上软件，并且是有实质性用处的。有关这个介绍可以点击文章 <a href="/brief-talk-http/">浅谈 HTTP</a></p><p>在开学军训一个月期间，也没有放弃学习易语言，不过那一个月应该不算学易语言这个语言，而是在学一个网络协议 HTTP，在这行的术语应该叫 POST 与 JS 逆向（基于易语言），这里我需要放一个我当时学习的链接 <a href="https://www.zygx8.com/thread-7162-1-6.html" target="_blank" rel="noopener noreferrer">零基础易语言 POST 入门到精通</a>，导师教的非常好，是真心推荐，我从他的课程学到了非常多的知识，就凭我听了他的这一期课，就能自行写出超星刷课软件，我觉得这就足够我去报他的班。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="qq-机器人-">qq 机器人 &nbsp;<a class="hash-link" href="#qq-机器人-" title="标题的直接链接">​</a></h3><p>非常可惜之前写了一段时间的 qq 机器人代码无法使用了，相关文章 <a href="https://www.bilibili.com/read/mobile/7009209?share_medium=iphone&amp;share_plat=ios&amp;share_source=QQ&amp;share_tag=s_i&amp;timestamp=1596387202&amp;unique_k=vdFqN2" target="_blank" rel="noopener noreferrer">纪念 QQ 机器人业黑暗的一天</a></p><p>我用的是酷 Q 框架，用易语言写的代码，花了也有半个月的时间去写<img loading="lazy" src="https://img.kuizuo.cn/image-20200926164358137.png" alt="image-20200926164358137" class="img_ev3q"></p><p>那时候封装了好几个功能，最终就因为腾讯的封杀，导致自己辛辛苦苦写了半个月的代码灰飞烟灭。这时候的心情与当初 QQ 被永久冻结一样，不过现在也看淡了，就算回来说实话也高兴不到哪里去，也就在以前群在多吹吹牛逼罢了。（泽宇是我之前玩网的一个艺名）</p><p>这个 qq 机器人算是我手机端和电脑端一个变通的交互方式，以下是一些相关的菜单图，有些功能不方便展示，仅作为个人使用。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20220517010245349.png" alt="image-20220517010245349" class="img_ev3q"></p><ol><li>对接网络验证服务端，购买卡密，实现购买卡密</li></ol><p><img loading="lazy" src="https://img.kuizuo.cn/image-20200928204705890.png" alt="image-20200928204705890" class="img_ev3q"></p><ol start="2"><li>实现一些注册，例如一些软件注册给新用户多少时间使用，就不必在通过电脑，而是直接通过机器人发送命令来注册即可。</li><li>群监控，监控群里的一些不良信息进行撤回，监控刷屏进行禁言操作。</li></ol><p>只要你想，然后给上对应的代码就行了，那时候也是沉迷于 qq 机器人花了很多时间写这些接口。这里的话我说说那时候我用机器人来写一个学校的用手机进行超星线下考试。</p><p>事情是这样的，这个考试是<strong>用手机考试</strong>的，但只能带一部手机，同时老师提供了题库，<strong>允许带资料</strong>，差不多就是开卷考。而且用于考试的软件（超星学习通）是<strong>不允许切换的后台</strong>来进行搜题的（或者说切换到后台会扣分），有些手机是无法分屏的（但是有悬浮窗）。这时候该怎么办，难不成真的去把题库打印一遍？还真有，十几张来着，先不说好不好，找一题都要找半天，有没有更有效的办法，有，我那时候就是通过机器人。</p><p>首先，将老师发的题库，存入文件（那时候的我还不会数据库，就只好读文件），然后通过则匹配，将对应的题目，将答案全部都记录到数组里面去。接着在通过给机器人发送对应的命令如 查题+关键词即可搜到相关的题目。这里就放一个我当初录制的一个视频，（其他人操作也就是通过悬浮窗来）</p><p><img loading="lazy" src="https://img.kuizuo.cn/demo6.gif" alt="demo6" class="img_ev3q"></p><p>即便眼睛再也好，也比不过可靠的搜索，搜索可靠也不及关键词筛选，当初考试就是通过这样方式来通过这场用手机的考试，但是也有缺点，只能说当初写软意识不好，没考虑周全，像这个搜题我还要再打一遍【查题】这个关键词，很傻，而不是发送【搜题模式】，然后直接发送题目获取就行，再发送【退出搜题】（那时候花了一天时间去写）。并且对于这样的搜题还要切换特别麻烦，好一点的办法，有，自写安卓悬浮窗，不过现在也没这样的考试了，也是我后面学了点安卓后随手写的，悬浮窗大致如下。</p><p><img loading="lazy" src="https://img.kuizuo.cn/floating.png" alt="搜题悬浮窗" class="img_ev3q"></p><p>qq 机器人算是我特别想写的一个东西，但很可惜腾讯封杀外面大部分 qq 机器人框架，我使用的同样框架无疑避免，同时腾讯自己的机器人又不给开发者提供合适的开发接口，这就是腾讯吗，这本来就是腾讯的作风。</p><p>至于后续如果有时间，或者要发展 qq 群的话，肯定会重新再写一份 qq 机器人，到时候想要实现功能可就多了。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="疫情期间也是进步最快的时候">疫情期间，也是进步最快的时候<a class="hash-link" href="#疫情期间也是进步最快的时候" title="标题的直接链接">​</a></h2><p>上一阶段学习期间，从 7 月到下半年 1 个月，这一阶段主要就是易语言与脚本开发，相关也就是上述了，而下一阶段，也就是从 1 月中旬到开学（5 月 23 号），也就是差不多这期间，开始了逆向初步学习和 Web 开发方面，而这段时间，可以说除了编程，就只有编程了。</p><p>先说下生物钟，晚上 6 点左右起来，然后早上 9 点左右睡觉，没错，这 4 个月基本上是这么熬过来的。（其中期间调整了两次作息习惯），因为疫情的因素，开不了学，又不方便出去，加上我本来也不喜欢出去，所以这阶段对我来说无疑是最好不过的，而这一阶段，也是我学习最多的时候，见识最多的时候，让我再一次感觉到编程的魅力，但同时让我感受到真正的编程和难。下面则会按时间顺序简单介绍下我学了什么。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="资源共享吧">资源共享吧<a class="hash-link" href="#资源共享吧" title="标题的直接链接">​</a></h3><p>首先要提一个这个学习论坛，因为我在这个论坛上找到的很多教程，可以说没有这个论坛，我视频教程都不好找，先放个论坛链接 <a href="https://www.zygx8.com/forum.php" target="_blank" rel="noopener noreferrer">资源共享吧</a>，首先这个论坛从名字上应该可以知道是资源共享的，是关于编程相关技术方面的资源，可不是那啥，我先放一张图片，看看到底都有啥资源。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20201005025855844.png" alt="image-20201005025855844" class="img_ev3q"></p><p>别说，基本上有关编程的你在这都能看到，当然肯定不是免费了，是需要交 VIP 的，但只要 199 元，终身高级 VIP 会员，别提有多值了，你知道外面一套培训有多贵吗，这我就不提了，自己搜一搜就知道了，我在写超星刷课不是提过一个讲师，我报了它的班，4000 安卓 VIP+3000 网页逆向 VIP 来着，而这里你只需要 199 元，并且在该论坛你也能看到他的一些相关课程。当然，和培训相比还是有一定的区别，但在这里的教程真不差。</p><p>关于付费学习，可能有些人不解，为啥要收费，没为啥，就是你听付费的课程，能比别人学的快，能少走点坑路，很多免费课程要么就是为了推荐他的付费课程，要么就是为了推荐他写的书，总之，免费之中必有付费，单纯的免费课程能学，但想要走个捷径，付费应该是最快捷的方法。</p><p>是真心推荐这个论坛，一点广告费都没收，因为在这个论坛上我下载了特别多有关编程相关的知识，奈何时间不允许，不然我真的都学了。正是因为我在这个论坛上学习到特别多的知识，这就是我推荐的理由之一。</p><p>下面的大多数学习都是基于这个论坛上的视频教程。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="安卓逆向">安卓逆向<a class="hash-link" href="#安卓逆向" title="标题的直接链接">​</a></h3><p>这上半年，我也只会网页端的数据分析与 JS 逆向，很多时候并没有网页版的，只有安卓应用，这时候想要偷其中的 api 接口，找到对应的加密点，该咋办，学呗。就必须要会安卓逆向，并且这个不比网页端简单。</p><p>在我开始提笔写的时候，已经有半年没怎么碰过安卓方面的了，我都快忘记了我安卓逆向的好多知识，而且当初还没有写笔记的习惯，就连我一开始怎么入门的都没什么印象了，总之就是看了教程，然后一步步照抄，视频教程怎做就怎么仿，就完事了。</p><p>同时也正是因为安卓，花了 10 天左右用 2.5 倍速度把毕向东的 java25 天速成教程看完了，而 java 才算是我真正第一门主流的编程语言，之前的 javascript 我是连 ES6 语法都不会的，甚至很多基本的语法我都不知道。但学完了 Java 的基础语法，但对于安卓逆向或者开发来说还是差太多了，虽说对于当时的我看的明白，但实际上整个安卓的项目结构我依旧不明白，不会点开发去搞逆向是真的折腾。</p><p>合理来说我安卓逆向压根就没学完，或者说我只学到了 java 层的源码分析（java 是真的好反编译了），我还没什么能拿的出手的东西，没有破解过安卓软件，只是分析了跟网页端差不多的 HTTP 请求，差不多的加密算法，在这方面我还真的不知道该说写什么，即使说了，很多没了解过安卓逆向人也不懂，后续的话会再学安卓这方面，从开发到逆向，到时候会这方面的知识在进行一个分类总结。（主要是我真的忘了太多了）</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="autojs">Auto.js<a class="hash-link" href="#autojs" title="标题的直接链接">​</a></h3><p>我先简单介绍一下这个是什么，这个也就是专门针对安卓端的无 root 脚本操作，看到后缀名你应该能想到 js，正是用 JavaScript 作为脚本语言。可以说用这个开发工具也能开发些安卓软件，但主要还是针对脚本操作，比如做一个 qq 自动点赞的， 贴吧签到脚本，抖音自动刷视频，双十一用过淘宝叠过猫猫吧，用 Auto.js 也能写个自动浏览商品，刷金币的，此外有太多例子了。</p><p>在之前的脚本操作，我也只会电脑端的，而对手机端无奈只好投屏到电脑，通过电脑的鼠标操作来实现脚本，而现在有了这个软件，则就不用在连接电脑，直接将写好的脚本打包成安装包安装，点击运行即可。但对比原生安卓开发，这个开发工具还是略显下风，不过对于安卓的自动化操作已经足够了，我也只说说我用这个写了个什么软件。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="钉钉签到脚本">钉钉签到脚本<a class="hash-link" href="#钉钉签到脚本" title="标题的直接链接">​</a></h4><p>像抖音自动刷视频和贴吧签到这些我就不多举例，主要还是这个软件，听名字就知道是钉钉签到的，有些在疫情期间，学校老师又要求同学使用钉钉，并且签到，但是有的同学就是会忘记签到或者没起来（说的是我），怎么办，记旷课？这不写个脚挂在那边时间到了自动签到呗。</p><p><img loading="lazy" src="https://img.kuizuo.cn/ddqd1.png" alt="ddqd1" class="img_ev3q"></p><p>这是我当时写的页面，只需要填写对应的课程名和开始的时间即可，时间一到，手机自动亮屏，开始签到。主要的代码就下面这一个函数</p><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">ddSign</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">courseName</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">launchApp</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'钉钉'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">waitForActivity</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'android.widget.FrameLayout'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> course </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">text</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">courseName</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">findOne</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">course</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">parent</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">!=</span><span class="token plain"> </span><span class="token keyword null nil" style="color:rgb(0, 0, 255)">null</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    course</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">parent</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">parent</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">click</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> sign </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">text</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'群签到'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">findOne</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">sign</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">parent</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">!=</span><span class="token plain"> </span><span class="token keyword null nil" style="color:rgb(0, 0, 255)">null</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    sign</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">parent</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">parent</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">click</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">sleep</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">3000</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token function" style="color:rgb(0, 0, 255)">desc</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'群签到'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token function" style="color:rgb(0, 0, 255)">sleep</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token number" style="color:rgb(9, 134, 88)">3000</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> btn_sign </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">className</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'android.view.View'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">desc</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'签到'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">findOne</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> result </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> btn_sign</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">click</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token function maybe-class-name" style="color:rgb(0, 0, 255)">Log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'签到结果'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> result</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">else</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token function" style="color:rgb(0, 0, 255)">toastLog</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'不在群签到页面'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>启动钉钉，等待钉钉启动完毕，找到对应的课程名，点击课程名，找到群签到按钮，点击群签到按钮，进入群签到找签到按钮，点击签到，签到成功。就这么完事了，脚本就是这样的。</p><p>不过最终有个缺点，对于一些没有 root 的手机，需要每次运行就要不断的打开无障碍服务，特别繁琐，但没办法，这是安卓的机制问题。</p><p>这里要提及的一句是为啥不用 HTTP 发送请求要来签到，而是要这种脚本方式，对比一下你就会发现，用脚本写基本无压力，就是简单判断一些字或者图在哪，然后点击对应的坐标，而通过 HTTP 请求的话，一是要过钉钉登录，二是要处理各种加密算法。不过钉钉登录算法难不难我就不知道了，我也懒得分析，加上正好学了 Auto.js，索性就写一个这样的签到脚本得了。但说实话签到就不应该这样用这种定时脚本，而是应该选择协议更好。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="深度学习之图像识别">深度学习之图像识别<a class="hash-link" href="#深度学习之图像识别" title="标题的直接链接">​</a></h3><p>可以去了解一些深度学习，颠覆我对机器的认知，至少让我又觉得编程的强大，重拾学下去的信心。首先，先看张图片</p><p><img loading="lazy" src="https://img.kuizuo.cn/QQ%E5%9B%BE%E7%89%8720201004030419.png" alt="QQ图片20201004030419" class="img_ev3q"></p><p>看图也能看明白，这个就是识别一个缺口的图片软件，可能对没接触过这行业的人觉得这并没有什么软用，这个滑块的意义主要还是防止人为操作和机器操作。对于人而已，自然而然知道缺口的位置，但是对于机器而言要怎么知道这个缺口的位置，就针对上面这类图片，可以通过图片颜色深度来定位到缺口的地方，同时也可以使用深度学习，简单来说深度学习就是 AI，不过这里的 AI 是用来让它识别这个缺口，至于怎么让它识别和对应的算法我就没过多了解了，我接触这个主要还是用现成的模型来训练识别的。说一下我是怎么让机器训练的。</p><p>这个过程其实就跟教小孩一样，现在有一个小孩，他不知道这个缺口的位置，这时候我告诉它缺口的位置在那，对应的操作也就是标注，如下</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20201004031417625.png" alt="image-20201004031417625" class="img_ev3q"></p><p>我把缺口的地方标注一下，并记录对应的坐标，然后告诉这个小孩，缺口是我标注的地方，你下次遇到的时候记得是缺口这样的，但是小孩毕竟是小孩，这是我换一张类似的图片，这时候他可能就蒙了，所以就需要不断的给他标注好的缺口图片，让这个小孩一直看，一直记，直到下一次看到一张陌生的图片，但是它已经把之前训练的给记住了，很快他就能找到缺口的位置，这整个过程其实就是告诉小孩，然后让小孩一直训练，这就达到了我们想要的目的，这个小孩也会知道缺口的位置了。现在把这个小孩换成机器，那么这就是深度学习，并且机器是机器，可以封装的“记忆”远比人类可比，人是会感到疲惫的，而机器不会。再比如下面这张图片</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20201004033445666.png" alt="image-20201004033445666" class="img_ev3q"></p><p>对于我们来说显示屏，键盘等等这些在常见不过了，深度学习就可以做到识别图片对应的物体分别是什么，不过这要的训练量就比上面那个滑块大多了。我这里简单说说主要的通途，现在我想拍一张人脸照，还有风景照，但是时间旧了，我想找可能就要一定的时间，这时候就可以通过识别图片，进行分类，例如头像照，风景照，食物照等等，现在大多数相册都有上述图片分类的功能，不止如此，通过训练还可以识别文字，快递单号，车牌号，识别人脸等等，总之想训练的东西，都能训练，不过就是吃训练量和显卡，一般来说都是用现成的模型直接用就完事了。对我目前而言，我深度学习学的是非常浅了，也只会用用模型，跑个显卡训练训练。</p><p>此外，既然图片训练是这样的，能不能训练其他的，当然，语音识别，模拟一些明星的声音，游戏 AI，甚至让机器自己去学习怎么打游戏，游戏内的人机也就如此，通过训练满分作文，实现写一篇条理清晰的作文等等，太多例子都能看到人工智能。</p><p>关于这方面我也不敢做过多讲述，毕竟也还没开始从事这方面的真正学习。但确实，惊艳到我了，也让我想去学习这方面的知识。想自己写一个属于自己的语音 AI 助手，训练出一个能自己玩小游戏的模型，总之想学的太多了。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="chrome-扩展开发">Chrome 扩展开发<a class="hash-link" href="#chrome-扩展开发" title="标题的直接链接">​</a></h3><p>关于这个的话可以查看我写过的一篇文章 <a href="/chrome-plugin-development">Chrome 插件开发</a>，我总结了一下我那时候学习的插件，和自写的一些模板，不在这做过多赘述了。</p><p>疫情这期间说句闭关学习应该不成问题，不过学的东西远不止于此，主要其他的没写出啥玩意，而且学的很浅很浅，比如汇编基础（不过应该已经忘得差不多了），又深入学习了编写游戏外挂，TCP 协议（和 HTTP 一样），还有就是一些开发工具的使用。期间也写过一些东西，例如疫情填表，网课签到等等，不过都是临时写来自用的，也懒得放图了，原理基本和超星刷课一样，有时间再整理一下。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="web-开发">Web 开发<a class="hash-link" href="#web-开发" title="标题的直接链接">​</a></h2><p>在进入了这个阶段，我就很久没再用易语言开发新的软件了。到目前为止也真的快半年没怎么动易语言的代码了（也快半年没怎么写项目了），就那个超星刷课而言，没想到半年后还能用。而这一阶段主要接触的也就是 Web 开发方面。</p><p>实际上，我在接触易语言就已经接触了一些 Web 方面，因为要针对网页的一些操作就不得不接触这些，比如 HTTP 协议，DOM 解析，CSS 选择器，JS。不过那时候这对真正的 Web 开发远远不够。当然要说一下为什么会想学习 Web，在学 Web 之前，实际上还接触了一些 js 高端操作，例如 AST 语法树（混淆 js 代码），WebSocket，但发现有点没学明白，用都有点没用明白，然后就是想搞明白这些操作，于是进阶学习 js。</p><p>其实决定性的也就是一门编程语言——JavaScript，那时候感觉到易语言的不足，恰好手头在学的一门编程也就是 JavaScript，于是就开始了 JavaScript 的学习，可以说不是 JavaScript，Web 想都没带想的。js 作为我目前的主力语言，就目前而言，基本屏幕上，必有 vscode 的痕迹，而且还是 js。js 吸引我的一个地方就是其他语言都能调用，加上语法清晰，不过要我硬说 js 哪里好，我也说不清楚，可能这就是对一件事物的热爱吧。</p><p>于是改变了当初原有的想法——搞安卓开发与深度学习，转行到 Web 开发去了，和学习其他技术一样，找教程，跟教程做一遍，自己在举一反三一波才不多就明了。</p><p>Web 学习确实比逆向轻松，并且学完 Web 能写的东西也算比较多。也算可以自己动手设计出一个界面或者功能出来，上手特别容易。这里我就不献丑了，之前前端写的那些代码真没脸丢出来。就连当初的笔记我都不敢看，写的是什么玩意，竟然还是在 js 文件上用注释来记录笔记。</p><p>就这样学习了几周，然后收到了开学通知，没错是开学通知，疫情的时候，开学一个月，于是就停滞了学习近一个月了，前面也说到，生物钟的问题，开学了就不得不强行调整生物钟，把我学习节奏给打乱了。其次突然开学，心态是真崩了，开学各种繁琐的事情搞得压根学不进去。原本不出意外在保持这样的学习状态一直学下去，暑假结束前就能把 Web 大部分知识都能搞完，然而却拖到现在。</p><p>不过也不能说开学不好，从 1 月 10 号放假，到 5 月 23 号开学，在家好像也就出门了 2 次，要是再这样拖到暑假估计身体可真要出问题。停滞了学习，但保住了身体，是赚是亏，对我来说血亏吧。</p><p>然而暑假由于学车的因素，加上外出玩了一波，整个暑假并没有像去年那样全身心投入去学习，不过业余时间会去摄取有关这行的知识与科普，也就是刷刷知乎，公众号，博客文章等等。而也就是在这段了解到了 Nodejs 与 Vue，暑假开始学习。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="nodejs">Nodejs<a class="hash-link" href="#nodejs" title="标题的直接链接">​</a></h3><p>不过学前端，Nodejs 基本是必接触，基本可以说只要是个前端开发者，就肯定会 Nodejs，关于 Nodejs 不做过多介绍，我能推荐的也只是一些 npm 包，总之在这期间 也就是只学了点 Nodejs 的基本使用，还有 npm (Node 包管理器)。</p><p>主要接触两个 Web 框架 Puppeteer 与 Express，关于这两个我在 Node 的那个目录内有简单说明到，这里也就不放链接了。这里简单说说 Express</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="express">Express<a class="hash-link" href="#express" title="标题的直接链接">​</a></h3><p>学 node 大多数就是为了搞服务端，那么肯定也有对应的服务端框架，Express 就是其中之一。</p><p>在此之前，我是写过点后端的，也就是一个网络验证的系统，不过那时候是基于易语言和 HP-Socket 的库，但有一个很大缺陷，就是我这个后端服务器编译出来的是 exe 文件，也就是只能在 windows 上运行，这对 Linux 系统服务器很不友好，于是乎就想搞一个基于 Express 的网络验证服务端。</p><p>而这期间才算学会用 Mysql，之前易语言写的网络验证时连 Sql 语句都不会，还都是用易语言自带命令帮我封装好来进行增删改查。也简单的将易语言写的网络验证接口全都搬运至 Express 中，然而有个问题来了，我要怎么查看数据？难不成直接打开数据库查，怎么可能，而这就开始了 vue-element-admin 开发，后文会说到，因为这里要涉及到一个新的技能——Vue。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="vue">Vue<a class="hash-link" href="#vue" title="标题的直接链接">​</a></h3><p>可以说没有 Vue，我多半不会去继续学习前端（怎么感觉这句话好像说过了），和大多数人学 Web 一样，都是从基本的 HTML CSS JS 这前端三件套开始学起，然而在学到一半的时候，想写一写 Web 小项目的时候，就需要在一个 HTML 上写上大量代码，并且页面还不好设计，并且在用了 Express 一段时间后，发现如果要做动态网站的时候，就需要将数据渲染到对应的模板语言上（如 ejs），于是想知道有没有啥能解决这上述问题，于是便开始搜索有关前端的一些相关知识扩展，果不其然，困惑了我一段时间是否继续学习前端，因 Vue 而解惑。</p><p>如果要我评价一句 Vue，我只能说后悔学 Vue，后悔学晚了。我花了挺多时间在原生的前端开发，在了解到 Vue 时，还在用着 Jquery。Vue 让我继续学前端并不是数据交互方面，而是模块化，在我接触原生前端开发的时候，这个问题尤为困扰我，每次写一个页面都需要重复大量相同代码，即便是复制粘贴也觉得烦躁，而 Vue 组件化就不一样。例如我当前的博客页面，你会看到导航栏，侧边栏，与正文，评论系统，乃至打赏按钮都是一个个组件拼接而成，只需要在单个 Vue 文件中，引入对应的组件，然后想 html 标签那样直接写在视图层上即可显示，当然，相关代码也展示了，有关 Vue 的我也都放在 Vue 这个目录下。</p><p>然后就是基于 Vue 而开发的组件库，在 Web 开发难免不了页面设计，然而并非所有程序员又兼设计师，想要设计出一个好看的按钮或其他组件并非容易的事情，而组件库便提供了一个好看的组件供开发者使用，例如通过引入 element 的样式与组件库</p><div class="language-html codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-html codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)">&lt;!-- 引入样式 --&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">link</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">rel</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">stylesheet</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">href</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">https://unpkg.com/element-ui/lib/theme-chalk/index.css</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">/&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">&lt;!-- 引入组件库 --&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">script</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">src</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">https://unpkg.com/element-ui/lib/index.js</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token script"></span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">script</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>然后在官网中找到需要的组件，如下按钮</p><p><el-button type="primary" plain="true">主要按钮</el-button></p><p>而对于的代码也就是</p><div class="language-html codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-html codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">el-button</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">type</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">primary</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">plain</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain">主要按钮</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">el-button</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>只需要简单修改一下参数就能生成相应的组件。哪里还需要花费大量时间去写 css，不断改参数，上手即用，快速成型。</p><p>Vue 模板语法也是，显示后端传递的数据也简单，比如下面这行</p><div class="language-html codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-html codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">h1</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain">标题: {{ title }}</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">h1</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>只要接收到后端发送来的标题，即可渲染在<code>{{title}}</code>内，此外还有数据的双向绑定，关于这些等等不在这细说了，需要的话可以自行翻阅 Vue 文档。</p><p>而且就这么说吧，前端框架如果不学 Vue 和 React 其中之一，面试都不给你面试的。甚至可以说，Vue 和 React 是前端开发必学之一，不学就跟不学前端没两样。</p><p>同时 Vue 还是国人尤大大（尤雨溪）开发的，在国内生态好，社区活跃高。基本上目前国内的大部分 Web 项目都有 Vue 的身影，同时 Vue 不止于前端，小程序的开发等等也有它的身影，如 uniapp 就是使用 Vue.js 所开发的。</p><p>Vue 能做的太多了，如果你恰好准备学 Web 方面，尤其是前端，毫不犹豫，直接学 Vue，Vue 在 github 上排名第三，star 高达 175k，凭这，就足以去学习一番。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="vuepress">Vuepress<a class="hash-link" href="#vuepress" title="标题的直接链接">​</a></h3><p>Vuepress 一个 Vue 驱动的静态网站生成器，可以用 Vuepress 来写文档，写博客，而我目前这个博客便是通过 Vuepress 实现而成。关于这个博客搭建过程就不在这花费口舌了。我有一篇文章专门讲述这个博客的搭建过程。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="对-web-开发做个小总结">对 Web 开发做个小总结<a class="hash-link" href="#对-web-开发做个小总结" title="标题的直接链接">​</a></h3><p>可以说没有前半年易语言学习所接触到的 Web 知识，就别说 Web 开发了，JS 估计都不会了解到，也因 JS，误打误撞闯进了 Web 开发的坑，让我领略到更多知识。</p><p>我算是作为 JS 语言的粉丝，听说过一句名言：凡是能用 JS 实现的最终都将用 JS 实现。即便不理解这句话的意思，但依旧这句话很喜欢，也许这就是对 JS 语言的一种爱吧。</p><p><img loading="lazy" src="https://img.kuizuo.cn/javascript.jpg" alt="javascript" class="img_ev3q"></p><p>写到这，其实 Web 开发真就要告一段落了，实在是不想在折腾 Web 了，主要就两点</p><ul><li>不会设计，不知道该设计什么，实现什么功能</li><li>后端数据接口写的非常痛苦，Express 折磨了我一个月</li></ul><p>在页面设计方面，有组件库很方便，但是不知道要写什么好，就那个网络验证而言，我已经绞尽脑汁想添加写功能，但是奈何后端写的折磨，很多我都写不下去，就比如用户-角色-权限 这三者关系，我只写了用户-角色 还有权限没写，还有积分，与 nodejs 模拟数据这些写的都特别鸡肋，实在是写不动了（甚至说实在不想写了）。想转型写点其他的，后续有时间才把这个在做过多优化。</p><p>目前把博客和网络验证基本搭建好，现在脑子只想好好写写博客，把这一年要学过的东西好好巩固一番，尤其是这一段 Vue 的学习，收获到太多知识，都有点来不及消化。后续会将这些都部署在该博客上（不妨点个收藏收藏个书签呗）</p><p>不过我目前的 Web 开发还有很多没学到，而关于 Web 后续的学习的话，以目前的话应该是不会在花费大量时间去学了，学了也有半年了，自我感觉 Web 这方面还是不适合我，但确实这半年的 Web 学习挺充实的，不会接着深入学习,会用已学过的知识去写一些东西出来。（主要还是太想学习其他技术了）</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="总结这一年学习经历">总结这一年学习经历<a class="hash-link" href="#总结这一年学习经历" title="标题的直接链接">​</a></h2><p>这一年学的确实多，相比于刚接触这行一年的人来说的话，我挺知足这一年能花费大量心思在这上面，同时还能坚持学下去，并爱上编程，于是乎从数学系转到了计算机系，但学还是自己学自己的，在我看来学校老师能教的，不如我课下自己学习的，况且编程单靠别人教是教不出什么玩意的，还真没听说过什么大神是另一个大神教出来了。</p><p>不过正是因为这种心态，也导致如今我连学校的课基本也都不会去上，能旷的课尽可能旷，旷课补觉，或者是宅在宿舍，坐在电脑前，盯着这赏心悦目的代码，和平时分相比它不香吗。既然旷课，那怎么能不挂科，虽然都是公共课，不过挺无所谓了。说件好玩事情，我大学英语挂了，没错，我英语说实在话就是不行，甚至我都没打算过四级考试，但这影响编写代码吗？不言而喻。</p><p>专业课的话，有的老师一般会认可我的能力，允许不去上课只考试就行，或者是不去也不会记名字，甚至和老师说一声不去就完事了。至少在我看来有时间在学校拿个文凭，不如直接用自己写过的项目去面试，至于看学历还是看能力，面试官一般都不看，因为只看简历呗。目前的话除了有关编程的事啥也不想干，估摸着在学一段时间就说不定真就辍学了呗，不，说不准还是给学校开除。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="身体状态">身体状态<a class="hash-link" href="#身体状态" title="标题的直接链接">​</a></h3><p>早已习惯了凌晨晚睡晚起，早上的课基本也都是旷了的那种，就已经习惯了旷课。再看看下午的课，不出意外的话，一般就是坐在电脑前到，到点了吃个饭，接着到凌晨 3,4 点，每天反复这样。我都不敢说我在这方面有天赋，我只觉得我每天花费在这方面的时间是别人的几倍罢了。</p><p><strong>哪有什么天生，一切不过是摧残出来罢了。</strong></p><p>说实在话，挺享受整天在电脑前办公的生活（相比于躺在床上玩游戏而言），不过熬夜，久坐，与长时间盯着屏幕，甚至是掉发，身体难免有些遭不住，并且我是能感受到，身体一天不如一天了。但它改变了我原有枯燥的生活，成天的游戏与娱乐，迷茫到不知所措， 如果没有 QQ 冻结，还有易语言，JS 这些，说真的，我现在极有可能还在某个床角玩着游戏，还对着屏幕傻笑（现在就特别想笑）。即使都是宅在家的生活，但编程能成为我养家糊口的资本，而游戏，它不行！甚至还可能成为我颓废的资本。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="事实告诉我我还有很多要学">事实告诉我，我还有很多要学<a class="hash-link" href="#事实告诉我我还有很多要学" title="标题的直接链接">​</a></h3><p>就在 9 月初，参加了一场网络安防（CTF）的比赛，真的是小巫见大巫，瞬间觉得自己还有很多要学的，虽然其他选手都很强，但也印衬了自己在这方面就是技不如人。说白就是自己菜，就是学的不够多，要是能在多学一点，说不定就多解一道题，多拿一点分，说不准就苟一波，吃个烂分。而事实是这是场没拿奖的比赛，而我是这场比赛的失败者。</p><p>不过有参与必有收获，确实让我学到了 Web 的一些渗透知识与一些工具的使用，也让我更加觉得外面的大佬是真的多，自己离他们还需要更加努力一把，这场比赛值了。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="给别人的一些建议">给别人的一些建议<a class="hash-link" href="#给别人的一些建议" title="标题的直接链接">​</a></h3><p>我也仅能给别人一些我学习上的建议，也仅仅是当前，毕竟我接触这样也才一年多。我其实都不推荐去学编程这玩意，但我常常和别人说多花点时间在这上面，能写出些东西来。话是这么说，但真正肯去学的又有几个，即便学了坚持下去的又有几个，即便花费口舌去和他们介绍，但多数觉得难，但你说这个东西难吗，很难，但你说学不进去吗，也不至于，如今网络上生态这么好，学习编程的人越来越多，相互帮助的人也多，只要肯学，肯下功夫，随便一百度就有的结果，怎么可能学不会。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="多搜索少问人">多搜索，少问人<a class="hash-link" href="#多搜索少问人" title="标题的直接链接">​</a></h4><p>我这一年学习中，基本上就是看视频跟着视频教程一步一步照做，我一开始学习的时候也会在群里问过别人，也私下问过别人，但是有用吗？压根就没用，基本就没什么人会去鸟你的。百度它解决不了吗，如今强大搜索引擎会是你解决问题的最好选择（甚至我帮别人解决问题还是我将百度结果链接给别人）。有两句话，百度 5 分钟，问人 2 小时。百度能解决你百分之 99 的问题，但问人并不一定解决其中的百分之 1。</p><p><img loading="lazy" src="https://img.kuizuo.cn/006ARE9vgy1fwntelg0mlj30b40b4gm1.jpg" alt="006ARE9vgy1fwntelg0mlj30b40b4gm1" class="img_ev3q"></p><p><strong>没点自行解决问题的能力真心劝别碰这行。</strong></p><p>我现在都有点反感那些没自行尝试，就直接问人的那种，有什么好问的，要么你学的不够多看不懂呗，要么就是你那里少做了什么步骤，大不了重新卸载安装重启来一遍嘛。主要没点自行解决问题的能力，到时候项目一来，出了一个 bug，或者开发环境与生产环境有问题，你问谁去？问了会回复你吗？能不能先自行看看是不是哪里少改的，或者版本的问题。说太多就是想强调一点，自行解决很重要，决定你适不适合干这行。</p><p>话也不能说的这么绝对，有时候搜索引擎确实不能有效的给到你想要的答案，比如我所用过的一个博客主题，是有交流群的，但有时候我百度了半天就是得不到我想要的结果，然后一问群，<strong>可能</strong>会一些<strong>热心伙伴</strong>会给你<strong>正确</strong>的答案，但往往是在你<strong>实在解决不了</strong>的情况问。毕竟，问了不一定答，但是不问一定不答。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="复制粘贴也是一门技术">复制粘贴也是一门技术<a class="hash-link" href="#复制粘贴也是一门技术" title="标题的直接链接">​</a></h4><p>别觉得偷别人代码有什么丢脸了，有的人甚至连偷都不会偷，而你早早就把项目给搞定了，别人会认可你的过程还是认可你的结果，必定是结果好吧，而且干这行的，基本上你见不到一个程序员是真的每一行每一行开始写起，而用的最多的三个键 Ctrl C V，不会真有程序员一行一行的敲吧，不会吧，不会吧。</p><p><img loading="lazy" src="https://img.kuizuo.cn/7280a4701a0daf98.jpg" alt="7280a4701a0daf98" class="img_ev3q"></p><p>当然，上面也只是说笑了，只是现在都是模块化编程，什么意思呢，就比如我要实现一个自动发送邮件的功能，怎么办，直接搜索，比如 nodejs 中实现发送邮箱，于是就搜索到了 nodemailer 这个模块，二话不说，直接运行官方的 demo 案例，发现可以运行，能达到我想要的目的，接着就是自己简单的封装一下，直接给项目来使用，这不就成了吗？</p><p>然而要从 0 开始写一个发送邮件的服务端，别有这种想法，大概率不会想写的。就我目前而言吧，除了一开始学习新的技术外，会跟着敲一遍磨磨手感，到后面基本上都是从网络上偷各种源码，然后自己看一遍主要的地方是怎么实现的，然后对源码进行修改来达到我需要的目的。如今网络环境这么好，想要的功能随便一搜就有了，如果你能做到改别人的代码，那么别人这份代码你肯定也学进去了不少。为啥还要自己造轮子，尽可能利用别人已经写好的代码，而不是自己在手动写一份类似功能。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="定一下明年的目标">定一下明年的目标<a class="hash-link" href="#定一下明年的目标" title="标题的直接链接">​</a></h2><p>到目前为止，我还有好多想写的东西没写，好多好多都写了一半由于一些某某原因没继续写下去。同时还有好多想学的技术，好多都是之前学到一半卡着就没接着学下去了。至于能学多少，尽力而为吧，希望明年的这个时候，在回头看看自己所写的一些代码，都能感到一些惬意。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="进阶-web-开发">进阶 Web 开发<a class="hash-link" href="#进阶-web-开发" title="标题的直接链接">​</a></h3><p>Vue 才学了点皮毛，很多 HTML5 特性都没玩明白，CSS 也只会基本样式，就别说设计网页特效啥的，能看的过去就不错了，如果有时间的话一定会去接触写 React，毕竟和 Vue 一样，都属于人气爆棚的前端框架，很多大厂都使用 React 作为前端框架使用。</p><p>像 Webpack，Eslint 等等前端工具库，再如 JavaScript 的超集 Typescript，这些肯定都会去学习一番。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="进阶-python">进阶 Python<a class="hash-link" href="#进阶-python" title="标题的直接链接">​</a></h3><p>学过点 Python，但并非精通，有特别多的库都还没用过。主要说说为什么想学 Python，最主要的就是深度学习这方面，在前面我也写过，深度识别之图象识别，其次就是模拟数据请求这些，如果知道 Python，说到爬虫自然不陌生，不过爬虫对我来说并不敢兴趣，主要是 Python 好做模拟请求，http 协议这些，在易语言这些操作都是乱写，基本没啥难度，当然，http 协议难得不是模拟数据请求，而是在逆向分析数据加密，风控算法，所以网页逆向的基本功还是要有的。</p><p>当然，如果有可能还会接触一些 Python 的后端框架 Djongo 和 Flask，看看会不会符合自己的编程风格，再考虑是否要重写一些后端接口，当然最主要的还是想学习 tensorflow，我本地环境都搭建好了，然而却没有花大量时间去在这方面学习！</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="安卓逆向与安卓开发">安卓逆向与安卓开发<a class="hash-link" href="#安卓逆向与安卓开发" title="标题的直接链接">​</a></h3><p>干这行前，我就是个重度手机使用者，或者说是玩机者。对于手机特别感兴趣，刷过机，拆修过手机，手头目前就有 5 台手机，对于电子设备可以说是又爱又恨了。用过的 APP 多，然而有些 APP 并不能达到我想要的目的，或者说有限制，于是就想尝试利用逆向技术去修改，奈何那时学了皮毛的安装逆向，根本不够用，也感到困难，于是就没继续学习，一开始的本心还是想搞安卓这方面。</p><p>如果可以的话，我更希望的是当一个安卓开发人员或者逆向分析工程师，而不是一个 Web 开发人员或者网络安全工程师。至于最后能如何，谁又能说的准呢。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="github">github<a class="hash-link" href="#github" title="标题的直接链接">​</a></h3><p>就目前而言，git 还有很多没玩明白，主要手头也没啥好开源的玩意，明年，一定多刷 github，当然最想的还是搞一个开源项目，还能在 github 上小有知名，那干这行真就无悔了。有点小野心，但以目前能力估计是够呛，想想就好，到时候技术上来的指不定就真成了呢。</p><p>这不才学了一年，才 20 出头，留给我的时间还多着很，在学个十年不成问题吧。但话是这么说，自己心里很清楚，已经有点学不进去了，就我写 Web 项目的这段时间，写着写着就去搞其他东西去了，实在是写的憋屈。总之已经没有一开始那么想学，那么有想法与灵感，那么肯于去学习新的技术，估摸着在学几年也许就会停滞于学习。</p><p>本以为年轻有的是精力，还曾妄想把好几门技术都学进去，但事实告诉我，能精通一个就不错了，学那么多意义又在哪，只是为了满足当初高中不认真学习的而又渴望学习的心吧。</p><p>总之，能学就尽量学，明年，理应更强。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="感谢">感谢<a class="hash-link" href="#感谢" title="标题的直接链接">​</a></h2><p>最后还是要感谢互联网的前辈们，与当下互联网的环境，不然的话我还可能在迷茫中四处摸索人生的真正意图，耗费着年轻所带来的资本。往着曾经写过的代码，眼角不禁也会湿润起来（绝不是熬夜太困），感叹当初为啥会去学这东西呢，也许这就是编程所带来的魅力吧。</p><p align="right">写于2020年11月18日 &nbsp; &nbsp;By 愧怍</p>]]></content:encoded>
            <category>年终总结</category>
            <category>summary</category>
        </item>
        <item>
            <title><![CDATA[浅谈HTTP]]></title>
            <link>https://kuizuo.cn/brief-talk-http</link>
            <guid>brief-talk-http</guid>
            <pubDate>Tue, 29 Sep 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[记录 git 操作失误导致代码丢失与找回的过程]]></description>
            <content:encoded><![CDATA[<p>关于 HTTP 我不讲理论，只讲一下具体的用途。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="get-请求之发送验证码">GET 请求之发送验证码<a class="hash-link" href="#get-请求之发送验证码" title="标题的直接链接">​</a></h2><p>首先我举一个例子，收过短信验证码吧，一般来说在你注册账号的时候就会用到，会有一个点击发送验证码的按钮，这里以 网址 <a href="https://www.114yygh.com/" target="_blank" rel="noopener noreferrer">114 预约挂号</a> 为例</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20200928234944932.png" alt="image-20200928234944932" class="img_ev3q"></p><p>输入完手机号，点击获取验证码就能收到验证码，但这背后的原理又是啥，服务器那边怎么知道我要验证码，并且我输入正确的验证码就进入，错误的就不行。而这正是网络协议 HTTP（关于 HTTP 相关的这里不做过多讲述，希望读者能自行百度了解），我先说下点击了获取验证码发生了什么，通过抓包工具可以获取到如下请求</p><div class="language-http codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-http codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">GET https://www.114yygh.com/web/common/verify-code/get?_time=1601308153790&amp;mobile=15212345678&amp;smsKey=LOGIN HTTP/1.1</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">Host: www.114yygh.com</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">Connection: keep-alive</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">Accept: application/json, text/plain, */*</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">Request-Source: PC</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3775.400 QQBrowser/10.6.4208.400</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">Content-Type: application/json;charset=UTF-8</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">Referer: https://www.114yygh.com/</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">Accept-Encoding: gzip, deflate, br</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">Accept-Language: zh-CN,zh;q=0.9</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>首先我们向服务器发送了一个如上的请求，这是一个 GET 请求，同时请求的链接（url）为<code>https://www.114yygh.com/web/common/verify-code/get?_time=1601308153790&amp;mobile=15212345678&amp;smsKey=LOGIN</code></p><p>如果你会点英文的话，可能会理解其中的含义，主要就这几个参数<code>verify-code</code>验证码，<code>_time=1601308153790</code>时间戳（时间戳是一个记录时间的东西，用当前时间减去<code>1970-01-01 08:00:00</code>即可得到，你可以通过这个工具<a href="https://tool.lu/timestamp/" target="_blank" rel="noopener noreferrer">时间戳在线转化</a>，这里的<code>1601308153790</code>所对应的时间为<code>2020-09-28 23:58:06</code>）还有一个<code>mobile=15212345678</code>，这个<code>15212345678</code>是我刚刚输入的手机号。这是向服务器请求的数据，那在来看看服务器返回给我们的是什么</p><div class="language-http codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-http codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">HTTP/1.1 200</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">Date: Mon, 28 Sep 2020 15:49:15 GMT</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">Content-Type: application/json;charset=UTF-8</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">Content-Length: 57</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">Connection: keep-alive</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">Set-Cookie: hyde_session=Kd10cra3X4yNBePaaQTKUkuYgX9J6Hfx_5337693</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">Set-Cookie: hyde_session_tm=1601308154470; Domain=.114yygh.com; Path=/; HttpOnly</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">Content-Security-Policy: : default-src *.114yygh.com *.qq.com *.baidu.com; font-src * data:</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">X-Content-Type-Options: nosniff</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">X-XSS-Protection: 1; mode=block</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">X-Frame-Options: SAMEORIGIN</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">X-Via-JSL: d8c5e31,-</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">X-Cache: bypass</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">{"resCode":0,"msg":null,"data":{"endMilliseconds":59997}}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>只需要关注最后一行即可，其中 resCode 为 0，同时手机号<code>15212345678</code>也收到了验证码，貌似 resCode 为 0 就决定了服务器是否有给手机号发送短信，事实上也是的，那么说了这么多，有什么用呢，用处可大了。</p><p>既然这样，我知道了发送上面的那个请求服务器就能给对应的手机号发送验证码，那么我能不能将上面那个请求的手机号给改一下，改成<code>15287654321</code>，事实上是完全没问题的，这里我就放一张 HTTP 测试工具的截图。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20200929001306474.png" alt="image-20200929001306474" class="img_ev3q"></p><p>那么是不是我多请求这样像服务器请求，我就能源源不断的收到验证码，现实很美好，人家服务器也不傻，我再一次向服务器发送请求，服务器给我的结果是</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token string-property property">"resCode"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token number" style="color:rgb(9, 134, 88)">10000</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token string-property property">"msg"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token string" style="color:rgb(163, 21, 21)">"请58秒后重试"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token string-property property">"data"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token keyword null nil" style="color:rgb(0, 0, 255)">null</span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>没错，就需要等，而且这里的 resCode 也不为 0，那么既然要等一分钟的话，我能不能写个定时脚本，每隔一分钟发送一次，人家服务器也不傻，一般来说，一个手机号最多也就收 5 次验证码，多了就会提示明天再重试，或者今天收到的验证码过多等等。而外面的炸则是通过收集几百个这样的请求，然后将手机号替换成要轰炸的，即可实现多平台验证码轰炸一个手机号。</p><p>现在你可能已经知道了初步了解 HTTP 请求，但一般的网站都不会像这个这么简单的，明文标码，通常都会进行效验，例如图片验证码，滑块，点字，点图等等，并且还会进行加密操作处理，而这才算真正的难点。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="post-请求之登录">POST 请求之登录<a class="hash-link" href="#post-请求之登录" title="标题的直接链接">​</a></h2><p>既然发验证码是这样，那如果是登录呢，下面就用网站 <a href="https://m.wcbchina.com/" target="_blank" rel="noopener noreferrer">万创帮</a> 为例，首先进入登录界面</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20200929003119277.png" alt="image-20200929003119277" class="img_ev3q"></p><p>输入手机号和密码，点击登录，同样的我们可以通过抓包工具获取到对应的 HTTP 请求，如下</p><div class="language-http codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-http codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">POST https://m.wcbchina.com/api/login/login?rnd=0.6463111465399551 HTTP/1.1</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">Host: m.wcbchina.com</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">Connection: keep-alive</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">Content-Length: 149</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">Pragma: no-cache</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">Cache-Control: no-cache</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">Accept: application/json, text/javascript, */*; q=0.01</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">Origin: https://m.wcbchina.com</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">X-Requested-With: XMLHttpRequest</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">User-Agent: Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Mobile Safari/537.36</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">Content-Type: application/json</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">Accept-Encoding: gzip, deflate, br</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">Accept-Language: zh-CN,zh;q=0.9</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">{"auth":{"timestamp":1601312429287,"sign":"777473FB2A1838DBD64BA7A11C98911B"},"username":"15212345678","password":"E9BC0E13A8A16CBB07B175D92A113126"}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>貌似比上面那个发验证码的复杂，确实，这是一个 POST 请求，你在链接上看不出什么有效信息，在最后一行才是关键。这里的<code>timestamp</code>也就是时间戳，记录时间的，username 是我们输入的手机号（账号）没什么问题，这里的 sign 和 password 的内容又是啥？这就是加密，让你不能简单单纯的通过替换文本来实现登录，这就来分析一下他到底怎么加密的。</p><p>通过在浏览器按下 F12 键，打开控制台面板，接着点击 Network，这里会将我们发送的请求记录下来</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20200929004247182.png" alt="image-20200929004247182" class="img_ev3q"></p><p>同时鼠标停在 Initiator 上有如下结果</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20200929004449660.png" alt="image-20200929004449660" class="img_ev3q"></p><p>不管三七二十一，点击跳转到对应的代码先，然后在左边下一个断点</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20200929004628978.png" alt="image-20200929004628978" class="img_ev3q"></p><p>这时候我们在点击登录按钮看看</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20200929004713733.png" alt="image-20200929004713733" class="img_ev3q"></p><p>没错，浏览器这时候停了下来，停在了我下断点的地方，通过函数名也可以猜到这个是发送的，对应的肯定在上面，通过右边的 Call Stack 函数调用栈即可追随上一函数</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20200929004943674.png" alt="image-20200929004943674" class="img_ev3q"></p><p>在这里我看到了原文的信息，这是通过 Jquery 通过 id 获取元素的值，也就是这里的手机号和密码，在这里还都是原文，点到下一个函数则变成了密文，那么肯定是上一个函数做了手脚。</p><p>认真观察，N 这个是我们的密码，但对 N 进行了一个操作也就是 <code>a.hex_md5(N)</code>，没错，这就是 md5 加密。有关加密的可以看看我写过的 <a href="/docs/brief-talk-encryption-algorithm">浅谈加密算法</a></p><p>那么通过加密工具将 md5 加密是否能得到我们要的加密结果，如下</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20200929005711500.png" alt="image-20200929005711500" class="img_ev3q"></p><p><code>E9BC0E13A8A16CBB07B175D92A113126</code>在看看 Password 的值，一模一样，看来已经解决了一个参数，那么还有一个<code>sign</code>呢。貌似右边的函数调用栈都不好使，我试试搜索字符串 sign 看看</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20200929005911119.png" alt="image-20200929005911119" class="img_ev3q"></p><p>好家伙，直接定位到了，那么同样的在这里下一个断点，查看一下到底发生了什么（实际上 js 静态分析就完事了，这个网站太简单了）</p><p>这里的 N 看来就决定了 sign，而 N 也是通过 md5 加密的，不过原文我还不知道，让代码执行到这一行看看结果</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20200929010417525.png" alt="image-20200929010417525" class="img_ev3q"></p><p>这里的 c 就是时间戳，而 token 和 password 都是未定义，那么就好办了。这里明文也就是 c <code>1601312429287</code>，那么用加密工具即可得到<code>777473FB2A1838DBD64BA7A11C98911B</code>，那么参数都搞定好了， 只需要替换一下账号，然后将正确的密码通过加密算法（这里为 md5）生成，同时对 sign 也生成出来，然后提交给服务器就能收到我们登录的请求，就认定为我们登录了，记录为在线用户。</p><p>如果我用的加密算法错了，或者我分析错了，提交给服务器会是怎么样的</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20200929011055451.png" alt="image-20200929011055451" class="img_ev3q"></p><p>例如我这里的 sign 算法是错了（将结尾的 B 改成了 A），发送给服务器，服务器返回给我们则是失败的结果，原因很简单，就是为了防止别人恶意登录所添加的效验，提交的数据伪成败，就决定了服务器给我们结果是成败。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="总结">总结<a class="hash-link" href="#总结" title="标题的直接链接">​</a></h2><p>通过上面的一些例子，只要能伪造请求，发送给服务器，就能获取我们想要的结果或者目的，事实上也是如此，但伪造数据的难易则要由所对应的网站而定，有的网站压根就没没什么难度，而有的你搞一天都未必能搞的出来。如今的网站在这方面也都下足了功夫，想要轻松的伪造请求可不是件容易的事情了。</p><p>也正是因为我学了 HTTP 请求与 JS 逆向分析，我能做的也就更多，而正是基于 HTTP 协议下，其中一个就是有关于超星刷课软件的例子，如果我没有学过这些，我就不可能写出来。</p><p>后续会有关 HTTP 请求这方面都会放在逆向这个分类下，比如一些网站的加密算法和常见的坑等等。</p>]]></content:encoded>
            <category>http</category>
        </item>
        <item>
            <title><![CDATA[Chrome插件开发]]></title>
            <link>https://kuizuo.cn/chrome-plugin-development</link>
            <guid>chrome-plugin-development</guid>
            <pubDate>Mon, 28 Sep 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[前言]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="前言">前言<a class="hash-link" href="#前言" title="标题的直接链接">​</a></h2><p>相关文章 <a href="https://developer.chrome.com/extensions/manifest" target="_blank" rel="noopener noreferrer">谷歌官方文档</a> (需翻墙)</p><p><a href="http://blog.haoji.me/chrome-plugin-develop.html" target="_blank" rel="noopener noreferrer">Chrome 插件开发全攻略</a> （强烈推荐看这一篇！）</p><p>你只需要看完上面那篇文章和掌握一些前端开发基础，就足以自行编写一个 Chrome 插件。本文也是基于上面文章加上自己之前写的插件所记。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="什么是-chrome-插件">什么是 Chrome 插件<a class="hash-link" href="#什么是-chrome-插件" title="标题的直接链接">​</a></h3><p>如果你用过 Chrome 浏览器的话，也许会用到过一些插件，其中比较知名的就是油猴插件，通过这些插件能够帮你例如自动完成一些功能，屏蔽广告，相当于一个浏览器内置的脚本。应该来说这是 Chrome 扩展开发，不过说 Chrome 插件更顺口，后文也会说成 Chrome 插件。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="安装-chrome-插件">安装 Chrome 插件<a class="hash-link" href="#安装-chrome-插件" title="标题的直接链接">​</a></h3><p>首先打开 Chrome，如下图即可进入插件的管理页面</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20200922225606159.png" alt="image-20200922225606159" class="img_ev3q"></p><p>这时候记得把右上角的开发者模式给勾上，如果不勾上的话你无法直接将文件夹拖入 Chrome 进行安装，就只能安装<code>.crx</code>格式的文件。Chrome 要求插件必须从它的 Chrome 应用商店（需要翻墙）安装，其它任何网站下载的都无法直接安装，所以可以把<code>crx</code>文件解压，然后通过开发者模式直接加载。</p><p>然后将写好的 Chrome 插件文件夹拖入到刚刚打开的插件管理页面即可。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="chrome-插件知识">Chrome 插件知识<a class="hash-link" href="#chrome-插件知识" title="标题的直接链接">​</a></h2><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="manifestjson">manifest.json<a class="hash-link" href="#manifestjson" title="标题的直接链接">​</a></h3><p>是<code>manifest.json</code>切记不要英文单词打错字，一定要有这个文件，且需要放在根目录上，否则就会出现未能成功加载扩展程序的错误。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="backgroundhtml-和-backgroundjs">background.html 和 background.js<a class="hash-link" href="#backgroundhtml-和-backgroundjs" title="标题的直接链接">​</a></h3><p>可以理解为后台，同时这个页面会一直常驻在浏览器中，而主要 background 权限非常高，几乎可以调用所有的 Chrome 扩展 API（除了 devtools），基本很多操作都是放在 background 执行，返回给 content，而且它可以<strong>无限制跨域</strong>，也就是可以跨域访问任何网站而无需要求对方设置<code>CORS</code>。这对我们后面要在 content 中发送跨域请求至关重要！</p><p>我习惯的做法是通过<code>”page”："background.html"</code>来导入<code>background.js</code>或其他 js 代码，如下</p><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)">// manifest.json</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"> </span><span class="token property">"background"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token property">"page"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"background.html"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><div class="language-html codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-html codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)">&lt;!-- background.html --&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token doctype punctuation" style="color:rgb(4, 81, 165)">&lt;!</span><span class="token doctype doctype-tag">DOCTYPE</span><span class="token doctype"> </span><span class="token doctype name">html</span><span class="token doctype punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">html</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">head</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">title</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain">背景页</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">title</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">meta</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">charset</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">utf-8</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">/&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">meta</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">http-equiv</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">Content-Type</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">content</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">text/html; charset=utf-8</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">/&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">head</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">body</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">script</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">type</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">text/javascript</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">src</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">js/jquery.js</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token script"></span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">script</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">script</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">type</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">text/javascript</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">src</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">js/background.js</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token script"></span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">script</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">body</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">html</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>如果是 scripts 方式导入 js 文件则需要反复修改<code>manifest.json</code>文件。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="关于乱码">关于乱码<a class="hash-link" href="#关于乱码" title="标题的直接链接">​</a></h4><p>有时候你在编写代码中出现了中文可能会出现了如下的乱码，</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20200923214834081.png" alt="image-20200923214834081" class="img_ev3q"></p><p>我遇到的原因是就是我原先的<code>background.html</code>代码写成如下的情况</p><div class="language-html codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-html codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">script</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">type</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">text/javascript</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">src</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">js/jquery.js</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token script"></span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">script</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">script</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">type</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">text/javascript</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">src</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">js/background.js</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token script"></span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">script</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>没错，就只写了这两个行，就出现乱码（将 UTF-8 的编码变为了 windows1252），而只需要把 background.html 代码修改成正常的 HTML 结构，也就是上上面的那个代码即可解决该乱码情况。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="contentjs">content.js<a class="hash-link" href="#contentjs" title="标题的直接链接">​</a></h3><p>我们主要的向页面注入脚本就依靠这个文件，相当于给页面添加了一个 js 文件，但是<code>content</code>和原始页面<strong>共享 DOM</strong>，但是不共享 JS，如要<strong>访问页面 JS（例如某个 JS 变量）</strong>，只能通过<code>injected js</code>来实现（后文会提到）。并且<code>content</code>不能访问绝大部分<code>chrome.xxx.api</code>，除了下面这 4 种：</p><ul><li>chrome.extension(getURL , inIncognitoContext , lastError , onRequest , sendRequest)</li><li>chrome.i18n</li><li>chrome.runtime(connect , getManifest , getURL , id , onConnect , onMessage , sendMessage)</li><li>chrome.storage</li></ul><p>这些 API 绝大部分时候都够用了，非要调用其它 API 的话，你还可以通过通信来实现让 background 来帮你调用。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="injectjs">inject.js<a class="hash-link" href="#injectjs" title="标题的直接链接">​</a></h3><p>上文也说到了<code>content</code>是<strong>无法访问页面中的 JS</strong>，可以操作 DOM，但是 DOM 却不能调用它，也就是无法在 DOM 中通过绑定事件的方式调用<code>content</code>中的代码（包括直接写<code>onclick</code>和<code>addEventListener</code>2 种方式都不行），但是，<strong>在页面上添加一个按钮并调用插件的扩展 API</strong>是一个很常见的需求，那该怎么办呢？这时候就需要注入 inject.js 这个文件</p><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token dom variable" style="color:rgb(9, 134, 88)">document</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">addEventListener</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'DOMContentLoaded'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">injectCustomJs</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// 向页面注入JS</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">injectCustomJs</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">jsPath</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  jsPath </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> jsPath </span><span class="token operator" style="color:rgb(0, 0, 0)">||</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'js/inject.js'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">var</span><span class="token plain"> temp </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token dom variable" style="color:rgb(9, 134, 88)">document</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">createElement</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'script'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  temp</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">setAttribute</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'type'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'text/javascript'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token comment" style="color:rgb(0, 128, 0)">// 获得的地址类似：chrome-extension://ihcokhadfjfchaeagdoclpnjdiokfakg/js/inject.js</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  temp</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">src</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> chrome</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">extension</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">getURL</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">jsPath</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  temp</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method-variable function-variable method function property-access" style="color:rgb(0, 0, 255)">onload</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">// 放在页面不好看，执行完后移除掉</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">parentNode</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">removeChild</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token dom variable" style="color:rgb(9, 134, 88)">document</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">head</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">appendChild</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">temp</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>还没有完，因为注入有权限，所以需要在 manifest.json 声明一下这个文件。也就是下面的这行代码</p><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">// 普通页面能够直接访问的插件资源列表，如果不设置是无法直接访问的</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token string-property property">"web_accessible_resources"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">"js/inject.js"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>这样你就能调用</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="关于消息通信">关于消息通信<a class="hash-link" href="#关于消息通信" title="标题的直接链接">​</a></h3><p>Chrome 插件主要就 4 个部分组成，injected，content，popup，background，但这 4 个部分所对应的权限，应用都有可能各自不一，这时候就需要通过消息通信，将对应的数据发送到对应的文件，主要也就如下四种通信方式：</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="popup-和-background">popup 和 background<a class="hash-link" href="#popup-和-background" title="标题的直接链接">​</a></h4><p>popup 可以直接调用 background 中的 JS 方法，也可以直接访问 background 的 DOM：</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)">// background.js</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">test</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">alert</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'我是background！'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// popup.js</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">var</span><span class="token plain"> bg </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> chrome</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">extension</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">getBackgroundPage</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">bg</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">test</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 访问bg的函数</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token function" style="color:rgb(0, 0, 255)">alert</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">bg</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">document</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">body</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">innerHTML</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token comment" style="color:rgb(0, 128, 0)">// 访问bg的DOM</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p><code>background</code>访问<code>popup</code>如下（前提是<code>popup</code>已经打开）：</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">var</span><span class="token plain"> views </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> chrome</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">extension</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">getViews</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">type</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'popup'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">views</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">length</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">views</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">location</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">href</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="popup-或-bg-与-content">popup 或 bg 与 content<a class="hash-link" href="#popup-或-bg-与-content" title="标题的直接链接">​</a></h4><h5 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="popup-或-bg-向-content-发送请求">popup 或 bg 向 content 发送请求<a class="hash-link" href="#popup-或-bg-向-content-发送请求" title="标题的直接链接">​</a></h5><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)">//background.js或popup.js：</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">sendMessageToContentScript</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">message</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> callback</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  chrome</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">tabs</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">query</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">active</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">currentWindow</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">tabs</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    chrome</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">tabs</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">sendMessage</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">tabs</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> message</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">response</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">callback</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">callback</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">response</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token function" style="color:rgb(0, 0, 255)">sendMessageToContentScript</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">cmd</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'test'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">value</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'你好，我是popup！'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">response</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'来自content的回复：'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> response</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p><code>content.js</code>通过监听事件接收：</p><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">chrome</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">runtime</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">onMessage</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">addListener</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">request</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> sender</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> sendResponse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token comment" style="color:rgb(0, 128, 0)">// console.log(sender.tab ?"from a content script:" + sender.tab.url :"from the extension");</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">request</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">cmd</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'test'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">alert</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">request</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">value</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">sendResponse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'我收到了你的消息！'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h5 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="content-向-popup-或-bg">content 向 popup 或 bg<a class="hash-link" href="#content-向-popup-或-bg" title="标题的直接链接">​</a></h5><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)">// content.js</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">chrome</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">runtime</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">sendMessage</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">greeting</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'你好，我是content呀，我主动发消息给后台！'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">response</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'收到来自后台的回复：'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> response</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)">//background.js 或 popup.js：</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">// 监听来自content的消息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">chrome</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">runtime</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">onMessage</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">addListener</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">request</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> sender</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> sendResponse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'收到来自content的消息：'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">request</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> sender</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> sendResponse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">sendResponse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'我是后台，我已收到你的消息：'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> </span><span class="token known-class-name class-name" style="color:rgb(38, 127, 153)">JSON</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">stringify</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">request</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>注意：</p><ul><li>content_scripts 向<code>popup</code>主动发消息的前提是 popup 必须打开！否则需要利用 background 作中转；</li><li>如果 background 和 popup 同时监听，那么它们都可以同时收到消息，但是只有一个可以 sendResponse，一个先发送了，那么另外一个再发送就无效；</li></ul><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="injected-和-content">injected 和 content<a class="hash-link" href="#injected-和-content" title="标题的直接链接">​</a></h4><p>主要就是<code>injected</code>向<code>content</code>发送，<code>injected</code>无需监听。</p><p><code>content</code>和页面内的脚本（<code>injected</code>自然也属于页面内的脚本）之间唯一共享的东西就是页面的 DOM 元素，有 2 种方法可以实现二者通讯，：</p><ol><li>可以通过<code>window.postMessage</code>和<code>window.addEventListener</code>来实现二者消息通讯；（推荐）</li><li>通过自定义 DOM 事件来实现（我就懒得写了，没怎么用到）；</li></ol><p><code>injected</code>中：</p><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token dom variable" style="color:rgb(9, 134, 88)">window</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">postMessage</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">test</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'你好！'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'*'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p><code>content script中</code>：</p><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token dom variable" style="color:rgb(9, 134, 88)">window</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">addEventListener</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token string" style="color:rgb(163, 21, 21)">'message'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">e</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">e</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="injected-与-popup">injected 与 popup<a class="hash-link" href="#injected-与-popup" title="标题的直接链接">​</a></h4><p><code>injected</code>无法直接和<code>popup</code>通信，必须借助<code>content</code>作为中间人。不过一般这种都少，直接和 bg 通信即可。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="我的模板">我的模板<a class="hash-link" href="#我的模板" title="标题的直接链接">​</a></h2><p>关于 Chrome 的主要内容也就这些，实际开发如果有个模板就能大大方便开发，在原文章中该作者已经分享了有对应的源代码，这里放上我自写的 Chrome 模板编写过程。</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20210820004414785.png" alt="image-20210820004414785" class="img_ev3q"></p><p>当然，这里需要提几点地方：</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="配置项与-storage">配置项与 storage<a class="hash-link" href="#配置项与-storage" title="标题的直接链接">​</a></h3><p>首先是配置方面，有时候插件的内的选项是要记录，以便下一次在启动插件的时候还是上一次的配置。先看代码</p><div class="language-html codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-html codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)">&lt;!-- popup.js --&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">div</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">class</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">config-item</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">input</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">type</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">checkbox</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">id</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">config1</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">class</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">box configs</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">/&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">label</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">class</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">hand</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">for</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">config1</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">title</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">配置1</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain">配置1</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">label</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">div</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">div</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">class</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">config-item</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">input</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">type</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">checkbox</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">id</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">config2</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">class</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">box configs</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">/&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;</span><span class="token tag" style="color:rgb(128, 0, 0)">label</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">class</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">hand</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">for</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">config2</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag" style="color:rgb(128, 0, 0)"> </span><span class="token tag attr-name" style="color:rgb(255, 0, 0)">title</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(4, 81, 165)">=</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag attr-value" style="color:rgb(128, 0, 0)">配置2</span><span class="token tag attr-value punctuation" style="color:rgb(4, 81, 165)">"</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain">配置2</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">label</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&lt;/</span><span class="token tag" style="color:rgb(128, 0, 0)">div</span><span class="token tag punctuation" style="color:rgb(4, 81, 165)">&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)">// popup.js</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token function" style="color:rgb(0, 0, 255)">$</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> configs </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token dom variable" style="color:rgb(9, 134, 88)">document</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">getElementsByClassName</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'configs'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">for</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> i </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"> i </span><span class="token operator" style="color:rgb(0, 0, 0)">&lt;</span><span class="token plain"> configs</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">length</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"> i</span><span class="token operator" style="color:rgb(0, 0, 0)">++</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> type </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> configs</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">type</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">type </span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'checkbox'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      configs</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method-variable function-variable method function property-access" style="color:rgb(0, 0, 255)">onchange</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        chrome</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">storage</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">sync</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">set</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">checked</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      chrome</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">storage</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">sync</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">get</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">configs</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">items</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        configs</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">checked</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> items</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">configs</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">||</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">else</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">type </span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'text'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">||</span><span class="token plain"> type </span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'password'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      configs</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method-variable function-variable method function property-access" style="color:rgb(0, 0, 255)">onblur</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        chrome</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">storage</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">sync</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">set</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">value</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      chrome</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">storage</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">sync</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">get</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">configs</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">items</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        configs</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">value</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> items</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">configs</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">id</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">||</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">''</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>可能需要多花点时间才能理解上面代码的意思，首先我在需要记录配置的地方添加了一个类<code>configs</code>，然后通过 js 代码遍历类名为<code>configs</code>，接着判断是多选框，还是输入框，input 的 id 为键名，value 为键值，来 set 或 get <code>chrome.storage</code>的值，然后进行事件绑定为修改配置后在记录一下配置。这里需要注意一下，写配置的时候<code>{ [this.id]: this.value }</code>这里的<code>this.id</code>是加了中括号的，原因就是这个 this.id 是变量，如果不加的话默认为字符串，但在这里有.所以是会报错的。</p><p>强烈不建议用 localStorage，我当初第一遍学的时候没学明白，我还通过消息通信将配置信息发给<code>content</code>，然后还用 localStorage 记录一遍，现在才发现<code>chrome.storage</code>是针对插件全局的，即使你在<code>background</code>或者<code>popup中</code>保存的数据，在<code>content</code>也能获取到。</p><p>当然这种读写配置的也算麻烦了，不像桌面级开发的读写配置。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="悬浮窗">悬浮窗<a class="hash-link" href="#悬浮窗" title="标题的直接链接">​</a></h3><p>首先，一般对于网页端的插件，能提供的页面最好方式就是悬浮窗了，这里我也是通过 DOM 创建元素生成对象。而这个悬浮窗是针对页面的，而不是像 popup 那样。相关的页面初始化代码如下，</p><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">var</span><span class="token plain"> view </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">show</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">cache</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">count</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">type</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">mouse_x</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token literal-property property">mouse_y</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">initView</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  view</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">float</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">$</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token template-string string" style="color:rgb(163, 21, 21)"></span><br></span><span class="token-line" style="color:#000000"><span class="token template-string string" style="color:rgb(163, 21, 21)">    &lt;div id="box"</span><br></span><span class="token-line" style="color:#000000"><span class="token template-string string" style="color:rgb(163, 21, 21)">style="position: fixed;border: 1px double rgb(0,0,0); width: 300px; top: 30px; right: 1%; z-index: 999999; font-size: 15px; background-color: rgb(255,255,255); color: #000000;user-select:none;"&gt;</span><br></span><span class="token-line" style="color:#000000"><span class="token template-string string" style="color:rgb(163, 21, 21)">&lt;div style="position: relative;"&gt;</span><br></span><span class="token-line" style="color:#000000"><span class="token template-string string" style="color:rgb(163, 21, 21)">    &lt;button name="show"</span><br></span><span class="token-line" style="color:#000000"><span class="token template-string string" style="color:rgb(163, 21, 21)">        style="position: absolute;top: 50%;right:1%; margin-top: 7px; line-height: 18px;overflow:hidden;border: 0px double rgb(0,0,0);cursor:pointer;font-size: 18px;background-color: rgb(255,255,255);"&gt;－</span><br></span><span class="token-line" style="color:#000000"><span class="token template-string string" style="color:rgb(163, 21, 21)">    &lt;/button&gt;</span><br></span><span class="token-line" style="color:#000000"><span class="token template-string string" style="color:rgb(163, 21, 21)">&lt;/div&gt;</span><br></span><span class="token-line" style="color:#000000"><span class="token template-string string" style="color:rgb(163, 21, 21)">&lt;div id="kz_title" style="height: auto; margin: 5px; font-size: 16px;"&gt;日志&lt;/div&gt;</span><br></span><span class="token-line" style="color:#000000"><span class="token template-string string" style="display:inline-block;color:rgb(163, 21, 21)"></span><br></span><span class="token-line" style="color:#000000"><span class="token template-string string" style="color:rgb(163, 21, 21)">&lt;div id="kz_main"&gt;</span><br></span><span class="token-line" style="color:#000000"><span class="token template-string string" style="color:rgb(163, 21, 21)">    &lt;hr&gt;</span><br></span><span class="token-line" style="color:#000000"><span class="token template-string string" style="color:rgb(163, 21, 21)">    &lt;form&gt;</span><br></span><span class="token-line" style="color:#000000"><span class="token template-string string" style="color:rgb(163, 21, 21)">        &lt;div style="margin-top: 5px;overflow-y: auto;"&gt;</span><br></span><span class="token-line" style="color:#000000"><span class="token template-string string" style="color:rgb(163, 21, 21)">            &lt;button id="kz_id1" name="cleanlog"</span><br></span><span class="token-line" style="color:#000000"><span class="token template-string string" style="color:rgb(163, 21, 21)">                style="margin-left: 10px;float:left;border-radius:0em;overflow:hidden;border: 1px double rgb(0,0,0);background-color: rgb(255,255,255);"&gt;功能按钮&lt;/button&gt;</span><br></span><span class="token-line" style="color:#000000"><span class="token template-string string" style="color:rgb(163, 21, 21)">            &lt;button id="kz_id2" name="cleanlog"</span><br></span><span class="token-line" style="color:#000000"><span class="token template-string string" style="color:rgb(163, 21, 21)">                style="margin-left: 10px;float:left;border-radius:0em;overflow:hidden;border: 1px double rgb(0,0,0);background-color: rgb(255,255,255);"&gt;功能按钮&lt;/button&gt;</span><br></span><span class="token-line" style="color:#000000"><span class="token template-string string" style="color:rgb(163, 21, 21)">        &lt;/div&gt;</span><br></span><span class="token-line" style="color:#000000"><span class="token template-string string" style="color:rgb(163, 21, 21)">    &lt;/form&gt;&lt;br&gt;</span><br></span><span class="token-line" style="color:#000000"><span class="token template-string string" style="color:rgb(163, 21, 21)">    &lt;div id="logList"&gt;&lt;/div&gt;</span><br></span><span class="token-line" style="color:#000000"><span class="token template-string string" style="color:rgb(163, 21, 21)">&lt;/div&gt;</span><br></span><span class="token-line" style="color:#000000"><span class="token template-string string" style="color:rgb(163, 21, 21)">&lt;/div&gt;</span><br></span><span class="token-line" style="color:#000000"><span class="token template-string string" style="color:rgb(163, 21, 21)">    </span><span class="token template-string template-punctuation string" style="color:rgb(163, 21, 21)">`</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  view</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">info</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> view</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">float</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">find</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'#info'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  view</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">kz_title</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> view</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">float</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">find</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'#kz_title'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  view</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">kz_main</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> view</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">float</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">find</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'#kz_main'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  view</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">float</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">appendTo</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'body'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">delegate</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'button'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'click'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">e</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    e</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">stopImmediatePropagation</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    e</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">stopPropagation</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    e</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">preventDefault</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> name </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">$</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">attr</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'name'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">name </span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'show'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token function" style="color:rgb(0, 0, 255)">$</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">html</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">view</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">show</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">?</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'＋'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'－'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      view</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">show</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">!</span><span class="token plain">view</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">show</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      view</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">kz_main</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">slideToggle</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">addViewMouseListener</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'日志输出1'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'日志输出2'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'日志输出3'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">addViewMouseListener</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  view</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">float</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">bind</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'mousedown'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">event</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    view</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">cache</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">x</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">$</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">position</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">left</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    view</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">cache</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">y</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">$</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">this</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">position</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">top</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    view</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">cache</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">mouse_x</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">originalEvent</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">clientX</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    view</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">cache</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">mouse_y</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">originalEvent</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">clientY</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">//console.log(view.cache.mouse_x, view.cache.mouse_y, view.cache.x, view.cache.y)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">$</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token dom variable" style="color:rgb(9, 134, 88)">document</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">bind</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'mousemove'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">event</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">//计算出现在的位置是多少</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">view</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">cache</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">mouse_x</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">view</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">cache</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">mouse_y</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain"> view</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">cache</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">y</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token plain"> view</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">kz_title</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">height</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">return</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> new_position_left </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">originalEvent</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">clientX</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain"> view</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">cache</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">mouse_x</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> view</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">cache</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">x</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      new_position_top </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">originalEvent</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">clientY</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain"> view</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">cache</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">mouse_y</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> view</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">cache</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">y</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">//加上边界限制</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">new_position_top </span><span class="token operator" style="color:rgb(0, 0, 0)">&lt;</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token comment" style="color:rgb(0, 128, 0)">//当上边的偏移量小于0的时候，就是上边的临界点，就让新的位置为0</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      new_position_top </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">//如果向下的偏移量大于文档对象的高度减去自身的高度，就让它等于这个高度</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">new_position_top </span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">$</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token dom variable" style="color:rgb(9, 134, 88)">document</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">height</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain"> view</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">float</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">height</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">&amp;&amp;</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">$</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token dom variable" style="color:rgb(9, 134, 88)">document</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">height</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain"> view</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">float</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">height</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      new_position_top </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">$</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token dom variable" style="color:rgb(9, 134, 88)">document</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">height</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain"> view</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">float</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">height</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token comment" style="color:rgb(0, 128, 0)">//右限制</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">new_position_left </span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">$</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token dom variable" style="color:rgb(9, 134, 88)">document</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">width</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain"> view</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">float</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">width</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      new_position_left </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">$</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token dom variable" style="color:rgb(9, 134, 88)">document</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">width</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain"> view</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">float</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">width</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">new_position_left </span><span class="token operator" style="color:rgb(0, 0, 0)">&lt;</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token comment" style="color:rgb(0, 128, 0)">//左边的偏移量小于0的时候设置 左边的位置为0</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      new_position_left </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    view</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">float</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">css</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">left</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> new_position_left </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'px'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">top</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> new_position_top </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'px'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">$</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token dom variable" style="color:rgb(9, 134, 88)">document</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">bind</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'mouseup'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">event</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    view</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">cache</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">mouse_x</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    view</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">cache</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">mouse_y</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">msg</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> color</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> date </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(38, 127, 153)">Date</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> t </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> date</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">getHours</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">':'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> date</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">getMinutes</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">':'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> date</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">getSeconds</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  msg </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> t </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'  '</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> msg</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> div </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">$</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'&lt;div class="log"&gt;&lt;/div&gt;'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">css</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token string-property property">'border-color'</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'rgba(121, 187, 255, 0.2)'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string-property property">'background-color'</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'rgba(121, 187, 255, 0.2)'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> log </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">$</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'&lt;p&gt;&lt;span style="color: '</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">color </span><span class="token operator" style="color:rgb(0, 0, 0)">||</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'#409EFF'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'"&gt;'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> msg </span><span class="token operator" style="color:rgb(0, 0, 0)">+</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'&lt;/span&gt;&lt;/p&gt;'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token function" style="color:rgb(0, 0, 255)">$</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'.log'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">length</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">&gt;</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">15</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">for</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">let</span><span class="token plain"> i </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">0</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">$</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'.log'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">length</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">15</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"> i</span><span class="token operator" style="color:rgb(0, 0, 0)">++</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token function" style="color:rgb(0, 0, 255)">$</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'.log'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">remove</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token function" style="color:rgb(0, 0, 255)">$</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'#logList'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">append</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">div</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">append</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>然后在 content.js 内容的对页面 url 判断是否需要初始化悬浮窗即可</p><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token dom variable" style="color:rgb(9, 134, 88)">document</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">addEventListener</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'DOMContentLoaded'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token dom variable" style="color:rgb(9, 134, 88)">location</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">host</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">indexOf</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">'chaoxing'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">!=</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">-</span><span class="token number" style="color:rgb(9, 134, 88)">1</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token function" style="color:rgb(0, 0, 255)">initView</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>如何发挥就看各位了。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="跨域请求">跨域请求<a class="hash-link" href="#跨域请求" title="标题的直接链接">​</a></h3><p>关于跨域请求，我当初在学习 Chrome 插件的时候，就是卡在了跨域这个地方，那时候前端学的浅，对跨域都不知道处理，然后放弃学习了 Chrome 插件一段时间，后来有时间了，想在补一补之前没写完的 Chrome 扩展搞完。然而跨域请求非常简单，而我那时候之所以卡住就是因为没好好看文档，搞不定的地方就多看几遍说不准就搞定了。</p><p>首先要使 Chrome 插件访问跨域资源，需要在 manifest.json 文件中声明要访问的域如下：</p><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"permissions"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">"http://www.google.com/"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"http://*.google.com/"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"https://*.google.com/"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"http://*/"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>建议直接直接暴力点写上</p><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">"permissions"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token string" style="color:rgb(163, 21, 21)">"http://*/*"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"https://*/*"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>然后封装一下对应的 ajax 请求，因为在 content 内进行 ajax 请求，是会在控制台输出跨域请求拦截，或者是 HTTPS 访问 HTTP 不安全等问题，这时候就需要通过消息通信，将 content 要发送的请求发送给 bg，让 bg 请求，然后等 bg 请求完毕，再将数据返回到 content 即可。下面是我对应的封装代码</p><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)">// background.js</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">chrome</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">runtime</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">onMessage</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">addListener</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">req</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> sender</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> sendResponse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">req</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> sender</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> sendResponse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(0, 0, 255)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">req</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">cmd</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">==</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'ajax'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    $</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">ajax</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">url</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> req</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">url</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">type</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> req</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">type</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">data</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> req</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">data</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token literal-property property">async</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token function-variable function" style="color:rgb(0, 0, 255)">success</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token function" style="color:rgb(0, 0, 255)">sendResponse</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">res</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token comment" style="color:rgb(0, 128, 0)">// content.js</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(0, 0, 255)">sendAjaxToBg</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">url</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> type</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> data</span><span class="token parameter punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token parameter"> callback</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  chrome</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">runtime</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">sendMessage</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"> </span><span class="token literal-property property">cmd</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'ajax'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">url</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> url</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">type</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> type</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token literal-property property">data</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> data </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">response</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token function" style="color:rgb(0, 0, 255)">callback</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">response</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>这里的话我通信发送的是 js 对象，其中 cmd 决定了我要的操作，后台通过判断 cmd 来执行对应的操作。比较不好理解的是回调函数，由于 JS 自身语言的因素与浏览器的问题，很多事件都是先挂着，后做完在回调，所以我这里就封装成这种形式，例如</p><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token function" style="color:rgb(0, 0, 255)">sendAjaxToBg</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">"http://..."</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"GET"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token keyword null nil" style="color:rgb(0, 0, 255)">null</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">function</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token parameter">response</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token console class-name" style="color:rgb(38, 127, 153)">console</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">log</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token plain">response</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token spread operator" style="color:rgb(0, 0, 0)">...</span><span class="token plain">code</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>这只是一个简单的 http 封装发送，如果要更复杂的话还可以添加协议头和 cookies，这里就不在补充了。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="一些自写-chrome-插件">一些自写 Chrome 插件<a class="hash-link" href="#一些自写-chrome-插件" title="标题的直接链接">​</a></h3><p>实际上已经写过一些 Chrome 插件了，奈何写的比较烂或没搞完，也就暂时先不发，有时间会再整理一下自己所写的。</p><p>一个验证码识别，有时候在登录的时候需要输入验证码是件非常痛苦的事情。于是乎我就通过调用打码 Api 接口写了个自动识别验证码并填写的。也提供了非常方便的右键识别验证码的功能。具体效果如图（实际上还是得第一次先确认要识别的图片框与输入框，下次加载的时候需要手动点击验证码才会自动生效，还是不够智能的，不过成就感十足）</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20210820001938051.png" alt="image-20210820001938051" class="img_ev3q"></p><p><img loading="lazy" src="https://img.kuizuo.cn/wydm.gif" alt="wydm" class="img_ev3q"></p><p>另一个是基于某布大佬的 WebHook 工具，所更改的，不过一直停滞着，有空将其完善一下。</p>]]></content:encoded>
            <category>chrome</category>
            <category>plugin</category>
            <category>develop</category>
        </item>
        <item>
            <title><![CDATA[第一个博客搭建之Vuepress]]></title>
            <link>https://kuizuo.cn/first-blog-is-vuepress</link>
            <guid>first-blog-is-vuepress</guid>
            <pubDate>Sun, 30 Aug 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[感谢 vuepress-theme-reco主题与一篇博客使用文章使用 vuepress 构建个人博客]]></description>
            <content:encoded><![CDATA[<p>感谢 <a href="https://vuepress-theme-reco.recoluan.com/" target="_blank" rel="noopener noreferrer">vuepress-theme-reco</a>主题与一篇博客使用文章<a href="https://lookroot.cn/views/article/vuepress.html#reco%E4%B8%BB%E9%A2%98" target="_blank" rel="noopener noreferrer">使用 vuepress 构建个人博客</a></p><p>在写这篇文章前，本人非前端专业人士，只是一时兴起想开始搭建一个博客，在该博客上记录与分享一下自己所学的一切内容。（然后现在都在往前端这方向走了😂）</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="补充">补充<a class="hash-link" href="#补充" title="标题的直接链接">​</a></h2><p>不打算破坏之前所写的一些内容，将一些补充的内容写在开头，目前访问 kzcode.cn 依旧能访问到该站，不过文章都保留原有未变动，图片都是直接跟随 MD 文档下，加上服务器又比较拉，所以访问会稍带卡顿。这篇合理来说也算我的第一篇博客，所以还是有必要记录一下的。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="为什么写博客">为什么写博客<a class="hash-link" href="#为什么写博客" title="标题的直接链接">​</a></h2><p>在接触软件行业的这一年里，也学到了很多很多很多的知识，也让我感受到代码的魅力与强大。在这学习过程中，百度到了各种相关学习文章，而这些正式前辈们所分享的学习经历，倘若没有这些，我可能早已停下学习的步伐。一时兴起，萌生了搭建博客的想法，然后开始搜索搭建博客的知识，于是乎就有了这篇文章。</p><p>写博客是为了记录自己，记录自己学习中的过程，知识，遇到的坑，写成一篇文章，也许过了几个月后的自己脑子不好使，忘记是如何解决的，回过头来看，瞬间焕然大悟。同时也能巩固自己所学的，在如今这个时代，技术更新换代是真的快，而要求学的东西也就越来越多。有时候学过的一项技术，过了几个月真的说忘就忘，不时常记录一下当初写的笔记，翻看之前写过的代码，那真的就和重新学习没什么两样了。</p><p>在此期间曾遇到许多坑，而解决最好的办法就是百度。在百度搜索过程中看到了许许多多的学习者分享自己那时候与我遇到一样的问题，说明他是如何解决的，并写文章。有时运气好可能他的解决办法同样也是我的解决办法，但往往总是不尽人意，这时需要再看下一个相关搜索或者下下个才能解决我的问题，这在学习过程中是必不可少的一个环节。而他们所分享的内容，就是一篇篇的博客。正是这一篇篇博客解惑学习者学习中的问题，让他们有自信再去学习下去！</p><p>于是就萌生的一种想法，利用自己所学的 Web 知识开始搭建属于自己的个人博客，分享自己所遇到的坑，希望能解决遇到同样问题的人。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="初步搭建博客界面">初步搭建博客界面<a class="hash-link" href="#初步搭建博客界面" title="标题的直接链接">​</a></h3><p>要展示给别人看，就必须得搞前端 UI 界面，同时为了快速开发，我又百度了相关的前端 UI 框架，其中决定用 layui，界面风格布局可以接受，于是乎在搜索用过 layui 框架搭建的个人博客，成功找到一篇博主<a href="https://www.yanshisan.cn/" target="_blank" rel="noopener noreferrer">燕十三一个人的江湖</a>分享的模板源码，然后开始大改，最终花了几个小时修改了大致页面</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20200901012343086.png" alt="image-20200901012343086" class="img_ev3q"></p><p>然后问题来了，前端大致界面设计好了，我最关心的文章要怎么写。。。而这份源码是没有给后端这些的（此时的我刚入前端，后端毛也不会），就一个纯前端页面，连文章模板都没有，可能是真的没什么可整理的，于是就放弃了自己手动搭建，主要还是那时候太菜了。</p><p>就在想用纯静态页面，还是用动态页面，对于动态页面获取文章数据的技能并不熟练。然后发现这种想法并不行，还是得借助外界提供现有的博客系统来写，于是乎停滞了一段时间，去搜索一系列相关的博客系统（合理来说应该是静态文件生成器），如 Hexo 或 WordPress，不过为啥选择 vuepress，因为我那时候正好在学 Vue，于是乎又开始新的一番折腾。不过也好，如果以后写技术文档，vuepress 也是一个非常推荐的选择。后续的话可能会去接触一下 Hexo 的 butterfly 主题，希望学到点东西，能给自己的博客在增添几份美感。</p><p>我所用的主题是<a href="https://vuepress-theme-reco.recoluan.com/" target="_blank" rel="noopener noreferrer">vuepress-theme-reco</a> 也非常推荐用这个主题来写博客，下面会简单介绍这款主题</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="reco-主题">reco 主题<a class="hash-link" href="#reco-主题" title="标题的直接链接">​</a></h2><blockquote><p>一款简洁而优雅的 vuepress 博客 &amp; 文档 主题。官方文档<a href="https://vuepress-theme-reco.recoluan.com/" target="_blank" rel="noopener noreferrer">立即前往</a></p></blockquote><p><img loading="lazy" src="https://img.kuizuo.cn/152702-539475.png" alt="image-20200515152702435" class="img_ev3q"></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="安装"><strong>安装</strong><a class="hash-link" href="#安装" title="标题的直接链接">​</a></h3><div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">#全局安装vuepress-reco</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">npm install @vuepress-reco/theme-cli -g</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"># 初始化 (blog改成你要的文件名)  然后填写项目标题等等</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">theme-cli init blog</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"># 进入项目目录</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">cd blog</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">#安装依赖包</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">npm install</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"># 运行</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">npm run dev</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"># 编译</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">npm run build</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>执行完<code>npm run dev</code>运行后，点击控制台的对应地址 你就能看到</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20200901191643031.png" alt="image-20200901191643031" class="img_ev3q"></p><p>当然，可能标题和一些会不一样，因为我更改了两处地方一处是<code>blog</code>下的<code>README.md</code>文件，文件结构如下</p><div class="language-markdown codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-markdown codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token hr punctuation" style="color:rgb(4, 81, 165)">---</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">home: true</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">heroText: 愧怍的个人空间</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">tagline: 我是愧怍,沉迷于代码无法自拔</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">...</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>这个是决定首页的样式，具体要什么背景，内容就因人而异。</p><p>另一处是<code>.vuepress\config.js</code>里的内容，内容有点多，我依次来讲</p><p>首先是开头几行的，title 决定你网站的标题，description 则是一开始出场界面的描述</p><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">module</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token property-access">exports</span><span class="token plain"> </span><span class="token operator" style="color:rgb(0, 0, 0)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line theme-code-block-highlighted-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">title</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'愧怍的小站'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line theme-code-block-highlighted-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">description</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">'如果代码都解决不了的话,那可能真的解决不了'</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>随后你要关注的就是 themeConfig 下的 author，也就是作者名，改成你的名字就行</p><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line theme-code-block-highlighted-line" style="color:#000000"><span class="token plain">    </span><span class="token string-property property">"logo"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"/logo.png"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token string-property property">"search"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token string-property property">"searchMaxSuggestions"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">10</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token string-property property">"lastUpdated"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Last Updated"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line theme-code-block-highlighted-line" style="color:#000000"><span class="token plain">    </span><span class="token string-property property">"author"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"愧怍"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line theme-code-block-highlighted-line" style="color:#000000"><span class="token plain">    </span><span class="token string-property property">"authorAvatar"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"/logo.png"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token string-property property">"record"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"xxxx"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token string-property property">"startYear"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"2017"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>其余的一些，比如<code>logo.png</code>与<code>avatar.png</code>啊，你换成你的想要的头像就行，他们都存放在.<code>vuepress\public</code>下,然后就是修改标题栏，他们都放在<code>themeConfig</code>下的<code>nav</code>里，这里你想修改哪个导航栏，就改哪个导航栏与标题，文末我会放上我的全部代码。</p><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token string-property property">"themeConfig"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token string-property property">"nav"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token string-property property">"text"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Home"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token string-property property">"link"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"/"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token string-property property">"icon"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"reco-home"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token string-property property">"text"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"TimeLine"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token string-property property">"link"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"/timeline/"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token string-property property">"icon"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"reco-date"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token string-property property">"text"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Docs"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token string-property property">"icon"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"reco-message"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token string-property property">"items"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token string-property property">"text"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"vuepress-reco"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token string-property property">"link"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"/docs/theme-reco/"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token string-property property">"text"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Contact"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token string-property property">"icon"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"reco-message"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token string-property property">"items"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token string-property property">"text"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"GitHub"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token string-property property">"link"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"https://github.com/recoluan"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">            </span><span class="token string-property property">"icon"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"reco-github"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">]</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>还有一个是主题自带的导航栏配置，这里你只需要更改 text 与 location 即可，其余不建议更改，你到时候写的文章都在依靠这两个</p><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token string-property property">"blogConfig"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token string-property property">"category"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token string-property property">"location"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">2</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token string-property property">"text"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Category"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token string-property property">"tag"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token string-property property">"location"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(9, 134, 88)">3</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">        </span><span class="token string-property property">"text"</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(163, 21, 21)">"Tag"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>zhuyi 你每次修改修改 config 的内容，就需要重新<code>npm run dev</code> vuepress 不支持热更新，也就是文件内容给修改了你需要重新编译运行，这是初学接触会遇到的坑。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="编写文章">编写文章<a class="hash-link" href="#编写文章" title="标题的直接链接">​</a></h3><p>现在有了一个页面风格不错，同时还是响应式页面，就差文章了。这时候你就需要了解 vuepress 的<a href="https://vuepress.vuejs.org/zh/guide/markdown.html#front-matter" target="_blank" rel="noopener noreferrer">Markdown 拓展</a>，我这里简单叙述一下，你该怎么写文章，下面是你要写文章的模板，你只需要关注几个内容就行了，</p><div class="language-markdown codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-markdown codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token front-matter-block punctuation" style="color:rgb(4, 81, 165)">---</span><span class="token front-matter-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token front-matter-block"></span><span class="token front-matter-block front-matter yaml language-yaml key atrule">title</span><span class="token front-matter-block front-matter yaml language-yaml punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token front-matter-block front-matter yaml language-yaml"> 笔记模板</span><br></span><span class="token-line" style="color:#000000"><span class="token front-matter-block front-matter yaml language-yaml"></span><span class="token front-matter-block front-matter yaml language-yaml key atrule">date</span><span class="token front-matter-block front-matter yaml language-yaml punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token front-matter-block front-matter yaml language-yaml"> </span><span class="token front-matter-block front-matter yaml language-yaml datetime number" style="color:rgb(9, 134, 88)">2020-08-21</span><span class="token front-matter-block front-matter yaml language-yaml"></span><br></span><span class="token-line" style="color:#000000"><span class="token front-matter-block front-matter yaml language-yaml"></span><span class="token front-matter-block front-matter yaml language-yaml key atrule">tags</span><span class="token front-matter-block front-matter yaml language-yaml punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token front-matter-block front-matter yaml language-yaml"></span><br></span><span class="token-line" style="color:#000000"><span class="token front-matter-block front-matter yaml language-yaml">  </span><span class="token front-matter-block front-matter yaml language-yaml punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token front-matter-block front-matter yaml language-yaml"> 笔记</span><br></span><span class="token-line" style="color:#000000"><span class="token front-matter-block front-matter yaml language-yaml"></span><span class="token front-matter-block front-matter yaml language-yaml key atrule">categories</span><span class="token front-matter-block front-matter yaml language-yaml punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token front-matter-block front-matter yaml language-yaml"></span><br></span><span class="token-line" style="color:#000000"><span class="token front-matter-block front-matter yaml language-yaml">  </span><span class="token front-matter-block front-matter yaml language-yaml punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token front-matter-block front-matter yaml language-yaml"> 个人学习笔记</span><br></span><span class="token-line" style="color:#000000"><span class="token front-matter-block front-matter yaml language-yaml"></span><span class="token front-matter-block front-matter yaml language-yaml key atrule">author</span><span class="token front-matter-block front-matter yaml language-yaml punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token front-matter-block front-matter yaml language-yaml"> 愧怍</span><br></span><span class="token-line" style="color:#000000"><span class="token front-matter-block front-matter yaml language-yaml"></span><span class="token front-matter-block front-matter yaml language-yaml key atrule">keys</span><span class="token front-matter-block front-matter yaml language-yaml punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token front-matter-block front-matter yaml language-yaml"></span><br></span><span class="token-line" style="color:#000000"><span class="token front-matter-block front-matter yaml language-yaml">  </span><span class="token front-matter-block front-matter yaml language-yaml punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token front-matter-block front-matter yaml language-yaml"> </span><span class="token front-matter-block front-matter yaml language-yaml string" style="color:rgb(163, 21, 21)">'e9bc0e13a8a16cbb07b175d92a113126'</span><span class="token front-matter-block front-matter yaml language-yaml"></span><br></span><span class="token-line" style="color:#000000"><span class="token front-matter-block front-matter yaml language-yaml"></span><span class="token front-matter-block front-matter yaml language-yaml key atrule">publish</span><span class="token front-matter-block front-matter yaml language-yaml punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token front-matter-block front-matter yaml language-yaml"> </span><span class="token front-matter-block front-matter yaml language-yaml boolean important">false</span><span class="token front-matter-block front-matter yaml language-yaml"></span><br></span><span class="token-line" style="color:#000000"><span class="token front-matter-block front-matter yaml language-yaml"></span><span class="token front-matter-block front-matter yaml language-yaml key atrule">isShowComments</span><span class="token front-matter-block front-matter yaml language-yaml punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token front-matter-block front-matter yaml language-yaml"> </span><span class="token front-matter-block front-matter yaml language-yaml boolean important">false</span><span class="token front-matter-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token front-matter-block"></span><span class="token front-matter-block punctuation" style="color:rgb(4, 81, 165)">---</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">::: tip</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">这是 tip</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">:::</span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token comment" style="color:rgb(0, 128, 0)">&lt;!--more --&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token title important punctuation" style="color:rgb(4, 81, 165)">##</span><span class="token title important"> 这是你的文章内容</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">正文内容</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p><code>---</code> 所包裹的内容就文章简述像下面这样</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20200901034715126.png" alt="image-20200901034715126" class="img_ev3q"></p><p>要更改标题，日期外，你还需要更改的是分类 categories 和标签 tags，举个例子，现在我想写一篇文章，标题是 ES6 语法，那么我可以这么写</p><div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token key atrule">tags</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain"> ES6</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain"> javascript</span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain"> js</span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token key atrule">categories</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">-</span><span class="token plain"> JavaScript</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>分类只写一个，可以写<code>JavaScript</code>（分类建议大写），标签写多个，然后你把你写的这篇文章，切记放在<code>blogs</code>目录下(以后写的博客都放在这里)，同时建一个文件夹名为<code>JavaScript</code>，的然后把文章放在这个目录下，文章名随意，建议和标题一样，如 ES6 语法.md。便于你以后分类，请按这样的方式归类文章。</p><p>万一我不小心<code>- JavaScript</code> 写成了 <code>- Java</code>，而并没有文件夹是<code>Java</code>的，没关系，也就是你在分类上看到 Java，文章分类不取决于文件夹名，而取决于<code>categories</code> 只是文件夹名和<code>categories</code>名一致便于分类罢了。</p><p>在标签页上，就能看到 ES6，javascript，与 js 的标签，方便定位相关文章</p><p>接着把要写的文章内容全都在写在<!-- -->下即可，这里要注意一下，正文内容的标题，从二级标题开始，一级标题就已经是 title 了，在写也没用。</p><p>其余相关的 key 和 publish 等相关参数还请读者查看 reco 主题的官方文档<a href="https://vuepress-theme-reco.recoluan.com/" target="_blank" rel="noopener noreferrer">立即前往</a>与 vuepress 官网<a href="https://vuepress.vuejs.org/zh/" target="_blank" rel="noopener noreferrer">立即前往</a></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="样式修改">样式修改<a class="hash-link" href="#样式修改" title="标题的直接链接">​</a></h3><p>可能你会局限于 reco 主题的默认样式，这里就说下如何修改样式。如果你会点前端，这应该来说非常简单。</p><ol><li>先参考这篇文章 <a href="https://vuepress-theme-reco.recoluan.com/views/other/reco-optimization.html" target="_blank" rel="noopener noreferrer">个人向优化</a>，我这里简单说明一下，首先一定要把<code>node_modules</code>里的<code>vuepress-theme-reco</code>这个主题文件夹整个放在<code>.vuepress\theme\</code>下，因为有些时候我们是要修改源码来更改样式的，如果你不这样做的话，而是直接修改<code>node_modules</code>里面的文件，你<code>npm install</code>就会覆盖你修改后的，所以要这一步操作。</li><li>当然你已经觉得 reco 主题都很完美了，不需要更改源码，那么你只需要在 <code>.vuepress/styles/</code> 来创建文件<code>index.styl</code>来方便地添加额外样式（还有一个默认样式，不推荐修改），然后把你要修改的样式代码写在<code>index.styl</code>文件里即可，例如我要修改首页的字体颜色，右键检查找到对应的 css 选择器，然后在<code>index.styl</code>添加就行，如</li></ol><div class="language-css codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-css codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token selector class">.home-blog</span><span class="token selector"> </span><span class="token selector class">.hero</span><span class="token selector"> h1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token property">color</span><span class="token punctuation" style="color:rgb(4, 81, 165)">:</span><span class="token plain"> </span><span class="token hexcode color">#fff</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain"></span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="部署到服务器上">部署到服务器上<a class="hash-link" href="#部署到服务器上" title="标题的直接链接">​</a></h3><p>关于部署到服务器上，如果只是为了让别人能看到你搭建的博客，而不是要购买域名和服务器这些，直接参考文章<a href="https://lookroot.cn/views/article/vuepress.html#reco%E4%B8%BB%E9%A2%98" target="_blank" rel="noopener noreferrer">使用 vuepress 构建个人博客</a>即可，如果有服务器和域名我这里简单说下怎么个部署法。</p><div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-shell codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token function" style="color:rgb(0, 0, 255)">npm</span><span class="token plain"> run bulid</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>首先执行上一行代码，然后在目录下会生成<code>public</code>文件夹，这个文件夹就是你所有的网站静态文件，这时候你需要你的服务器开启一个 web 服务，我这里用的是腾讯云 CentOS 与宝塔面板（至于这两个怎么搞，外面教程太多了），这里我就用 Nginx。然后如下图添加站点</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20200918194540550.png" alt="image-20200918194540550" class="img_ev3q"></p><p>因个人情况填写域名，FTP，数据库等等，然后通过 ftp 工具直接传文件至站点对应的目录下，然后访问服务器对应的 ip 地址或者个人域名解析就行了。</p><p>不过这个还要手动部署特别麻烦，有没有什么命令能一键部署的，有，这里我推荐一篇文章<a href="https://reinness.com/views/technology-sharing/vuepress/auto_deploy.html#index-js" target="_blank" rel="noopener noreferrer">一键部署到服务器</a>，解决了我当初一直用 ftp 的痛点。不过有个更简单的自动部署脚本，scp2，有兴趣可以自行查阅。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="自己搭建遇到的坑">自己搭建遇到的坑<a class="hash-link" href="#自己搭建遇到的坑" title="标题的直接链接">​</a></h2><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="图片路径">图片路径<a class="hash-link" href="#图片路径" title="标题的直接链接">​</a></h3><p>首先就是 markdown 图片相对路径的坑，在写文章的话，如果涉及的本地图片引入，那么默认不操作的，也就是需要配置一下，默认在当前同级文件下，在创建一个文件名相同的文件夹来存放图片，我这里就以 Typora 为例，如图</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20200901180754412.png" alt="image-20200901180754412" class="img_ev3q"></p><p>其次，Typora 的路径是不带<code>./</code>，在 vuepress 会被编译成绝对路径。需要在前面添加上<code>./</code>，不过主题内已自带插件<code>markdown-it</code>，这个问题无需担心。</p><p>但常常我们的 md 文件名是中文的，这时候相对路径带有中文，但是 vuepress 会将中文路径进行 url 编码，</p><p>不会将你的这些图片编译到静态文件上，所以需要做一些操作</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="解决方法">解决方法<a class="hash-link" href="#解决方法" title="标题的直接链接">​</a></h4><ol><li>安装 markdown-it-disable-url-encode</li></ol><div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">npm i markdown-it-disable-url-encode</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><ol start="2"><li>在.vuepress/config.js 中配置如下</li></ol><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token literal-property property">markdown</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token function-variable function" style="color:rgb(0, 0, 255)">extendMarkdown</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token parameter">md</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(0, 0, 0)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(4, 81, 165)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">      md</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token method function property-access" style="color:rgb(0, 0, 255)">use</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token function" style="color:rgb(0, 0, 255)">require</span><span class="token punctuation" style="color:rgb(4, 81, 165)">(</span><span class="token string" style="color:rgb(163, 21, 21)">"markdown-it-disable-url-encode"</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">)</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#000000"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(4, 81, 165)">}</span><span class="token punctuation" style="color:rgb(4, 81, 165)">,</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>现在你用 Typora 就引用本地图片就可以在 vuepress 中完美显示了。</p><blockquote><p>参考 <a href="https://segmentfault.com/a/1190000022275001" target="_blank" rel="noopener noreferrer">Vuepress 图片资源中文路径问题</a> 完美解决上述问题</p></blockquote><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="引入-ui-组件库报错">引入 UI 组件库报错<a class="hash-link" href="#引入-ui-组件库报错" title="标题的直接链接">​</a></h3><p>如果你在该主题使用其他 UI 组件库，如 element，ant design，那么你很有可能会编译失败，官方解释</p><p><img loading="lazy" src="https://img.kuizuo.cn/image-20201223042921876.png" alt="image-20201223042921876" class="img_ev3q"></p><p>解决办法很简单，先删除 node_modules，然后<strong>再安装 ui 组件库</strong>依赖后，再安装其他依赖就行了。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="放一些链接">放一些链接<a class="hash-link" href="#放一些链接" title="标题的直接链接">​</a></h2><p>放一些自己搭建这个博客过程中用到的一些链接地址，主要针对插件安装这些</p><ul><li><a href="https://vuepress.vuejs.org/zh/" target="_blank" rel="noopener noreferrer">VuePress 官网</a></li><li><a href="https://vuepress.github.io/" target="_blank" rel="noopener noreferrer">VuePress 社区</a></li><li><a href="https://github.com/vuepress/awesome-vuepress" target="_blank" rel="noopener noreferrer">awesome-vuepress</a></li><li><a href="https://vuepress-theme-reco.recoluan.com/" target="_blank" rel="noopener noreferrer">reco 主题</a></li><li><a href="https://blog.csdn.net/sudadaipeng1/article/details/102971008#%e6%b7%bb%e5%8a%a0svg-label%e6%a0%87%e7%ad%be" target="_blank" rel="noopener noreferrer">一个非常详细的搭建教程</a></li></ul><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="总结">总结<a class="hash-link" href="#总结" title="标题的直接链接">​</a></h2><p>就此，就可以好好的编写文章，主题固然方便，快捷搭建博客同时也别光顾这美化博客，注重分享文章，这才是博客的真正意义。reco 的主题也是希望帮助更多的人花更多的时间在内容创作上，而不是博客搭建上。</p><p>在使用 Vuepress 的一段时间，发现他更适合写的是文档，写博客可以，但花里胡哨的点少，比较简约，对于我这种又爱折腾的人来说，后续有可能会借鉴 Hexo 博客的一款主题 butterfly，将其源码复制到目前这个博客上，顺便巩固下自己的前端设计基础。</p><p>但还是要说的，要看自己到底要不要搭建博客，记录与分享文章，别盲目跟从。同时如果搭建博客，请把重心放在创作和笔记上，反复去美化主题对技术的提升远不如一篇有技术性的文章总结。</p><p>最后，希望我所分享的所有内容，正是你目前所遇到的难题，能为你排坑，便足矣。</p>]]></content:encoded>
            <category>blog</category>
            <category>vuepress</category>
            <category>project</category>
        </item>
    </channel>
</rss>