<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://quanscheng.vercel.app/blog</id>
    <title>TransonQ Blog</title>
    <updated>2024-04-26T00:00:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://quanscheng.vercel.app/blog"/>
    <subtitle>TransonQ Blog</subtitle>
    <icon>https://quanscheng.vercel.app/img/favicon.ico</icon>
    <entry>
        <title type="html"><![CDATA[full-bleed 布局]]></title>
        <id>https://quanscheng.vercel.app/blog/2024/04/26/full-bleed-layout</id>
        <link href="https://quanscheng.vercel.app/blog/2024/04/26/full-bleed-layout"/>
        <updated>2024-04-26T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[full-bleed图例]]></summary>
        <content type="html"><![CDATA[<h2 class="anchor anchorWithStickyNavbar_jjaS" id="full-bleed图例">full-bleed图例<a class="hash-link" aria-label="full-bleed图例的直接链接" title="full-bleed图例的直接链接" href="https://quanscheng.vercel.app/blog/2024/04/26/full-bleed-layout#full-bleed%E5%9B%BE%E4%BE%8B">​</a></h2>
<p><img decoding="async" loading="lazy" src="https://raw.githubusercontent.com/TransonQ/image-share/main/img/202404262238250.png" alt="full-bleed" class="img_PD5j"></p>
<h2 class="anchor anchorWithStickyNavbar_jjaS" id="代码">代码<a class="hash-link" aria-label="代码的直接链接" title="代码的直接链接" href="https://quanscheng.vercel.app/blog/2024/04/26/full-bleed-layout#%E4%BB%A3%E7%A0%81">​</a></h2>
<div class="language-html codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-html codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">main</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">class</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">wrapper</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">h1</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">Some Heading</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">h1</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">p</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">Some content and stuff</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">p</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">div</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">class</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">full-bleed</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">img</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">src</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">https://picsum.photos/1200/300</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">div</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">p</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">Some content and stuff</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">p</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">main</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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-css codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-css codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token selector class" style="color:#00009f">.wrapper</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">display</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> grid</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">/** 定义 grid 为三列 */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">grid-template-columns</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token number" style="color:#36acaa">1</span><span class="token unit">fr</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">min</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">65</span><span class="token unit">ch</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">calc</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">100</span><span class="token unit">%</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">64</span><span class="token unit">px</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token number" style="color:#36acaa">1</span><span class="token unit">fr</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">height</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">100</span><span class="token unit">%</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token selector class" style="color:#00009f">.wrapper</span><span class="token selector" style="color:#00009f"> </span><span class="token selector combinator" style="color:#00009f">&gt;</span><span class="token selector" style="color:#00009f"> *</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">/** 每个子元素都放在第二列的格子中;</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">      第一列和第三列的格子是空的;</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">      这样就达到了整体居中的效果.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">  */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">grid-column</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token selector class" style="color:#00009f">.full-bleed</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">width</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">100</span><span class="token unit">%</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">/** 从第1 到第3 列，不包含第四列，因为这个写法是按照索引的，左闭右开 */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">grid-column</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">/</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">4</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">display</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">grid</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">place-items</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">center</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token selector class" style="color:#00009f">.full-bleed</span><span class="token selector" style="color:#00009f"> </span><span class="token selector combinator" style="color:#00009f">&gt;</span><span class="token selector" style="color:#00009f"> img</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">width</span><span class="token punctuation" style="color:#393A34">:</span><span class="token number" style="color:#36acaa">100</span><span class="token unit">%</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">max-width</span><span class="token punctuation" style="color:#393A34">:</span><span class="token number" style="color:#36acaa">900</span><span class="token unit">px</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">min-width</span><span class="token punctuation" style="color:#393A34">:</span><span class="token number" style="color:#36acaa">500</span><span class="token unit">px</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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 decoding="async" loading="lazy" src="https://raw.githubusercontent.com/TransonQ/image-share/main/img/202404262243244.png" alt="效果图" class="img_PD5j"></p>
<blockquote>
<p>文章来源：<a href="https://www.joshwcomeau.com/css/full-bleed/" target="_blank" rel="noopener noreferrer">Full-Bleed Layout Using CSS Grid</a></p>
</blockquote>]]></content>
        <author>
            <name>TransonQ</name>
            <uri>https://github.com/TransonQ</uri>
        </author>
        <category label="css" term="css"/>
        <category label="grid" term="grid"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[pnpm工作区实现monorepo+shadcn项目]]></title>
        <id>https://quanscheng.vercel.app/blog/2024/04/20/monorepo-pnpm-tailwind-shadcn</id>
        <link href="https://quanscheng.vercel.app/blog/2024/04/20/monorepo-pnpm-tailwind-shadcn"/>
        <updated>2024-04-20T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[创建工作区]]></summary>
        <content type="html"><![CDATA[<h2 class="anchor anchorWithStickyNavbar_jjaS" id="创建工作区">创建工作区<a class="hash-link" aria-label="创建工作区的直接链接" title="创建工作区的直接链接" href="https://quanscheng.vercel.app/blog/2024/04/20/monorepo-pnpm-tailwind-shadcn#%E5%88%9B%E5%BB%BA%E5%B7%A5%E4%BD%9C%E5%8C%BA">​</a></h2>
<blockquote>
<p>推荐使用 <a href="https://pnpm.io/" target="_blank" rel="noopener noreferrer">pnpm</a>，本文章 pnpm 版本为：v8.15.7</p>
</blockquote>
<div class="language-jsx codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-jsx codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">mkdir growth</span><span class="token operator" style="color:#393A34">-</span><span class="token plain">apps</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">cd growth</span><span class="token operator" style="color:#393A34">-</span><span class="token plain">apps</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">pnpm init</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>可以得到如下的项目结构，然后修改 package.json，如下所示
<img decoding="async" loading="lazy" src="https://raw.githubusercontent.com/TransonQ/image-share/main/img/monorepo%E5%88%9D%E5%A7%8B%E5%8C%96.png" alt="init" class="img_PD5j"></p>
<p>创建 <code>pnpm-workspace.yaml</code>，并且更新文件内容如下：</p>
<p><img decoding="async" loading="lazy" src="https://raw.githubusercontent.com/TransonQ/image-share/main/img/202404191549769.png" alt="image-20240419154935735" class="img_PD5j"></p>
<p>创建 <code>.npmrc</code> 文件，更新文件内容如下：</p>
<div class="codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-text codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">auto-install-peers = true</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">enable-pre-post-scripts=true</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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>.gitignore</code> 文件，更新如下内容：</p>
<div class="codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-text codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain"># Logs</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">logs</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">*.log</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">npm-debug.log*</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">yarn-debug.log*</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">yarn-error.log*</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">pnpm-debug.log*</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">lerna-debug.log*</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">node_modules</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">dist</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">dist-ssr</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">*.local</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># Editor directories and files</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">!.vscode/extensions.json</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">.idea</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">.DS_Store</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">*.suo</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">*.ntvs*</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">*.njsproj</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">*.sln</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">*.sw?</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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 decoding="async" loading="lazy" src="https://raw.githubusercontent.com/TransonQ/image-share/main/img/202404191552768.png" alt="image-20240419155206736" class="img_PD5j"></p>
<p>初始化工作区 git：</p>
<div class="codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-text codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">git init</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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>/apps</code> <code>/packages</code> :</p>
<div class="codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-text codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">├───📁 apps/</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">├───📁 packages/</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">├───📄 .gitignore</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">├───📄 .npmrc</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">├───📄 package.json</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">└───📄 pnpm-workspace.yaml</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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 中的公共目录，参考设计如下：</p>
<ul>
<li>/ui</li>
<li>/utils</li>
<li>/config-ts</li>
<li>/config-tailwind</li>
</ul>
<blockquote>
<p>里程碑：已经得到一个 monorepo 基本的架构了。</p>
</blockquote>
<h2 class="anchor anchorWithStickyNavbar_jjaS" id="apps">apps<a class="hash-link" aria-label="apps的直接链接" title="apps的直接链接" href="https://quanscheng.vercel.app/blog/2024/04/20/monorepo-pnpm-tailwind-shadcn#apps">​</a></h2>
<p>这里以常见的 vite-react 创建一个 SPA 项目为例：</p>
<div class="codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-text codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">cd apps</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">pnpx create-vite</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">--------------- </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">pnpx create-vite</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Packages: +1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">+</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Progress: resolved 1, reused 1, downloaded 0, added 1, done</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">✔ Project name: … vite-react</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">✔ Select a framework: › React</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">✔ Select a variant: › TypeScript</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">---------------</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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-react 项目作为模板项目，后续创建类似的项目以此为样板直接快速搭建就好了。所以为此我们需要做一点小改动：</p>
<ul>
<li>我们将 <code>/apps/vite-react/package.json</code> 中的 <code>devDependencies</code> 和 <code>dependencies</code> 剪切到顶层的 <code>/package.json</code> 中。</li>
<li>执行 <code>pnpm i</code>。</li>
<li>接下来在 vite-react 项目的终端中执行 <code>pnpm run dev</code> 可以看到已经运行了一个初始项目。</li>
</ul>
<div class="codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-text codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">pnpm run dev</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">--------</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">&gt; vite</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Port 5173 is in use, trying another one...</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  VITE v5.2.9  ready in 130 ms</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  ➜  Local:   http://localhost:5174/</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  ➜  Network: use --host to expose</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  ➜  press h + enter to show help</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">--------</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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>注意：因为这个案例需求是，可能会创建多个 SPA 项目，将基础依赖提取到顶层 package.json 是为了保证所有项目使用同一个依赖版本。方便管理。</p>
</blockquote>
<h2 class="anchor anchorWithStickyNavbar_jjaS" id="packages">packages<a class="hash-link" aria-label="packages的直接链接" title="packages的直接链接" href="https://quanscheng.vercel.app/blog/2024/04/20/monorepo-pnpm-tailwind-shadcn#packages">​</a></h2>
<div class="codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-text codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">pnpm init</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>需要修改一下 package.json，根据 monorepo 工作区的约定，我们约定公共 ui 库的名称前缀为 <code>@mono/</code>。</p>
<div class="language-json codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-json codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">{</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "name": "@mono/ui",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "version": "1.0.0",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "description": "",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "private": true,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "scripts": {},</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "keywords": []</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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>pnpm i</code> ，你会在终端中看到类似于这样的提示：Scope: all 2 workspace projects 。这说明 pnpm 识别到了你的工作区中的项目。这一步是必须的，后续类似的操作，也遵循这一原则。</p>
</blockquote>
<p>然后为 packages 中的项目都初始化，然后都给项目名字加上前缀：<code>@mono/utils</code> , <code>@mono/config-ts</code> ,<code>@mono/config-tailwind</code> 。文章后续默认已经设置好了各个项目的 package.json。</p>
<h2 class="anchor anchorWithStickyNavbar_jjaS" id="配置-monoconfig-ts">配置 @mono/config-ts<a class="hash-link" aria-label="配置 @mono/config-ts的直接链接" title="配置 @mono/config-ts的直接链接" href="https://quanscheng.vercel.app/blog/2024/04/20/monorepo-pnpm-tailwind-shadcn#%E9%85%8D%E7%BD%AE-monoconfig-ts">​</a></h2>
<p><img decoding="async" loading="lazy" src="https://raw.githubusercontent.com/TransonQ/image-share/main/img/202404202002429.png" alt="monorepo-ts" class="img_PD5j"></p>
<p>一个最快速的实践方式是，直接将vite-react 项目中的配置文件复制到公共配置项目<code>@mono/config-ts</code>中。</p>
<p>config-ts</p>
<div class="codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-text codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">├───📄 package.json</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">├───📄 tsconfig.json</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">└───📄 tsconfig.node.json</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>config-ts/package.json</p>
<div class="codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-text codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">{</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "name": "@mono/config-ts",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "version": "1.0.0",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "description": "",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "private": true,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "exports": {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    ".": "./tsconfig.json"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>完成以上步骤后，需要在 apps/vite-react工作区中安装 @mono/config-ts</p>
<div class="codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-text codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">{</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "name": "vite-react",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	...</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "devDependencies": {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    "@mono/config-ts": "workspace:*"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>然后可能需要重启一下 ts 服务器，才会有代码提示。接下来通过在apps/vite-react的 ts 配置中引入并继承公共的配置就好了：</p>
<div class="codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-text codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">{</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "extends": "@mono/config-ts",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "include": [</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    "src"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  ],</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "compilerOptions": {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    "baseUrl": ".",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    "paths": {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      "~/*": [</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        "src/*"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      ]</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    },</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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>里程碑：已经完成了复用 ts 配置的操作啦。</p>
</blockquote>
<p>上面还配置了路径别名，根据自己习惯的配置即可，记得在 <code>vite.config.ts</code> 中配置路径别名，还需要安装node 的类型文件：</p>
<div class="codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-text codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">pnpm i -wD @types/node</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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-ts codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-ts codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// `vite.config.ts`</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> react </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"@vitejs/plugin-react"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> resolve </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"path"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> defineConfig </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"vite"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// https://vitejs.dev/config/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">default</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">defineConfig</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  plugins</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token function" style="color:#d73a49">react</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  resolve</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    alias</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token string-property property" style="color:#36acaa">"~"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">resolve</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">__dirname</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"src"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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 anchorWithStickyNavbar_jjaS" id="配置-monoui-shadcn">配置 @mono/ui (shadcn)<a class="hash-link" aria-label="配置 @mono/ui (shadcn)的直接链接" title="配置 @mono/ui (shadcn)的直接链接" href="https://quanscheng.vercel.app/blog/2024/04/20/monorepo-pnpm-tailwind-shadcn#%E9%85%8D%E7%BD%AE-monoui-shadcn">​</a></h2>
<p><img decoding="async" loading="lazy" src="https://raw.githubusercontent.com/TransonQ/image-share/main/img/202404202003607.png" alt="monorepo-ui" class="img_PD5j"></p>
<p>还记得前面配置的 <code>@mono/ui</code> 吗？现在准备开始配置项目应该如何巧妙的复用 shadcn 组件，由于 shadcn 具有极高的灵活性，同时它又是通过拷贝组件的到本地仓库的模式进行开发，如果 monorepo 多个项目每一个项目都去维护各自的 UI 组件，工作量会大大提高。所以这里主要分享一下如何在 monorepo 中复用组件。</p>
<p>经过前面的配置，monorepo项目目录大概如下：</p>
<div class="codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-text codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">.</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">├───📁 apps/</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│   └───📁 vite-react/</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│       └───...</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">├───📁 packages/</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│   ├───📁 config-tailwind/</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│   │   └───📄 package.json</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│   ├───📁 config-ts/</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│   │   ├───📄 package.json</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│   │   ├───📄 tsconfig.json</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│   │   └───📄 tsconfig.node.json</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│   ├───📁 ui/</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│   │   └───📄 package.json</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│   └───📁 utils/</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│       └───📄 package.json</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">├───📄 .gitignore</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">├───📄 .npmrc</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">├───📄 package.json</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">├───📄 pnpm-lock.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">└───📄 pnpm-workspace.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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>@mono/ui</code>也就是 <code>/packages/ui</code> ，现在将会在这里通过 <a href="https://ui.shadcn.com/docs/installation/vite" target="_blank" rel="noopener noreferrer">shadcn/ui 的官方教程</a>，开始初始化组件的存放位置。</p>
<blockquote>
<p>注意：这里我们不需要初始化为 vite 项目，其实只需要一个 ts 配置就好了。</p>
</blockquote>
<p>首先需要在@mono/ui中安装共享 ts 配置的公共库：@mono/config-ts</p>
<div class="codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-text codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">cd /packages/ui</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">pnpm i @mono/config-ts @mono/utils</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">------</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">{</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "name": "@mono/ui",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "version": "1.0.0",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "description": "",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "scripts": {},</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "keywords": [],</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "dependencies": {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    "@mono/config-ts": "workspace:*",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    "@mono/utils": "workspace:*"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">------</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>创建一个 tsconfig.json 文件</p>
<div class="language-json codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-json codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">{</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "extends": "@mono/config-ts",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "include": [</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    "src"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  ],</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "compilerOptions": {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    "baseUrl": ".",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    "paths": {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      "@/*": [</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        "src/*"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      ]</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    },</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>紧接着开始下一步，开始初始化 shadcn 配置项</p>
<div class="codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-text codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">pnpm install -wD tailwindcss postcss autoprefixer</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">pnpx tailwindcss init -p</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">pnpx shadcn-ui@latest init</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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="codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-text codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">✔ Would you like to use TypeScript (recommended)? … no / yes</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">✔ Which style would you like to use? › Default</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">✔ Which color would you like to use as base color? › Slate</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">✔ Where is your global CSS file? … src/gloabal.css</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">✔ Would you like to use CSS variables for colors? … no / yes</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">✔ Are you using a custom tailwind prefix eg. tw-? (Leave blank if not) … </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">✔ Where is your tailwind.config.js located? … tailwind.config.js</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">✔ Configure the import alias for components: … src</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">✔ Configure the import alias for utils: … @mono/utils</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">✔ Are you using React Server Components? … no / yes</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">✔ Write configuration to components.json. Proceed? … yes</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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>注意：上面有一些不同，分别是：</p>
<ol>
<li>Configure the import alias for components:  src<!-- -->
<ul>
<li>由于@mono/ui，仅作为存放 shadcn 组件库的工作区，所以直接放在 src 下足够了，避免文件夹层级过深。</li>
</ul>
</li>
<li>Configure the import alias for utils:  @mono/utils<!-- -->
<ul>
<li>是的，@mono/utils 用于存放整个项目的公共函数工具。</li>
</ul>
</li>
<li>如果你打开项目会发现 shadcn 默认安装了一些必要的依赖，考虑到多个项目使用相同版本，将他们移动到顶层工作区的 package.json中去。</li>
</ol>
</blockquote>
<h2 class="anchor anchorWithStickyNavbar_jjaS" id="配置-monoutils">配置 @mono/utils<a class="hash-link" aria-label="配置 @mono/utils的直接链接" title="配置 @mono/utils的直接链接" href="https://quanscheng.vercel.app/blog/2024/04/20/monorepo-pnpm-tailwind-shadcn#%E9%85%8D%E7%BD%AE-monoutils">​</a></h2>
<p><img decoding="async" loading="lazy" src="https://raw.githubusercontent.com/TransonQ/image-share/main/img/202404202003313.png" alt="monorepo-utils" class="img_PD5j"></p>
<div class="codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-text codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">├───📁 src/</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│   ├───📄 cn.ts</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│   └───📄 index.ts</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">├───📄 package.json</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">└───📄 tsconfig.json</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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>cn.ts</code>是 UI 必要的函数</p>
<div class="language-ts codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-ts codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> clsx</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">type</span><span class="token plain"> </span><span class="token class-name">ClassValue</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"clsx"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> twMerge </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"tailwind-merge"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">cn</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">...</span><span class="token plain">inputs</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> ClassValue</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">twMerge</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">clsx</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">inputs</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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>index.ts</code>所有工具函数导出的入口，未来需要使用到的函数都可以在此处导出。</p>
<div class="language-ts codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-ts codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">export</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> cn </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"./cn"</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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>packages.json</code></p>
<div class="language-json codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-json codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">{</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "name": "@mono/utils",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "version": "1.0.0",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "description": "shared utils",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "scripts": {},</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "devDependencies": {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    "@mono/config-ts": "workspace:^"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  },</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "exports": {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    ".": "./src/index.ts"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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>里程碑：这样配置，既满足了公共函数的存放位置，有解答了上面关于：“Configure the import alias for utils:  @mono/utils” 的问题。</p>
</blockquote>
<p>现在来试试组件安装效果：</p>
<div class="codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-text codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">cd /packages/ui</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">pnpx shadcn-ui@latest add button</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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 decoding="async" loading="lazy" src="https://raw.githubusercontent.com/TransonQ/image-share/main/img/202404192042176.png" alt="image-20240419204201124" class="img_PD5j"></p>
<p>可以看到，安装组件验证了上面把工具函数都放在@mono/utils中的做法是正确的。</p>
<p>接下来配置package.json，添加：exports相关的配置，以便我们在业务 app 中更直观的引入。</p>
<div class="language-json codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-json codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">{</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "name": "@mono/ui",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "version": "1.0.0",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "description": "",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "scripts": {},</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "keywords": [],</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "dependencies": {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    "@mono/config-ts": "workspace:*",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    "@mono/utils": "workspace:*",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    "@radix-ui/react-slot": "1.0.2"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  },</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "exports": {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    "./*": "./src/ui/*.tsx"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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-react 项目，看看上面引入的 button 组件是否有效。</p>
<div class="codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-text codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">pnpm -F vite-react i @mono/ui</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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-tsx codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-tsx codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"> </span><span class="token imports maybe-class-name">Button</span><span class="token imports"> </span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"@mono/ui/button"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">App</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">      </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">Button</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text">click</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag class-name" style="color:#00009f">Button</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">    </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">default</span><span class="token plain"> </span><span class="token maybe-class-name">App</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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="codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-text codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">pnpm -F vite-react run dev</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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 decoding="async" loading="lazy" src="https://raw.githubusercontent.com/TransonQ/image-share/main/img/202404192049610.png" alt="image-20240419204908546" class="img_PD5j"></p>
<blockquote>
<p>是的，成功引入了共享组件库@mono/ui中的 button 组件，没有样式效果。请继续阅读下一个章节：关于共享tailwind的配置，@mono/config-tailwind。</p>
</blockquote>
<h2 class="anchor anchorWithStickyNavbar_jjaS" id="配置-monoconfig-tailwind">配置 @mono/config-tailwind<a class="hash-link" aria-label="配置 @mono/config-tailwind的直接链接" title="配置 @mono/config-tailwind的直接链接" href="https://quanscheng.vercel.app/blog/2024/04/20/monorepo-pnpm-tailwind-shadcn#%E9%85%8D%E7%BD%AE-monoconfig-tailwind">​</a></h2>
<p><img decoding="async" loading="lazy" src="https://raw.githubusercontent.com/TransonQ/image-share/main/img/202404202003005.png" alt="monorepo-tailwind" class="img_PD5j"></p>
<p>现在我们需要引入 tailwind 相关的配置</p>
<div class="codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-text codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">cd apps/vite-react</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">pnpx tailwindcss init -p</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">pnpm i @mono/config-tailwind</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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.ts 做一点小改动，所有项目的默认配置都是通过继承 @mono/config-tailwind 来的。</p>
<div class="codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-text codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain"># config-tailwind</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">├───📄 global.css</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">├───📄 package.json</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">└───📄 tailwind.config.js</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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>/packages/config-tailwind/tailwind.config.ts</code> 配置如下：</p>
<div class="language-ts codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-ts codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token doc-comment comment" style="color:#999988;font-style:italic">/** </span><span class="token doc-comment comment keyword" style="color:#00009f;font-style:italic">@type</span><span class="token doc-comment comment" style="color:#999988;font-style:italic"> </span><span class="token doc-comment comment punctuation" style="color:#393A34;font-style:italic">{</span><span class="token doc-comment comment" style="color:#999988;font-style:italic">import('tailwindcss').Config</span><span class="token doc-comment comment punctuation" style="color:#393A34;font-style:italic">}</span><span class="token doc-comment comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">module</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">exports </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  darkMode</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">"class"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  content</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">'./pages/**/*.{ts,tsx}'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">'./components/**/*.{ts,tsx}'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">'./app/**/*.{ts,tsx}'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">'./src/**/*.{ts,tsx}'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">'../../packages/ui/src/**/*.{ts,tsx}'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// ++</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">'../../packages/lib/src/**/*.{ts,tsx}'</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// ++</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  prefix</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  theme</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    container</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      center</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      padding</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"2rem"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      screens</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token string-property property" style="color:#36acaa">"2xl"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"1400px"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    extend</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      colors</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        border</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"hsl(var(--border))"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        input</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"hsl(var(--input))"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        ring</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"hsl(var(--ring))"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        background</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"hsl(var(--background))"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        foreground</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"hsl(var(--foreground))"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        primary</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token constant" style="color:#36acaa">DEFAULT</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"hsl(var(--primary))"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          foreground</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"hsl(var(--primary-foreground))"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        secondary</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token constant" style="color:#36acaa">DEFAULT</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"hsl(var(--secondary))"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          foreground</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"hsl(var(--secondary-foreground))"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        destructive</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token constant" style="color:#36acaa">DEFAULT</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"hsl(var(--destructive))"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          foreground</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"hsl(var(--destructive-foreground))"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        muted</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token constant" style="color:#36acaa">DEFAULT</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"hsl(var(--muted))"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          foreground</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"hsl(var(--muted-foreground))"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        accent</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token constant" style="color:#36acaa">DEFAULT</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"hsl(var(--accent))"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          foreground</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"hsl(var(--accent-foreground))"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        popover</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token constant" style="color:#36acaa">DEFAULT</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"hsl(var(--popover))"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          foreground</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"hsl(var(--popover-foreground))"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        card</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token constant" style="color:#36acaa">DEFAULT</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"hsl(var(--card))"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          foreground</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"hsl(var(--card-foreground))"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      borderRadius</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        lg</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"var(--radius)"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        md</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"calc(var(--radius) - 2px)"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        sm</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"calc(var(--radius) - 4px)"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      keyframes</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token string-property property" style="color:#36acaa">"accordion-down"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          from</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> height</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"0"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          to</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> height</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"var(--radix-accordion-content-height)"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token string-property property" style="color:#36acaa">"accordion-up"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          from</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> height</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"var(--radix-accordion-content-height)"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          to</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> height</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"0"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      animation</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token string-property property" style="color:#36acaa">"accordion-down"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"accordion-down 0.2s ease-out"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token string-property property" style="color:#36acaa">"accordion-up"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"accordion-up 0.2s ease-out"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  plugins</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token keyword" style="color:#00009f">require</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"tailwindcss-animate"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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>global.css</code></p>
<div class="language-css codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-css codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token atrule rule" style="color:#00a4db">@tailwind</span><span class="token atrule" style="color:#00a4db"> base</span><span class="token atrule punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token atrule rule" style="color:#00a4db">@tailwind</span><span class="token atrule" style="color:#00a4db"> components</span><span class="token atrule punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token atrule rule" style="color:#00a4db">@tailwind</span><span class="token atrule" style="color:#00a4db"> utilities</span><span class="token atrule punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token atrule rule" style="color:#00a4db">@layer</span><span class="token atrule" style="color:#00a4db"> base</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token selector pseudo-class" style="color:#00009f">:root</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--background</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token unit">%</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">100</span><span class="token unit">%</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--foreground</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">222.2</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">84</span><span class="token unit">%</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">4.9</span><span class="token unit">%</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--card</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token unit">%</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">100</span><span class="token unit">%</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--card-foreground</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">222.2</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">84</span><span class="token unit">%</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">4.9</span><span class="token unit">%</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--popover</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token unit">%</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">100</span><span class="token unit">%</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--popover-foreground</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">222.2</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">84</span><span class="token unit">%</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">4.9</span><span class="token unit">%</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--primary</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">222.2</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">47.4</span><span class="token unit">%</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">11.2</span><span class="token unit">%</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--primary-foreground</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">210</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">40</span><span class="token unit">%</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">98</span><span class="token unit">%</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--secondary</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">210</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">40</span><span class="token unit">%</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">96.1</span><span class="token unit">%</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--secondary-foreground</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">222.2</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">47.4</span><span class="token unit">%</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">11.2</span><span class="token unit">%</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--muted</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">210</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">40</span><span class="token unit">%</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">96.1</span><span class="token unit">%</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--muted-foreground</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">215.4</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">16.3</span><span class="token unit">%</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">46.9</span><span class="token unit">%</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--accent</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">210</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">40</span><span class="token unit">%</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">96.1</span><span class="token unit">%</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--accent-foreground</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">222.2</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">47.4</span><span class="token unit">%</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">11.2</span><span class="token unit">%</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--destructive</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">84.2</span><span class="token unit">%</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">60.2</span><span class="token unit">%</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--destructive-foreground</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">210</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">40</span><span class="token unit">%</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">98</span><span class="token unit">%</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--border</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">214.3</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">31.8</span><span class="token unit">%</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">91.4</span><span class="token unit">%</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--input</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">214.3</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">31.8</span><span class="token unit">%</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">91.4</span><span class="token unit">%</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--ring</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">222.2</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">84</span><span class="token unit">%</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">4.9</span><span class="token unit">%</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--radius</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0.5</span><span class="token unit">rem</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--sb-track-color</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">hsl</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">var</span><span class="token punctuation" style="color:#393A34">(</span><span class="token variable" style="color:#36acaa">--muted</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--sb-thumb-color</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">hsl</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">var</span><span class="token punctuation" style="color:#393A34">(</span><span class="token variable" style="color:#36acaa">--muted-foreground</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--sb-size</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">6</span><span class="token unit">px</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token selector class" style="color:#00009f">.dark</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--background</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">240</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10</span><span class="token unit">%</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3.9</span><span class="token unit">%</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--foreground</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token unit">%</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">98</span><span class="token unit">%</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--card</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">240</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10</span><span class="token unit">%</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3.9</span><span class="token unit">%</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--card-foreground</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token unit">%</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">98</span><span class="token unit">%</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--popover</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">240</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10</span><span class="token unit">%</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3.9</span><span class="token unit">%</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--popover-foreground</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token unit">%</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">98</span><span class="token unit">%</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--primary</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token unit">%</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">98</span><span class="token unit">%</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--primary-foreground</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">240</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">5.9</span><span class="token unit">%</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10</span><span class="token unit">%</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--secondary</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">240</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3.7</span><span class="token unit">%</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">15.9</span><span class="token unit">%</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--secondary-foreground</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token unit">%</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">98</span><span class="token unit">%</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--muted</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">240</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3.7</span><span class="token unit">%</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">15.9</span><span class="token unit">%</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--muted-foreground</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">240</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">5</span><span class="token unit">%</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">64.9</span><span class="token unit">%</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--accent</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">240</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3.7</span><span class="token unit">%</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">15.9</span><span class="token unit">%</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--accent-foreground</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token unit">%</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">98</span><span class="token unit">%</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--destructive</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">62.8</span><span class="token unit">%</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">30.6</span><span class="token unit">%</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--destructive-foreground</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">85.7</span><span class="token unit">%</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">97.3</span><span class="token unit">%</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--border</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">240</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3.7</span><span class="token unit">%</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">15.9</span><span class="token unit">%</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--input</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">240</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3.7</span><span class="token unit">%</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">15.9</span><span class="token unit">%</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--ring</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">240</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">4.9</span><span class="token unit">%</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">83.9</span><span class="token unit">%</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--sb-track-color</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">hsl</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">var</span><span class="token punctuation" style="color:#393A34">(</span><span class="token variable" style="color:#36acaa">--muted</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--sb-thumb-color</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">hsl</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">var</span><span class="token punctuation" style="color:#393A34">(</span><span class="token variable" style="color:#36acaa">--muted-foreground</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--sb-size</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">6</span><span class="token unit">px</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token atrule rule" style="color:#00a4db">@layer</span><span class="token atrule" style="color:#00a4db"> base</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token selector" style="color:#00009f">*</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token atrule rule" style="color:#00a4db">@apply</span><span class="token atrule" style="color:#00a4db"> border-border</span><span class="token atrule punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token selector" style="color:#00009f">body</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token atrule rule" style="color:#00a4db">@apply</span><span class="token atrule" style="color:#00a4db"> bg-background text-foreground</span><span class="token atrule punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token selector" style="color:#00009f">body</span><span class="token selector pseudo-element" style="color:#00009f">::-webkit-scrollbar</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">width</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">var</span><span class="token punctuation" style="color:#393A34">(</span><span class="token variable" style="color:#36acaa">--sb-size</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token selector" style="color:#00009f">body</span><span class="token selector pseudo-element" style="color:#00009f">::-webkit-scrollbar-track</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">background</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">var</span><span class="token punctuation" style="color:#393A34">(</span><span class="token variable" style="color:#36acaa">--sb-track-color</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">border-radius</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3</span><span class="token unit">px</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token selector" style="color:#00009f">body</span><span class="token selector pseudo-element" style="color:#00009f">::-webkit-scrollbar-thumb</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">background</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">var</span><span class="token punctuation" style="color:#393A34">(</span><span class="token variable" style="color:#36acaa">--sb-thumb-color</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">border-radius</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3</span><span class="token unit">px</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token atrule rule" style="color:#00a4db">@supports</span><span class="token atrule" style="color:#00a4db"> </span><span class="token atrule keyword" style="color:#00009f">not</span><span class="token atrule" style="color:#00a4db"> </span><span class="token atrule function" style="color:#d73a49">selector</span><span class="token atrule punctuation" style="color:#393A34">(</span><span class="token atrule selector-function-argument selector pseudo-element" style="color:#00009f">::-webkit-scrollbar</span><span class="token atrule punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token selector" style="color:#00009f">body</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token property" style="color:#36acaa">scrollbar-color</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">var</span><span class="token punctuation" style="color:#393A34">(</span><span class="token variable" style="color:#36acaa">--sb-thumb-color</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">var</span><span class="token punctuation" style="color:#393A34">(</span><span class="token variable" style="color:#36acaa">--sb-track-color</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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>package.json</code></p>
<div class="language-json codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-json codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">{</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "name": "@mono/config-tailwind",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "version": "1.0.0",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "description": "",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "scripts": {},</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "keywords": [],</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "exports": {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    ".": "./tailwind.config.ts",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    "./global.css": "./global.css"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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 解析的项目中的 tailwind.config.ts 可以直接引入并导出公共配置：</p>
<p><code>apps/vite-react/tailwind.config.ts</code></p>
<p><code>packages/ui/tailwind.config.ts</code></p>
<div class="codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-text codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">export * from "@mono/config-tailwind";</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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-react 项目中的 main.tsx里面的 <code>import 'global.css'</code>-&gt;<code>import "@mono/config-tailwind/global.css"</code></p>
</blockquote>
<h2 class="anchor anchorWithStickyNavbar_jjaS" id="配置-ui-add-指令">配置 ui-add 指令<a class="hash-link" aria-label="配置 ui-add 指令的直接链接" title="配置 ui-add 指令的直接链接" href="https://quanscheng.vercel.app/blog/2024/04/20/monorepo-pnpm-tailwind-shadcn#%E9%85%8D%E7%BD%AE-ui-add-%E6%8C%87%E4%BB%A4">​</a></h2>
<p><img decoding="async" loading="lazy" src="https://raw.githubusercontent.com/TransonQ/image-share/main/img/202404192321443.png" alt="image-20240419232127393" class="img_PD5j"></p>
<p><img decoding="async" loading="lazy" src="https://raw.githubusercontent.com/TransonQ/image-share/main/img/202404192321858.png" alt="image-20240419232147741" class="img_PD5j"></p>
<p>现在测试一下命令是否生效：</p>
<div class="codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-text codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">pnpm run ui-add card</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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-react 项目中 引入案例：</p>
<div class="language-tsx codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-tsx codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"> </span><span class="token imports maybe-class-name">Button</span><span class="token imports"> </span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"@mono/ui/button"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"></span><br></span><span class="token-line" style="color:#393A34"><span class="token imports">  </span><span class="token imports maybe-class-name">Card</span><span class="token imports punctuation" style="color:#393A34">,</span><span class="token imports"></span><br></span><span class="token-line" style="color:#393A34"><span class="token imports">  </span><span class="token imports maybe-class-name">CardContent</span><span class="token imports punctuation" style="color:#393A34">,</span><span class="token imports"></span><br></span><span class="token-line" style="color:#393A34"><span class="token imports">  </span><span class="token imports maybe-class-name">CardDescription</span><span class="token imports punctuation" style="color:#393A34">,</span><span class="token imports"></span><br></span><span class="token-line" style="color:#393A34"><span class="token imports">  </span><span class="token imports maybe-class-name">CardFooter</span><span class="token imports punctuation" style="color:#393A34">,</span><span class="token imports"></span><br></span><span class="token-line" style="color:#393A34"><span class="token imports">  </span><span class="token imports maybe-class-name">CardHeader</span><span class="token imports punctuation" style="color:#393A34">,</span><span class="token imports"></span><br></span><span class="token-line" style="color:#393A34"><span class="token imports">  </span><span class="token imports maybe-class-name">CardTitle</span><span class="token imports punctuation" style="color:#393A34">,</span><span class="token imports"></span><br></span><span class="token-line" style="color:#393A34"><span class="token imports"></span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"@mono/ui/card"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">App</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">      </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">Button</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text">click</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag class-name" style="color:#00009f">Button</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">      </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">Card</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">        </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">CardHeader</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">          </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">CardTitle</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text">Card Title</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag class-name" style="color:#00009f">CardTitle</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">          </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">CardDescription</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text">Card Description</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag class-name" style="color:#00009f">CardDescription</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">        </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag class-name" style="color:#00009f">CardHeader</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">        </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">CardContent</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">          </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">p</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text">Card Content</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">p</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">        </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag class-name" style="color:#00009f">CardContent</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">        </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">CardFooter</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">          </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">p</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text">Card Footer</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">p</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">        </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag class-name" style="color:#00009f">CardFooter</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">      </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag class-name" style="color:#00009f">Card</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">    </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">default</span><span class="token plain"> </span><span class="token maybe-class-name">App</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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 decoding="async" loading="lazy" src="https://raw.githubusercontent.com/TransonQ/image-share/main/img/202404192326293.png" alt="image-20240419232626210" class="img_PD5j"></p>
<h2 class="anchor anchorWithStickyNavbar_jjaS" id="配置monohooks">配置@mono/hooks<a class="hash-link" aria-label="配置@mono/hooks的直接链接" title="配置@mono/hooks的直接链接" href="https://quanscheng.vercel.app/blog/2024/04/20/monorepo-pnpm-tailwind-shadcn#%E9%85%8D%E7%BD%AEmonohooks">​</a></h2>
<p><img decoding="async" loading="lazy" src="https://raw.githubusercontent.com/TransonQ/image-share/main/img/202404202004923.png" alt="monorepo-hooks" class="img_PD5j"></p>
<p>用类似的方式可以尝试配置一个公共hooks 库：</p>
<div class="codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-text codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">├───📁 src/</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│   ├───📄 index.ts</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│   └───📄 useTest.ts</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">├───📄 package.json</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">└───📄 tsconfig.json</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-json codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">// package.json</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">{</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "name": "@mono/hooks",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "version": "1.0.0",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "private": true,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "description": "",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "scripts": {},</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "exports": {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    ".": "./src/index.ts"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  },</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "devDependencies": {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    "@mono/config-ts": "workspace:*"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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 anchorWithStickyNavbar_jjaS" id="tldr">TL;DR<a class="hash-link" aria-label="TL;DR的直接链接" title="TL;DR的直接链接" href="https://quanscheng.vercel.app/blog/2024/04/20/monorepo-pnpm-tailwind-shadcn#tldr">​</a></h2>
<p>Repository address: <a href="https://github.com/TransonQ/growth-apps" target="_blank" rel="noopener noreferrer">https://github.com/TransonQ/growth-apps</a></p>]]></content>
        <author>
            <name>TransonQ</name>
            <uri>https://github.com/TransonQ</uri>
        </author>
        <category label="tailwind" term="tailwind"/>
        <category label="monorepo" term="monorepo"/>
        <category label="pnpm" term="pnpm"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[去除在 vscode 中无法识别 tailwindcss 的警告]]></title>
        <id>https://quanscheng.vercel.app/blog/2024/04/10/去除tailwindcss 警告</id>
        <link href="https://quanscheng.vercel.app/blog/2024/04/10/去除tailwindcss 警告"/>
        <updated>2024-04-10T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[问题描述]]></summary>
        <content type="html"><![CDATA[<h2 class="anchor anchorWithStickyNavbar_jjaS" id="问题描述">问题描述<a class="hash-link" aria-label="问题描述的直接链接" title="问题描述的直接链接" href="https://quanscheng.vercel.app/blog/2024/04/10/%E5%8E%BB%E9%99%A4tailwindcss%20%E8%AD%A6%E5%91%8A#%E9%97%AE%E9%A2%98%E6%8F%8F%E8%BF%B0">​</a></h2>
<p><img decoding="async" loading="lazy" src="https://raw.githubusercontent.com/TransonQ/image-share/main/img/202404102007750.png" alt="image-20240410200754613" class="img_PD5j"></p>
<blockquote>
<p>Unknown at rule @tailwindcss(unknownAtRules)</p>
</blockquote>
<h2 class="anchor anchorWithStickyNavbar_jjaS" id="解决方法">解决方法<a class="hash-link" aria-label="解决方法的直接链接" title="解决方法的直接链接" href="https://quanscheng.vercel.app/blog/2024/04/10/%E5%8E%BB%E9%99%A4tailwindcss%20%E8%AD%A6%E5%91%8A#%E8%A7%A3%E5%86%B3%E6%96%B9%E6%B3%95">​</a></h2>
<p>打开 vscode 设置，输入<code>file associations</code> 添加项：</p>
<div class="codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-text codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">*.css     tailwindcss</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">*.scss    tailwindcss</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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 decoding="async" loading="lazy" src="https://raw.githubusercontent.com/TransonQ/image-share/main/img/202404102014408.png" alt="image-20240410201406358" class="img_PD5j"></p>
<blockquote>
<p>到此就可以了，治好了强迫症。</p>
</blockquote>]]></content>
        <author>
            <name>TransonQ</name>
            <uri>https://github.com/TransonQ</uri>
        </author>
        <category label="tailwind" term="tailwind"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[自定义useSearchState与查询字符串同步状态]]></title>
        <id>https://quanscheng.vercel.app/blog/2024/01/02/useSearchState</id>
        <link href="https://quanscheng.vercel.app/blog/2024/01/02/useSearchState"/>
        <updated>2024-01-02T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[code]]></summary>
        <content type="html"><![CDATA[<h2 class="anchor anchorWithStickyNavbar_jjaS" id="code">code<a class="hash-link" aria-label="code的直接链接" title="code的直接链接" href="https://quanscheng.vercel.app/blog/2024/01/02/useSearchState#code">​</a></h2>
<blockquote>
<p><a href="https://gist.github.com/TransonQ/1c34c4785631285e41a88e8397212b6f" target="_blank" rel="noopener noreferrer">代码: useSearchState-TransonQ</a></p>
</blockquote>
<div class="language-ts codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-ts codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> useState</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> useEffect </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"react"</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token generic-function function" style="color:#d73a49">useSearchState</span><span class="token generic-function generic class-name operator" style="color:#393A34">&lt;</span><span class="token generic-function generic class-name constant" style="color:#36acaa">T</span><span class="token generic-function generic class-name operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">key</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> init</span><span class="token operator" style="color:#393A34">?</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">T</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> searchParams </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">URLSearchParams</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">window</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">location</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">search</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> initValue </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> searchParams</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">key</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">||</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">try</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token constant" style="color:#36acaa">JSON</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">parse</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">initValue</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 尝试解析查询字符串中的值</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">init </span><span class="token operator" style="color:#393A34">!==</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">undefined</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      initValue </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">JSON</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stringify</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">init</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 如果解析错误，使用init的格式化后的值</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      initValue </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 如果init也没有，初始化为空字符串</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">params</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> setParams</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token generic-function function" style="color:#d73a49">useState</span><span class="token generic-function generic class-name operator" style="color:#393A34">&lt;</span><span class="token generic-function generic class-name constant" style="color:#36acaa">T</span><span class="token generic-function generic class-name operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">JSON</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">parse</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">initValue</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">T</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">useEffect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> searchParams </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">URLSearchParams</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">window</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">location</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">search</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    searchParams</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">set</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">key</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">JSON</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stringify</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">params</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> newUrl </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:#e3116c">`</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#393A34">${</span><span class="token template-string interpolation">window</span><span class="token template-string interpolation punctuation" style="color:#393A34">.</span><span class="token template-string interpolation">location</span><span class="token template-string interpolation punctuation" style="color:#393A34">.</span><span class="token template-string interpolation">pathname</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#393A34">}</span><span class="token template-string string" style="color:#e3116c">?</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#393A34">${</span><span class="token template-string interpolation">searchParams</span><span class="token template-string interpolation punctuation" style="color:#393A34">.</span><span class="token template-string interpolation function" style="color:#d73a49">toString</span><span class="token template-string interpolation punctuation" style="color:#393A34">(</span><span class="token template-string interpolation punctuation" style="color:#393A34">)</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#393A34">}</span><span class="token template-string template-punctuation string" style="color:#e3116c">`</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    window</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">history</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">replaceState</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> newUrl</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">params</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> key</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">params</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> setParams</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">const</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">default</span><span class="token plain"> useSearchState</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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 anchorWithStickyNavbar_jjaS" id="使用案例">使用案例<a class="hash-link" aria-label="使用案例的直接链接" title="使用案例的直接链接" href="https://quanscheng.vercel.app/blog/2024/01/02/useSearchState#%E4%BD%BF%E7%94%A8%E6%A1%88%E4%BE%8B">​</a></h2>
<p><a href="https://codesandbox.io/p/sandbox/usesearchstate-key-init-9krjzz" target="_blank" rel="noopener noreferrer">https://codesandbox.io/p/sandbox/usesearchstate-key-init-9krjzz</a></p>
<iframe src="https://codesandbox.io/embed/9krjzz?view=Editor+%2B+Preview&amp;module=%2Fsrc%2Fhooks%2FuseSearchState.ts&amp;expanddevtools=1" style="width:100%;height:600px;border:0;border-radius:4px;overflow:hidden" title="useSearchState('key',init)" allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking" sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"></iframe>]]></content>
        <author>
            <name>TransonQ</name>
            <uri>https://github.com/TransonQ</uri>
        </author>
        <category label="hooks" term="hooks"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[使用useContext封装一个全局useToast]]></title>
        <id>https://quanscheng.vercel.app/blog/2023/12/26/useToast</id>
        <link href="https://quanscheng.vercel.app/blog/2023/12/26/useToast"/>
        <updated>2023-12-26T00:00:00.000Z</updated>
        <content type="html"><![CDATA[<div class="language-tsx codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Xkn2">ToastContext.ts</div><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-tsx codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"> createContext </span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'react'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">interface</span><span class="token plain"> </span><span class="token class-name">ToastContextProps</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  toast</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function-variable function" style="color:#d73a49">success</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">message</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> duration</span><span class="token operator" style="color:#393A34">?</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">number</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function-variable function" style="color:#d73a49">error</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">message</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> duration</span><span class="token operator" style="color:#393A34">?</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">number</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token maybe-class-name">ToastContext</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token generic-function function" style="color:#d73a49">createContext</span><span class="token generic-function generic class-name operator" style="color:#393A34">&lt;</span><span class="token generic-function generic class-name">ToastContextProps </span><span class="token generic-function generic class-name operator" style="color:#393A34">|</span><span class="token generic-function generic class-name"> </span><span class="token generic-function generic class-name keyword" style="color:#00009f">undefined</span><span class="token generic-function generic class-name operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">undefined</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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-ts codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Xkn2">emitter.ts</div><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-ts codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> mitt </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'mitt'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> emitter </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">mitt</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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-tsx codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Xkn2">GlobalToastProvider.tsx</div><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-tsx codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"> </span><span class="token imports maybe-class-name">Toast</span><span class="token imports"> </span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@shopify/polaris'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"> useEffect</span><span class="token imports punctuation" style="color:#393A34">,</span><span class="token imports"> useMemo</span><span class="token imports punctuation" style="color:#393A34">,</span><span class="token imports"> useState </span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'react'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"> uniqueCode </span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'../../utils'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"> </span><span class="token imports maybe-class-name">ToastContext</span><span class="token imports"> </span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'./ToastContext'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"> emitter </span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'./emitter'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * Toasts 传参</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">type</span><span class="token plain"> </span><span class="token class-name">ToastsProps</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">/** 前端生成的唯一id */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  id</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">/** toast 内容 */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  message</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">/** toast 类型 */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  type</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'success'</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'error'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">/** toast 持续时间 */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  duration</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">number</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">/** 插入队列的时间 */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  createdAt</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Date</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token function-variable function" style="color:#d73a49">GlobalToastProvider</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  children</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  children</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token maybe-class-name">React</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access maybe-class-name">ReactNode</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">/** toasts 队列 */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">toasts</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> setToasts</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token generic-function function" style="color:#d73a49">useState</span><span class="token generic-function generic class-name operator" style="color:#393A34">&lt;</span><span class="token generic-function generic class-name">ToastsProps</span><span class="token generic-function generic class-name punctuation" style="color:#393A34">[</span><span class="token generic-function generic class-name punctuation" style="color:#393A34">]</span><span class="token generic-function generic class-name operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">/** 唤起成功的 toast */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token function-variable function" style="color:#d73a49">toastSuccess</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">message</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> duration </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">5000</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> newToast</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token maybe-class-name">ToastsProps</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      id</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">uniqueCode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'toast_success'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      type</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'success'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      message</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      duration</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      createdAt</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Date</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 记录插入队列的时间</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">setToasts</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">prevToasts</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token spread operator" style="color:#393A34">...</span><span class="token plain">prevToasts</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> newToast</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">/** 唤起错误的 toast */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token function-variable function" style="color:#d73a49">toastError</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">message</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> duration </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">5000</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> newToast</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token maybe-class-name">ToastsProps</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      id</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">uniqueCode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'toast_error'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      type</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'error'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      message</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      duration</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      createdAt</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Date</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 记录插入队列的时间</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">setToasts</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">prevToasts</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token spread operator" style="color:#393A34">...</span><span class="token plain">prevToasts</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> newToast</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">/** toast 唤起函数 */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> toastHandler </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useMemo</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      success</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> toastSuccess</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      error</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> toastError</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">/** 移除 toast */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token function-variable function" style="color:#d73a49">dismissToast</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">id</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">setToasts</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">prevToasts</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> prevToasts</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">filter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">toast</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> toast</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">id</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">!==</span><span class="token plain"> id</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">/** 定时器根据入队时间和 duration 比较确定 toast 存在时长 */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">useEffect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> timer</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token maybe-class-name">NodeJS</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access maybe-class-name">Timeout</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">toasts</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">length</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">===</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    timer </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">setInterval</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> now </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Date</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> updatedToasts </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> toasts</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">filter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">toast</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> now</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">getTime</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token plain"> toast</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">createdAt</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">getTime</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain"> toast</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">duration</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token function" style="color:#d73a49">setToasts</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">updatedToasts</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1000</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token function" style="color:#d73a49">clearInterval</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">timer</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">toasts</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">useEffect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    emitter</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">on</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'toaster.error'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">e</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">any</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      toastHandler</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">e</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">message</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">duration</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    emitter</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">on</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'toaster.success'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">e</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">any</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      toastHandler</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">success</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">e</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">message</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">duration</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      emitter</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">all</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">clear</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">toastHandler</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">ToastContext.Provider</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">value</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:#393A34">=</span><span class="token tag script language-javascript punctuation" style="color:#393A34">{</span><span class="token tag script language-javascript punctuation" style="color:#393A34">{</span><span class="token tag script language-javascript" style="color:#00009f"> toast</span><span class="token tag script language-javascript operator" style="color:#393A34">:</span><span class="token tag script language-javascript" style="color:#00009f"> toastHandler </span><span class="token tag script language-javascript punctuation" style="color:#393A34">}</span><span class="token tag script language-javascript punctuation" style="color:#393A34">}</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">      </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">children</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">      </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">toasts</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">map</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">item</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">Toast</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">          </span><span class="token tag attr-name" style="color:#00a4db">key</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:#393A34">=</span><span class="token tag script language-javascript punctuation" style="color:#393A34">{</span><span class="token tag script language-javascript" style="color:#00009f">item</span><span class="token tag script language-javascript punctuation" style="color:#393A34">.</span><span class="token tag script language-javascript property-access" style="color:#00009f">id</span><span class="token tag script language-javascript punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">          </span><span class="token tag attr-name" style="color:#00a4db">content</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:#393A34">=</span><span class="token tag script language-javascript punctuation" style="color:#393A34">{</span><span class="token tag script language-javascript" style="color:#00009f">item</span><span class="token tag script language-javascript punctuation" style="color:#393A34">.</span><span class="token tag script language-javascript property-access" style="color:#00009f">message</span><span class="token tag script language-javascript punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">          </span><span class="token tag attr-name" style="color:#00a4db">onDismiss</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:#393A34">=</span><span class="token tag script language-javascript punctuation" style="color:#393A34">{</span><span class="token tag script language-javascript punctuation" style="color:#393A34">(</span><span class="token tag script language-javascript punctuation" style="color:#393A34">)</span><span class="token tag script language-javascript" style="color:#00009f"> </span><span class="token tag script language-javascript arrow operator" style="color:#393A34">=&gt;</span><span class="token tag script language-javascript" style="color:#00009f"> </span><span class="token tag script language-javascript function" style="color:#d73a49">dismissToast</span><span class="token tag script language-javascript punctuation" style="color:#393A34">(</span><span class="token tag script language-javascript" style="color:#00009f">item</span><span class="token tag script language-javascript punctuation" style="color:#393A34">.</span><span class="token tag script language-javascript property-access" style="color:#00009f">id</span><span class="token tag script language-javascript punctuation" style="color:#393A34">)</span><span class="token tag script language-javascript punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">          </span><span class="token tag attr-name" style="color:#00a4db">error</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:#393A34">=</span><span class="token tag script language-javascript punctuation" style="color:#393A34">{</span><span class="token tag script language-javascript" style="color:#00009f">item</span><span class="token tag script language-javascript punctuation" style="color:#393A34">.</span><span class="token tag script language-javascript property-access" style="color:#00009f">type</span><span class="token tag script language-javascript" style="color:#00009f"> </span><span class="token tag script language-javascript operator" style="color:#393A34">===</span><span class="token tag script language-javascript" style="color:#00009f"> </span><span class="token tag script language-javascript string" style="color:#e3116c">'error'</span><span class="token tag script language-javascript punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">        </span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">    </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag class-name" style="color:#00009f">ToastContext.Provider</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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-ts codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Xkn2">useToast</div><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-ts codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> useContext </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'react'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> ToastContext </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'./ToastContext'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">type</span><span class="token plain"> </span><span class="token class-name">useToastValue</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function-variable function" style="color:#d73a49">success</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">message</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> duration</span><span class="token operator" style="color:#393A34">?</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">number</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function-variable function" style="color:#d73a49">error</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">message</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> duration</span><span class="token operator" style="color:#393A34">?</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">number</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> useToast </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> useToastValue </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> context </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useContext</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ToastContext</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">!</span><span class="token plain">context</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">throw</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token string" style="color:#e3116c">'useToast must be used within a &lt;GlobalToastProvider&gt; * &lt;/GlobalToastProvider&gt;'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> context</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">toast</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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-tsx codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Xkn2">toaster.ts</div><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-tsx codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"> emitter </span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'./emitter'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> toaster </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function-variable function" style="color:#d73a49">success</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">message</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> duration</span><span class="token operator" style="color:#393A34">?</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">number</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    emitter</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">emit</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'toaster.success'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> message</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> duration </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function-variable function" style="color:#d73a49">error</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">message</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> duration</span><span class="token operator" style="color:#393A34">?</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">number</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    emitter</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">emit</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'toaster.error'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> message</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> duration </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>]]></content>
        <author>
            <name>TransonQ</name>
            <uri>https://github.com/TransonQ</uri>
        </author>
        <category label="hooks" term="hooks"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[升级doc龙v2->v3]]></title>
        <id>https://quanscheng.vercel.app/blog/2023/11/01/update-docusaurus</id>
        <link href="https://quanscheng.vercel.app/blog/2023/11/01/update-docusaurus"/>
        <updated>2023-11-01T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[步骤]]></summary>
        <content type="html"><![CDATA[<h2 class="anchor anchorWithStickyNavbar_jjaS" id="步骤">步骤<a class="hash-link" aria-label="步骤的直接链接" title="步骤的直接链接" href="https://quanscheng.vercel.app/blog/2023/11/01/update-docusaurus#%E6%AD%A5%E9%AA%A4">​</a></h2>
<blockquote>
<p><a href="https://docusaurus.io/docs/migration/v3" target="_blank" rel="noopener noreferrer">官方升级指南</a></p>
</blockquote>
<h3 class="anchor anchorWithStickyNavbar_jjaS" id="packagejson">package.json<a class="hash-link" aria-label="package.json的直接链接" title="package.json的直接链接" href="https://quanscheng.vercel.app/blog/2023/11/01/update-docusaurus#packagejson">​</a></h3>
<div class="language-json codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-json codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain"> {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   "dependencies": {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     // upgrade to Docusaurus v3</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">-    "@docusaurus/core": "2.4.3",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">-    "@docusaurus/preset-classic": "2.4.3",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">+    "@docusaurus/core": "3.0.0",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">+    "@docusaurus/preset-classic": "3.0.0",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     // upgrade to MDX v2</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">-    "@mdx-js/react": "^1.6.22",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">+    "@mdx-js/react": "^3.0.0",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     // upgrade to prism-react-renderer v2.0+</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">-    "prism-react-renderer": "^1.3.5",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">+    "prism-react-renderer": "^2.1.0",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     // upgrade to React v18.0+</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">-    "react": "^17.0.2",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">-    "react-dom": "^17.0.2"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">+    "react": "^18.2.0",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">+    "react-dom": "^18.2.0"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   },</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   "devDependencies": {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     // upgrade Docusaurus dev dependencies to v3</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">-    "@docusaurus/module-type-aliases": "2.4.3"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">-    "@docusaurus/types": "2.4.3"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">+    "@docusaurus/module-type-aliases": "3.0.0"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">+    "@docusaurus/types": "3.0.0"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   "engines": {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     // require Node.js 18.0+</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">-    "node": "&gt;=16.14"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">+    "node": "&gt;=18.0"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> }</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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 anchorWithStickyNavbar_jjaS" id="ts项目">ts项目<a class="hash-link" aria-label="ts项目的直接链接" title="ts项目的直接链接" href="https://quanscheng.vercel.app/blog/2023/11/01/update-docusaurus#ts%E9%A1%B9%E7%9B%AE">​</a></h3>
<div class="language-json codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-json codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain"> {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   ...</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   "devDependencies": {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     // swap the external TypeScript config package for the new official one</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">-    "@tsconfig/docusaurus": "^1.0.7",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">+    "@docusaurus/tsconfig": "3.0.0",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     // upgrade React types to v18.0+</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">-    "@types/react": "^17.0.69",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">+    "@types/react": "^18.2.29",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     // upgrade TypeScript to v5.0+</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">-    "typescript": "~4.7.4"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">+    "typescript": "~5.2.2"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> }</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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 anchorWithStickyNavbar_jjaS" id="检查是否存在-v3无法编译的文件">检查是否存在 v3无法编译的文件<a class="hash-link" aria-label="检查是否存在 v3无法编译的文件的直接链接" title="检查是否存在 v3无法编译的文件的直接链接" href="https://quanscheng.vercel.app/blog/2023/11/01/update-docusaurus#%E6%A3%80%E6%9F%A5%E6%98%AF%E5%90%A6%E5%AD%98%E5%9C%A8-v3%E6%97%A0%E6%B3%95%E7%BC%96%E8%AF%91%E7%9A%84%E6%96%87%E4%BB%B6">​</a></h3>
<div class="language-js codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-js codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">npx docusaurus</span><span class="token operator" style="color:#393A34">-</span><span class="token plain">mdx</span><span class="token operator" style="color:#393A34">-</span><span class="token plain">checker</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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 anchorWithStickyNavbar_jjaS" id="prism-react-renderer-配置">Prism-React-Renderer 配置<a class="hash-link" aria-label="Prism-React-Renderer 配置的直接链接" title="Prism-React-Renderer 配置的直接链接" href="https://quanscheng.vercel.app/blog/2023/11/01/update-docusaurus#prism-react-renderer-%E9%85%8D%E7%BD%AE">​</a></h3>
<div class="language-js codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-js codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token operator" style="color:#393A34">-</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> lightTheme </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">require</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'prism-react-renderer/themes/github'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">-</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> darkTheme </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">require</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'prism-react-renderer/themes/dracula'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">themes</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">require</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'prism-react-renderer'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> lightTheme </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> themes</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">github</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> darkTheme </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> themes</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">dracula</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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>个人补上了 mermaid 支持, 案例:</p>
<!-- -->
</blockquote>]]></content>
        <author>
            <name>TransonQ</name>
            <uri>https://github.com/TransonQ</uri>
        </author>
        <category label="docusaurus" term="docusaurus"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[在Remix中使用styled-components]]></title>
        <id>https://quanscheng.vercel.app/blog/2023/10/30/remix-with-css-in-js</id>
        <link href="https://quanscheng.vercel.app/blog/2023/10/30/remix-with-css-in-js"/>
        <updated>2023-10-30T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[背景]]></summary>
        <content type="html"><![CDATA[<h2 class="anchor anchorWithStickyNavbar_jjaS" id="背景">背景<a class="hash-link" aria-label="背景的直接链接" title="背景的直接链接" href="https://quanscheng.vercel.app/blog/2023/10/30/remix-with-css-in-js#%E8%83%8C%E6%99%AF">​</a></h2>
<blockquote>
<p>最近业务开始使用remix用于开发, 相对于之前纯客户端渲染开发, <code>styled-components</code>这一高效的<code>css-in-js</code>库一直想用在ssr上面, 前段时间卡壳在于对原生node请求响应这一方向接触较少, 较为生疏的情况下, 看着人家<a href="https://styled-components.com/docs/advanced#server-side-rendering" target="_blank" rel="noopener noreferrer">styled-components SSR</a>文档看了, 原理了解了之后总结就是: 服务端渲染需要将生成的css和html从服务端发往客户端,<code>css-in-js</code>的库基本都有==避免双重渲染== 的手段. 如下就是<code>styled-components</code>收集样式后加入详情头解决方法.</p>
</blockquote>
<h2 class="anchor anchorWithStickyNavbar_jjaS" id="代码案例">代码案例<a class="hash-link" aria-label="代码案例的直接链接" title="代码案例的直接链接" href="https://quanscheng.vercel.app/blog/2023/10/30/remix-with-css-in-js#%E4%BB%A3%E7%A0%81%E6%A1%88%E4%BE%8B">​</a></h2>
<div class="language-ts codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-ts codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  createReadableStreamFromReadable</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">type</span><span class="token plain"> </span><span class="token class-name">EntryContext</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"@remix-run/node"</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> RemixServer </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"@remix-run/react"</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> isbot </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"isbot"</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> renderToPipeableStream </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"react-dom/server"</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> PassThrough </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"stream"</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> ServerStyleSheet </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"styled-components"</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 1.导入ServerStyleSheet</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> addDocumentResponseHeaders </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"./shopify.server"</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">ABORT_DELAY</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">5000</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">default</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">handleRequest</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  request</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> Request</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  responseStatusCode</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">number</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  responseHeaders</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> Headers</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  remixContext</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> EntryContext</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">addDocumentResponseHeaders</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">request</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> responseHeaders</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> callbackName </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">isbot</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">request</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">headers</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"user-agent"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"onAllReady"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"onShellReady"</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name builtin">Promise</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">resolve</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> reject</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> sheet </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ServerStyleSheet</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 2.创建ServerStyleSheet实例</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> pipe</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> abort </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">renderToPipeableStream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token comment" style="color:#999988;font-style:italic">// 3.使用collectStyles方法收集样式</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      sheet</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">collectStyles</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">RemixServer</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          context</span><span class="token operator" style="color:#393A34">=</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">remixContext</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          url</span><span class="token operator" style="color:#393A34">=</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">request</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">url</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          abortDelay</span><span class="token operator" style="color:#393A34">=</span><span class="token punctuation" style="color:#393A34">{</span><span class="token constant" style="color:#36acaa">ABORT_DELAY</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token operator" style="color:#393A34">/</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">callbackName</span><span class="token punctuation" style="color:#393A34">]</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> body </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">PassThrough</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> stream </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">createReadableStreamFromReadable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">body</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> styleTags </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> sheet</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getStyleTags</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 4.获取样式标签</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          responseHeaders</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">set</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Content-Type"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"text/html"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          responseHeaders</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">set</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Link"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> styleTags</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 5.将样式标签添加到响应头中</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token function" style="color:#d73a49">resolve</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Response</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">stream</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">              headers</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> responseHeaders</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">              status</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> responseStatusCode</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token function" style="color:#d73a49">pipe</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">body</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">onShellError</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">error</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token function" style="color:#d73a49">reject</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">error</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">onError</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">error</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          responseStatusCode </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">500</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token builtin">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">error</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">setTimeout</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">abort</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">ABORT_DELAY</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>]]></content>
        <author>
            <name>TransonQ</name>
            <uri>https://github.com/TransonQ</uri>
        </author>
        <category label="remix" term="remix"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[图解 RSC]]></title>
        <id>https://quanscheng.vercel.app/blog/2023/08/04/Illustrated-RSC</id>
        <link href="https://quanscheng.vercel.app/blog/2023/08/04/Illustrated-RSC"/>
        <updated>2023-08-04T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[一 . 最开始 : PHP 时代]]></summary>
        <content type="html"><![CDATA[<h2 class="anchor anchorWithStickyNavbar_jjaS" id="一--最开始--php-时代">一 . 最开始 : PHP 时代<a class="hash-link" aria-label="一 . 最开始 : PHP 时代的直接链接" title="一 . 最开始 : PHP 时代的直接链接" href="https://quanscheng.vercel.app/blog/2023/08/04/Illustrated-RSC#%E4%B8%80--%E6%9C%80%E5%BC%80%E5%A7%8B--php-%E6%97%B6%E4%BB%A3">​</a></h2>
<p><img decoding="async" loading="lazy" alt="1" src="https://quanscheng.vercel.app/assets/images/1-5b248ce966493eecc2faebd19000b6ec.webp" width="1920" height="1087" class="img_PD5j"></p>
<h2 class="anchor anchorWithStickyNavbar_jjaS" id="二--更多交互--csr-时代">二 . 更多交互 : CSR 时代<a class="hash-link" aria-label="二 . 更多交互 : CSR 时代的直接链接" title="二 . 更多交互 : CSR 时代的直接链接" href="https://quanscheng.vercel.app/blog/2023/08/04/Illustrated-RSC#%E4%BA%8C--%E6%9B%B4%E5%A4%9A%E4%BA%A4%E4%BA%92--csr-%E6%97%B6%E4%BB%A3">​</a></h2>
<blockquote>
<p>客户端渲染会收到渲染网站所需的js</p>
</blockquote>
<p><img decoding="async" loading="lazy" alt="2" src="https://quanscheng.vercel.app/assets/images/2-aa95b4c38ab95b6f89bbef1e9c5a4d4b.webp" width="1920" height="1522" class="img_PD5j"></p>
<blockquote>
<p>客户端已经具备渲染代码, 从而不需要跟服务器通信</p>
</blockquote>
<p><img decoding="async" loading="lazy" alt="3" src="https://quanscheng.vercel.app/assets/images/3-f987ec6da900f7cea409acedbfb5ec85.webp" width="1920" height="1324" class="img_PD5j"></p>
<h2 class="anchor anchorWithStickyNavbar_jjaS" id="三--更好的-seo-服务端渲染ssr静态站点生成ssg">三 . 更好的 SEO: 服务端渲染(SSR)/静态站点生成(SSG)<a class="hash-link" aria-label="三 . 更好的 SEO: 服务端渲染(SSR)/静态站点生成(SSG)的直接链接" title="三 . 更好的 SEO: 服务端渲染(SSR)/静态站点生成(SSG)的直接链接" href="https://quanscheng.vercel.app/blog/2023/08/04/Illustrated-RSC#%E4%B8%89--%E6%9B%B4%E5%A5%BD%E7%9A%84-seo-%E6%9C%8D%E5%8A%A1%E7%AB%AF%E6%B8%B2%E6%9F%93ssr%E9%9D%99%E6%80%81%E7%AB%99%E7%82%B9%E7%94%9F%E6%88%90ssg">​</a></h2>
<blockquote>
<p>客户端可以短时间看到静态网页, 但是需要更多时间加载js和 hydrate</p>
</blockquote>
<p><img decoding="async" loading="lazy" alt="4" src="https://quanscheng.vercel.app/assets/images/4-b895a64119980e04255828216204d255.webp" width="1920" height="1445" class="img_PD5j"></p>
<blockquote>
<p>后续导航跟CSR一样, SSR拥有显示下一页所需要的所有渲染代码, 因此切换速度很快</p>
</blockquote>
<p><img decoding="async" loading="lazy" alt="5" src="https://quanscheng.vercel.app/assets/images/5-80bd5feab1c1ef7a74b3b3b48e4d17f4.webp" width="1920" height="1324" class="img_PD5j"></p>
<blockquote>
<p>问题 : 大多数 SSR/SSG 方法将<em>用于生成页面的所有 JavaScript</em>发送到客户端，然后客户端<em>再次运行所有内容</em>，并将该 HTML 与刚刚启动的 JavaScript 结合起来。我们真的需要发送并运行所有 JavaScript 吗？我们真的需要重复所有渲染工作只是为了水合吗？如果服务器端渲染需要很长时间怎么办？</p>
</blockquote>
<h2 class="anchor anchorWithStickyNavbar_jjaS" id="四--react-server-component">四 . React Server Component<a class="hash-link" aria-label="四 . React Server Component的直接链接" title="四 . React Server Component的直接链接" href="https://quanscheng.vercel.app/blog/2023/08/04/Illustrated-RSC#%E5%9B%9B--react-server-component">​</a></h2>
<ol>
<li>
<p>可以此定义哪些组件代码需要在服务器运行</p>
</li>
<li>
<p>服务器组件可以<em>直接从组件内部</em>获取数据。获取完成后，服务器组件可以将该数据<em>流式传输</em>到客户端。</p>
</li>
<li>
<p>加载慢的服务器组件,可以有单独的加载, 其他并不影响</p>
</li>
</ol>
<p><img decoding="async" loading="lazy" alt="7" src="https://quanscheng.vercel.app/assets/images/7-c3e225e7811ab306f18549e4ff495977.gif" width="1456" height="880" class="img_PD5j"></p>]]></content>
        <author>
            <name>TransonQ</name>
            <uri>https://github.com/TransonQ</uri>
        </author>
        <category label="RSC" term="RSC"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[swr取消请求hook封装]]></title>
        <id>https://quanscheng.vercel.app/blog/2023/07/04/swr取消请求hook封装</id>
        <link href="https://quanscheng.vercel.app/blog/2023/07/04/swr取消请求hook封装"/>
        <updated>2023-07-04T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[issue-129-comment]]></summary>
        <content type="html"><![CDATA[<div class="language-js codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-js codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useCancellableSWR</span><span class="token punctuation" style="color:#393A34">(</span><span class="token parameter">key</span><span class="token parameter punctuation" style="color:#393A34">,</span><span class="token parameter"> swrOptions</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> source </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> axios</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access maybe-class-name">CancelToken</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">source</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">useSWR</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">key</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token parameter">url</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> axios</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">url</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token literal-property property" style="color:#36acaa">cancelToken</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> source</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">token</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">then</span><span class="token punctuation" style="color:#393A34">(</span><span class="token parameter">res</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> res</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">data</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token spread operator" style="color:#393A34">...</span><span class="token plain">swrOptions</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    source</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// usage:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> data </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> cancelFn</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useCancellableSWR</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'/endpoint'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">cancelFn</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">cancel</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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/vercel/swr/issues/129#issuecomment-608995613" target="_blank" rel="noopener noreferrer">issue-129-comment</a></p>]]></content>
        <author>
            <name>TransonQ</name>
            <uri>https://github.com/TransonQ</uri>
        </author>
        <category label="swr" term="swr"/>
        <category label="axios" term="axios"/>
        <category label="hooks" term="hooks"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[流行框架中hydration和resumability对比]]></title>
        <id>https://quanscheng.vercel.app/blog/2023/06/15/hydration-resumability</id>
        <link href="https://quanscheng.vercel.app/blog/2023/06/15/hydration-resumability"/>
        <updated>2023-06-15T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[流行框架中hydration和resumability对比]]></summary>
        <content type="html"><![CDATA[<p><img decoding="async" loading="lazy" alt="流行框架中hydration和resumability对比" src="https://quanscheng.vercel.app/assets/images/%E6%B5%81%E8%A1%8C%E6%A1%86%E6%9E%B6%E4%B8%ADhydration%E5%92%8Cresumability%E5%AF%B9%E6%AF%94-4e5e75f501726f9cb4feba35bc664225.webp" width="1100" height="605" class="img_PD5j"></p>
<h2 class="anchor anchorWithStickyNavbar_jjaS" id="hydration">hydration<a class="hash-link" aria-label="hydration的直接链接" title="hydration的直接链接" href="https://quanscheng.vercel.app/blog/2023/06/15/hydration-resumability#hydration">​</a></h2>
<p>当 React、Vue、Svelte 或 Angular 等 SPA 框架添加了 SSR 支持时，水合作为一种算法首次出现。为了使这些框架在浏览器中变得交互式，它们必须从根 () 重新执行整个应用程序，以恢复序列化为 HTML (renderToString) 时丢失的状态和事件处理程序。</p>
<p>所有水合实现都将单个组件作为根（通常是 ），为了使其具有交互性，树中的每个组件都必须执行。只有在设置了事件处理程序之后，用户才能与其交互。</p>
<p>水合作用只能通过向先前在服务器中执行的组件树添加交互性的过程来理解。这是一个 O(n) 算法，其中 N 是要唤醒的组件数量。</p>
<p><img decoding="async" loading="lazy" alt="hydration" src="https://quanscheng.vercel.app/assets/images/hydration-c63871a1bdb6a1319bd2918b06b1d466.gif" width="640" height="480" class="img_PD5j"></p>
<h2 class="anchor anchorWithStickyNavbar_jjaS" id="partial-hydration">partial hydration<a class="hash-link" aria-label="partial hydration的直接链接" title="partial hydration的直接链接" href="https://quanscheng.vercel.app/blog/2023/06/15/hydration-resumability#partial-hydration">​</a></h2>
<p>Astro 框架凸显了部分水合的概念，它源于这样的理解：并非树的所有部分都需要水合，特别是那些完全静态的部分。这种方法建立了“交互岛”，减少了浏览器的工作负载，从而实现更快的交互。</p>
<p>部分水合正是这样的：在不同时刻多次调用 HydroRoot()，所以这个名字很合适。</p>
<p>然而，必须强调的是，这些“交互岛”需要由开发人员手动创建。此外，这些岛会创建边界，这意味着每个岛都作为独立的子应用程序运行，这可能会阻碍应用程序不同部分之间的通信。</p>
<p><img decoding="async" loading="lazy" alt="partial_hydration" src="https://quanscheng.vercel.app/assets/images/partial_hydration-c8cd4c2ce8ecc1f2762ff3fbb8337ebf.gif" width="640" height="480" class="img_PD5j"></p>
<h2 class="anchor anchorWithStickyNavbar_jjaS" id="react-server-component-is-hydration">React Server Component is hydration<a class="hash-link" aria-label="React Server Component is hydration的直接链接" title="React Server Component is hydration的直接链接" href="https://quanscheng.vercel.app/blog/2023/06/15/hydration-resumability#react-server-component-is-hydration">​</a></h2>
<p>就像部分水合一样，RSC 是具有不同姓氏的水合，我们可以将其称为稀疏水合(<strong>Sparse Hydration</strong>)。</p>
<p>RSC 没有创建孤立的岛屿，而是维护单个根，允许组件相互通信。但是，根目录中的“服务器组件”不需要在浏览器中重新执行。相反，React 将这些组件的 vNode 作为数据序列化到 HTML 中。这是一种时空权衡(<a href="https://zh.wikipedia.org/wiki/%E6%97%B6%E7%A9%BA%E6%9D%83%E8%A1%A1" target="_blank" rel="noopener noreferrer">Space–time tradeoff</a>)。</p>
<p>就像孤岛架构一样，开发人员必须努力使用“使用服务器”或“使用客户端”指令在 React 服务器组件中设置边界。</p>
<p><img decoding="async" loading="lazy" alt="React Server Component is hydration" src="https://quanscheng.vercel.app/assets/images/React%20Server%20Component%20is%20hydration-7ff51ee48ae123ee1091de65400d6186.gif" width="640" height="480" class="img_PD5j"></p>
<h2 class="anchor anchorWithStickyNavbar_jjaS" id="可恢复性resumability本质上是一种不同的算法">可恢复性(Resumability)本质上是一种不同的算法<a class="hash-link" aria-label="可恢复性(Resumability)本质上是一种不同的算法的直接链接" title="可恢复性(Resumability)本质上是一种不同的算法的直接链接" href="https://quanscheng.vercel.app/blog/2023/06/15/hydration-resumability#%E5%8F%AF%E6%81%A2%E5%A4%8D%E6%80%A7resumability%E6%9C%AC%E8%B4%A8%E4%B8%8A%E6%98%AF%E4%B8%80%E7%A7%8D%E4%B8%8D%E5%90%8C%E7%9A%84%E7%AE%97%E6%B3%95">​</a></h2>
<p>(Resumability is fundamentally a different algorithm) 最后，我们深入研究了可恢复性，这是一种提倡即时交互性的范例，无需水合或爬行组件。它完全脱离了树结构。</p>
<p>可恢复性的独特之处在于根（或入口点）是事件处理程序，而不是组件。</p>
<p>在传统的水合、部分水合和 React Server 组件中，组件充当根。对于部分水合，您可能有多个根，而对于 React Server 组件，您只有一个根。</p>
<p>另一方面，可恢复性将事件处理程序置于根位置。箭头从事件指向组件，表明不需要运行任何用户代码，即使对于可以重新渲染的组件也是如此。这种方法有效地将所有组件视为静态的，无论它们是否是静态的。</p>
<p><img decoding="async" loading="lazy" alt="Resumability" src="https://quanscheng.vercel.app/assets/images/Resumability-55c318bf36e377fa29d67de7ee311999.gif" width="640" height="480" class="img_PD5j"></p>
<blockquote>
<p>参考原文</p>
<p><a href="https://www.builder.io/blog/hydration-tree-resumability-map" target="_blank" rel="noopener noreferrer">hydration-tree-resumability-map</a></p>
</blockquote>]]></content>
        <author>
            <name>TransonQ</name>
            <uri>https://github.com/TransonQ</uri>
        </author>
        <category label="hydration" term="hydration"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Docusaurus2 使用 Algolia DocSearch]]></title>
        <id>https://quanscheng.vercel.app/blog/2023/06/14/doc龙配置搜索</id>
        <link href="https://quanscheng.vercel.app/blog/2023/06/14/doc龙配置搜索"/>
        <updated>2023-06-14T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[指引]]></summary>
        <content type="html"><![CDATA[<h2 class="anchor anchorWithStickyNavbar_jjaS" id="指引">指引<a class="hash-link" aria-label="指引的直接链接" title="指引的直接链接" href="https://quanscheng.vercel.app/blog/2023/06/14/doc%E9%BE%99%E9%85%8D%E7%BD%AE%E6%90%9C%E7%B4%A2#%E6%8C%87%E5%BC%95">​</a></h2>
<p><a href="https://docusaurus.io/zh-CN/docs/search" target="_blank" rel="noopener noreferrer">链接: 使用 Algolia DocSearch 官方指引</a></p>
<p><a href="https://docsearch.algolia.com/apply/" target="_blank" rel="noopener noreferrer">链接: 申请 DocSearch</a></p>
<p>提交后大约 1-2 天内会收到 反馈邮件, 通知注册成功. 然后登录到 <a href="https://dashboard.algolia.com/" target="_blank" rel="noopener noreferrer">个人中心</a></p>
<p><img decoding="async" loading="lazy" alt="AlgoliaDocSearch-1" src="https://quanscheng.vercel.app/assets/images/AlgoliaDocSearch-1-668ba6ddf78ccf2ead2fe803785c6e38.png" width="768" height="955" class="img_PD5j"></p>
<p><img decoding="async" loading="lazy" alt="AlgoliaDocSearch-2" src="https://quanscheng.vercel.app/assets/images/AlgoliaDocSearch-2-57ead9612a5c3518251719fadac981ec.png" width="1272" height="693" class="img_PD5j"></p>
<p><img decoding="async" loading="lazy" alt="AlgoliaDocSearch-3" src="https://quanscheng.vercel.app/assets/images/AlgoliaDocSearch-3-6df35a9ce67ac4518c53780c76f9bf28.png" width="1017" height="965" class="img_PD5j"></p>
<h2 class="anchor anchorWithStickyNavbar_jjaS" id="配置">配置<a class="hash-link" aria-label="配置的直接链接" title="配置的直接链接" href="https://quanscheng.vercel.app/blog/2023/06/14/doc%E9%BE%99%E9%85%8D%E7%BD%AE%E6%90%9C%E7%B4%A2#%E9%85%8D%E7%BD%AE">​</a></h2>
<div class="language-json codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Xkn2">docusaurus.config.js</div><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-json codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">algolia: {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  // The application ID provided by Algolia</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  appId: '',</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  // Public API key: it is safe to commit it</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  apiKey: '',</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  // algolia application name</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  indexName: '',</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  // ... ...</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">},</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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 decoding="async" loading="lazy" alt="AlgoliaDocSearch-4" src="https://quanscheng.vercel.app/assets/images/AlgoliaDocSearch-4-dde92a525ccb29c9d3be472623149cb7.png" width="1027" height="609" class="img_PD5j"></p>]]></content>
        <author>
            <name>TransonQ</name>
            <uri>https://github.com/TransonQ</uri>
        </author>
        <category label="docusaurus2" term="docusaurus2"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[vite部署线上报MIME类型错误]]></title>
        <id>https://quanscheng.vercel.app/blog/2023/06/07/vite-amplify</id>
        <link href="https://quanscheng.vercel.app/blog/2023/06/07/vite-amplify"/>
        <updated>2023-06-07T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[错误如下]]></summary>
        <content type="html"><![CDATA[<h2 class="anchor anchorWithStickyNavbar_jjaS" id="错误如下">错误如下<a class="hash-link" aria-label="错误如下的直接链接" title="错误如下的直接链接" href="https://quanscheng.vercel.app/blog/2023/06/07/vite-amplify#%E9%94%99%E8%AF%AF%E5%A6%82%E4%B8%8B">​</a></h2>
<div class="codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-text codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "application/octet-stream".  Strict MIME type checking is enforced for module scripts per HTML spec.</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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 anchorWithStickyNavbar_jjaS" id="配置文件解决">配置文件解决<a class="hash-link" aria-label="配置文件解决的直接链接" title="配置文件解决的直接链接" href="https://quanscheng.vercel.app/blog/2023/06/07/vite-amplify#%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E8%A7%A3%E5%86%B3">​</a></h2>
<blockquote>
<p>注意: 添加头的方法在 <code>amplify.yml</code> 可能有用, 但是主要是看你构建目录是否正确, 亚马逊配置如果目录不对, 有时候可以构建成功! Vite 默认构建目录是 <code>dist</code> , CRA默认构建目录是 <code>build</code></p>
</blockquote>
<p>使用“customHeaders”属性配置了所有 JavaScript 文件的 MIME 类型为“application/javascript”。</p>
<p><img decoding="async" loading="lazy" alt="vite-amplify-error.png" src="https://quanscheng.vercel.app/assets/images/vite-amplify-error-a547acfc4f6c2c72a90c14c9b3229390.png" width="1362" height="1164" class="img_PD5j"></p>
<h2 class="anchor anchorWithStickyNavbar_jjaS" id="nginx解决">nginx解决<a class="hash-link" aria-label="nginx解决的直接链接" title="nginx解决的直接链接" href="https://quanscheng.vercel.app/blog/2023/06/07/vite-amplify#nginx%E8%A7%A3%E5%86%B3">​</a></h2>
<div class="codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-text codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">types {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    application/javascript  js;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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://kas.kim/blog/failed-to-load-module-script" target="_blank" rel="noopener noreferrer">解决方法</a></p>
<div class="codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-text codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">sudo vi /etc/nginx/mime.types</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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="codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-text codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">application/javascript js</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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="codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-text codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">application/javascript js mjs</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>重启nginx</p>
<div class="codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-text codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">sudo nginx -s reload</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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 anchorWithStickyNavbar_jjaS" id="apache-服务器解决">Apache 服务器解决<a class="hash-link" aria-label="Apache 服务器解决的直接链接" title="Apache 服务器解决的直接链接" href="https://quanscheng.vercel.app/blog/2023/06/07/vite-amplify#apache-%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%A7%A3%E5%86%B3">​</a></h2>
<div class="codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-text codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">AddType application/javascript .js</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>]]></content>
        <author>
            <name>TransonQ</name>
            <uri>https://github.com/TransonQ</uri>
        </author>
        <category label="vite" term="vite"/>
        <category label="amplify" term="amplify"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[vite-react-ts]]></title>
        <id>https://quanscheng.vercel.app/blog/2023/06/07/vite-react-ts-start</id>
        <link href="https://quanscheng.vercel.app/blog/2023/06/07/vite-react-ts-start"/>
        <updated>2023-06-07T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[包管理器]]></summary>
        <content type="html"><![CDATA[<h2 class="anchor anchorWithStickyNavbar_jjaS" id="包管理器">包管理器<a class="hash-link" aria-label="包管理器的直接链接" title="包管理器的直接链接" href="https://quanscheng.vercel.app/blog/2023/06/07/vite-react-ts-start#%E5%8C%85%E7%AE%A1%E7%90%86%E5%99%A8">​</a></h2>
<p>如果使用<code>yarn</code>安装, 新版本 yarn 管理会把下载的包管理至.yarn 文件夹,node_modules 里面基本就是链接的形式, 所以会出现下面的情况, ==正常运行,但是 ts 服务器检测不到包==:</p>
<p><img decoding="async" loading="lazy" alt="vite-react-ts-01-yarn.png" src="https://quanscheng.vercel.app/assets/images/vite-react-ts-01-yarn-11b1a6aaa39a8fa9e00d96488d65824c.png" width="1794" height="738" class="img_PD5j"></p>
<p>使用<code>npm</code>或者<code>pnpm</code>就没有这个问题.</p>
<h2 class="anchor anchorWithStickyNavbar_jjaS" id="关于软硬链接的知识">关于软/硬链接的知识<a class="hash-link" aria-label="关于软/硬链接的知识的直接链接" title="关于软/硬链接的知识的直接链接" href="https://quanscheng.vercel.app/blog/2023/06/07/vite-react-ts-start#%E5%85%B3%E4%BA%8E%E8%BD%AF%E7%A1%AC%E9%93%BE%E6%8E%A5%E7%9A%84%E7%9F%A5%E8%AF%86">​</a></h2>
<p><a href="https://mp.weixin.qq.com/s/IQjgzwFHDdXeTMG3GZunzw" target="_blank" rel="noopener noreferrer">从pnpm来看软硬链接的应用</a></p>
<p><a href="https://mp.weixin.qq.com/s/7gwJZruwCbKwxqWlXvA3fQ" target="_blank" rel="noopener noreferrer">一文带你深度理解pnpm</a></p>]]></content>
        <author>
            <name>TransonQ</name>
            <uri>https://github.com/TransonQ</uri>
        </author>
        <category label="vite" term="vite"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[vscode中自定义peacock插件]]></title>
        <id>https://quanscheng.vercel.app/blog/2023/06/02/vscode-peacock</id>
        <link href="https://quanscheng.vercel.app/blog/2023/06/02/vscode-peacock"/>
        <updated>2023-06-02T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[安装]]></summary>
        <content type="html"><![CDATA[<h2 class="anchor anchorWithStickyNavbar_jjaS" id="安装">安装<a class="hash-link" aria-label="安装的直接链接" title="安装的直接链接" href="https://quanscheng.vercel.app/blog/2023/06/02/vscode-peacock#%E5%AE%89%E8%A3%85">​</a></h2>
<p><a href="https://marketplace.visualstudio.com/items?itemName=johnpapa.vscode-peacock" target="_blank" rel="noopener noreferrer">扩展市场: peacock</a></p>
<h2 class="anchor anchorWithStickyNavbar_jjaS" id="配置">配置<a class="hash-link" aria-label="配置的直接链接" title="配置的直接链接" href="https://quanscheng.vercel.app/blog/2023/06/02/vscode-peacock#%E9%85%8D%E7%BD%AE">​</a></h2>
<p>因为一般都有自己喜欢的主题, 我使用的是暗色主题 <a href="https://marketplace.visualstudio.com/items?itemName=teabyii.ayu" target="_blank" rel="noopener noreferrer">Ayu</a>,所以默认配置是把侧边栏,状态栏,标题栏都换了颜色, 有点扎眼, 不过由于右下角的remote标志是比较亮的颜色, 所以就配置成底部状态栏颜色区分,就比较舒服了.</p>
<p><img decoding="async" loading="lazy" alt="peacock-setting-1.png" src="https://quanscheng.vercel.app/assets/images/peacock-setting-1-c2f4b00007bad33af3de9958102ab41a.png" width="1988" height="564" class="img_PD5j"></p>
<h3 class="anchor anchorWithStickyNavbar_jjaS" id="只设置状态栏">只设置状态栏<a class="hash-link" aria-label="只设置状态栏的直接链接" title="只设置状态栏的直接链接" href="https://quanscheng.vercel.app/blog/2023/06/02/vscode-peacock#%E5%8F%AA%E8%AE%BE%E7%BD%AE%E7%8A%B6%E6%80%81%E6%A0%8F">​</a></h3>
<p><img decoding="async" loading="lazy" alt="peacock-setting-2.png" src="https://quanscheng.vercel.app/assets/images/peacock-setting-2-a3e825a4bf2f990d3632c2e5f5f4538f.png" width="2014" height="1184" class="img_PD5j"></p>
<h3 class="anchor anchorWithStickyNavbar_jjaS" id="配置预设颜色">配置预设颜色<a class="hash-link" aria-label="配置预设颜色的直接链接" title="配置预设颜色的直接链接" href="https://quanscheng.vercel.app/blog/2023/06/02/vscode-peacock#%E9%85%8D%E7%BD%AE%E9%A2%84%E8%AE%BE%E9%A2%9C%E8%89%B2">​</a></h3>
<p><img decoding="async" loading="lazy" alt="peacock-setting-3.png" src="https://quanscheng.vercel.app/assets/images/peacock-setting-3-5156eea24dcc8e64bd4e0bcb1d06533b.png" width="2308" height="1012" class="img_PD5j"></p>
<div class="language-json codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-json codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain"> "peacock.favoriteColors": [</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      "name": "漩涡鸣人",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      "value": "#ff8906"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    },</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      "name": "宇智波佐助",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      "value": "#6246ea"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    },</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      "name": "春野樱",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      "value": "#fec7d7"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    },</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      "name": "旗木卡卡西",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      "value": "#078080"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    },</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      "name": "日向雏田",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      "value": "#bae8e8"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    },</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      "name": "Node Green",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      "value": "#215732"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    },</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      "name": "雾霾蓝",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      "value": "#232946"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    },</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      "name": "尘埃灰",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      "value": "#72757e"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    },</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      "name": "森林绿",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      "value": "#00473e"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    },</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      "name": "星空黑",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      "value": "#0f0e17"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    },</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      "name": "原野绿",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      "value": "#215732"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    },</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  ],</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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 anchorWithStickyNavbar_jjaS" id="设置成功">设置成功<a class="hash-link" aria-label="设置成功的直接链接" title="设置成功的直接链接" href="https://quanscheng.vercel.app/blog/2023/06/02/vscode-peacock#%E8%AE%BE%E7%BD%AE%E6%88%90%E5%8A%9F">​</a></h2>
<p><img decoding="async" loading="lazy" alt="peacock-setting-4.png" src="https://quanscheng.vercel.app/assets/images/peacock-setting-4-45347b16696fbe46abc0a70ab76d8460.png" width="1262" height="392" class="img_PD5j"></p>]]></content>
        <author>
            <name>TransonQ</name>
            <uri>https://github.com/TransonQ</uri>
        </author>
        <category label="vscode" term="vscode"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[window.location]]></title>
        <id>https://quanscheng.vercel.app/blog/2023/06/01/widow-location</id>
        <link href="https://quanscheng.vercel.app/blog/2023/06/01/widow-location"/>
        <updated>2023-06-01T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[window.location对象是一个包含当前页面URL信息的对象。]]></summary>
        <content type="html"><![CDATA[<p><code>window.location</code>对象是一个包含当前页面URL信息的对象。</p>
<div class="language-js codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-js codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string-property property" style="color:#36acaa">"href"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"https://transon.netlify.app/blog/2023-05-24-download-blob#typescript-%E7%89%88%E6%9C%AC"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string-property property" style="color:#36acaa">"protocol"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"https:"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string-property property" style="color:#36acaa">"host"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"transon.netlify.app"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string-property property" style="color:#36acaa">"hostname"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"transon.netlify.app"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string-property property" style="color:#36acaa">"port"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string-property property" style="color:#36acaa">"pathname"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"/blog/2023-05-24-download-blob"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string-property property" style="color:#36acaa">"search"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string-property property" style="color:#36acaa">"hash"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"#typescript-%E7%89%88%E6%9C%AC"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string-property property" style="color:#36acaa">"origin"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"https://transon.netlify.app"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function-variable function" style="color:#d73a49">assign</span><span class="token operator" style="color:#393A34">:</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function-variable function" style="color:#d73a49">reload</span><span class="token operator" style="color:#393A34">:</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function-variable function" style="color:#d73a49">replace</span><span class="token operator" style="color:#393A34">:</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string-property property" style="color:#36acaa">"ancestorOrigins"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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 anchorWithStickyNavbar_jjaS" id="1-href">1. <code>.href</code><a class="hash-link" aria-label="1-href的直接链接" title="1-href的直接链接" href="https://quanscheng.vercel.app/blog/2023/06/01/widow-location#1-href">​</a></h2>
<p><code>href</code>属性返回当前页面的URL地址，可以读取和设置。例如：</p>
<div class="language-js codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-js codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 获取当前页面的URL地址</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">var</span><span class="token plain"> url </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token dom variable" style="color:#36acaa">window</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">location</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">href</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">url</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 通过设置href属性来重定向页面</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token dom variable" style="color:#36acaa">window</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">location</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">href</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"http://www.example.com"</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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 anchorWithStickyNavbar_jjaS" id="2-protocol">2. <code>.protocol</code><a class="hash-link" aria-label="2-protocol的直接链接" title="2-protocol的直接链接" href="https://quanscheng.vercel.app/blog/2023/06/01/widow-location#2-protocol">​</a></h2>
<p><code>protocol</code>属性返回当前页面的协议名称（例如<code>http:</code>或<code>https:</code>），可以读取和设置。例如：</p>
<div class="language-js codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-js codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 获取当前页面的协议名称</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">var</span><span class="token plain"> protocol </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token dom variable" style="color:#36acaa">window</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">location</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">protocol</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">protocol</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 通过设置protocol属性来切换协议</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token dom variable" style="color:#36acaa">window</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">location</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">protocol</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"https:"</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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 anchorWithStickyNavbar_jjaS" id="3-host">3. <code>.host</code><a class="hash-link" aria-label="3-host的直接链接" title="3-host的直接链接" href="https://quanscheng.vercel.app/blog/2023/06/01/widow-location#3-host">​</a></h2>
<p><code>host</code>属性返回当前页面的主机名和端口号（例如<code>www.example.com:8080</code>），可以读取和设置。例如：</p>
<div class="language-js codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-js codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 获取当前页面的主机名和端口号</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">var</span><span class="token plain"> host </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token dom variable" style="color:#36acaa">window</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">location</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">host</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">host</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 通过设置host属性来修改主机名和端口号</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token dom variable" style="color:#36acaa">window</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">location</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">host</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"www.example.com:8080"</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴��板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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 anchorWithStickyNavbar_jjaS" id="4-hostname">4. <code>.hostname</code><a class="hash-link" aria-label="4-hostname的直接链接" title="4-hostname的直接链接" href="https://quanscheng.vercel.app/blog/2023/06/01/widow-location#4-hostname">​</a></h2>
<p><code>hostname</code>属性返回当前页面的主机名（例如<code>www.example.com</code>），可以读取和设置。例如：</p>
<div class="language-js codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-js codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 获取当前页面的主机名</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">var</span><span class="token plain"> hostname </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token dom variable" style="color:#36acaa">window</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">location</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">hostname</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">hostname</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 通过设置hostname属性来修改主机名</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token dom variable" style="color:#36acaa">window</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">location</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">hostname</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"www.example.com"</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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 anchorWithStickyNavbar_jjaS" id="5-port">5. <code>.port</code><a class="hash-link" aria-label="5-port的直接链接" title="5-port的直接链接" href="https://quanscheng.vercel.app/blog/2023/06/01/widow-location#5-port">​</a></h2>
<p><code>port</code>属性返回当前页面的端口号（例如<code>8080</code>），可以读取和设置。例如：</p>
<div class="language-js codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-js codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 获取当前页面的端口号</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">var</span><span class="token plain"> port </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token dom variable" style="color:#36acaa">window</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">location</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">port</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">port</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 通过设置port属性来修改端口号</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token dom variable" style="color:#36acaa">window</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">location</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">port</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"8080"</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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 anchorWithStickyNavbar_jjaS" id="6-pathname">6. <code>.pathname</code><a class="hash-link" aria-label="6-pathname的直接链接" title="6-pathname的直接链接" href="https://quanscheng.vercel.app/blog/2023/06/01/widow-location#6-pathname">​</a></h2>
<p><code>pathname</code>属性返回当前页面的路径（例如<code>/index.html</code>），可以读取和设置。例如：</p>
<div class="language-js codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-js codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 获取当前页面的路径</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">var</span><span class="token plain"> pathname </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token dom variable" style="color:#36acaa">window</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">location</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">pathname</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pathname</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 通过设置pathname属性来修改路径</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token dom variable" style="color:#36acaa">window</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">location</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">pathname</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"/newpage.html"</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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 anchorWithStickyNavbar_jjaS" id="7-search">7. <code>.search</code><a class="hash-link" aria-label="7-search的直接链接" title="7-search的直接链接" href="https://quanscheng.vercel.app/blog/2023/06/01/widow-location#7-search">​</a></h2>
<p><code>search</code>属性返回当前页面的查询字符串部分（例如<code>?id=123&amp;name=John</code>），可以读取和设置。例如：</p>
<div class="language-js codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-js codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 获取当前页面的查询字符串部分</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">var</span><span class="token plain"> search </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token dom variable" style="color:#36acaa">window</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">location</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">search</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">search</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">//通过设置search属性来添加查询参数</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token dom variable" style="color:#36acaa">window</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">location</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">search</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"?id=123&amp;name=John"</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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 anchorWithStickyNavbar_jjaS" id="8-hash">8. <code>.hash</code><a class="hash-link" aria-label="8-hash的直接链接" title="8-hash的直接链接" href="https://quanscheng.vercel.app/blog/2023/06/01/widow-location#8-hash">​</a></h2>
<p><code>hash</code>属性返回当前页面的锚点部分（例如<code>#section1</code>），可以读取和设置。例如：</p>
<div class="language-js codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-js codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 获取当前页面的锚点部分</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">var</span><span class="token plain"> hash </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token dom variable" style="color:#36acaa">window</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">location</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">hash</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">hash</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 通过设置hash属性来跳转到指定的锚点</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token dom variable" style="color:#36acaa">window</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">location</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">hash</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"#section2"</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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 anchorWithStickyNavbar_jjaS" id="9-origin">9. <code>.origin</code><a class="hash-link" aria-label="9-origin的直接链接" title="9-origin的直接链接" href="https://quanscheng.vercel.app/blog/2023/06/01/widow-location#9-origin">​</a></h2>
<p><code>origin</code>属性返回当前页面的域名（包括协议和端口号），例如<code>http://www.example.com:8080</code>。该属性只读。例如：</p>
<div class="language-js codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-js codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 获取当前页面的域名（包括协议和端口号）</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">var</span><span class="token plain"> origin </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token dom variable" style="color:#36acaa">window</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">location</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">origin</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">origin</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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 anchorWithStickyNavbar_jjaS" id="10-assignurl">10. <code>.assign(url)</code><a class="hash-link" aria-label="10-assignurl的直接链接" title="10-assignurl的直接链接" href="https://quanscheng.vercel.app/blog/2023/06/01/widow-location#10-assignurl">​</a></h2>
<p><code>assign()</code>方法会将当前窗口重定向到指定的URL地址，可以用来实现页面跳转。例如：</p>
<div class="language-js codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-js codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 将当前页面重定向到指定的URL地址</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token dom variable" style="color:#36acaa">window</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">location</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">assign</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"http://www.example.com"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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 anchorWithStickyNavbar_jjaS" id="11-reload">11. <code>.reload()</code><a class="hash-link" aria-label="11-reload的直接链接" title="11-reload的直接链接" href="https://quanscheng.vercel.app/blog/2023/06/01/widow-location#11-reload">​</a></h2>
<p><code>reload()</code>方法会重新加载当前页面，可以用来实现页面刷新。例如：</p>
<div class="language-js codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-js codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 刷新当前页面</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token dom variable" style="color:#36acaa">window</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">location</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">reload</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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 anchorWithStickyNavbar_jjaS" id="12-replaceurl">12. <code>.replace(url)</code><a class="hash-link" aria-label="12-replaceurl的直接链接" title="12-replaceurl的直接链接" href="https://quanscheng.vercel.app/blog/2023/06/01/widow-location#12-replaceurl">​</a></h2>
<p><code>replace()</code>方法会将当前窗口的URL地址替换为指定的URL地址，可以用来实现页面跳转。它与<code>assign()</code>方法的区别在于，<code>replace()</code>方法不会将新的URL地址添加到浏览器的历史记录中，因此用户不能使用“后退”按钮返回该URL地址之前的页面。例如：</p>
<div class="language-js codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-js codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 将当前页面的URL地址替换为指定的URL地址</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token dom variable" style="color:#36acaa">window</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">location</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">replace</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"http://www.example.com"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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 anchorWithStickyNavbar_jjaS" id="13-ancestororigins">13. <code>.ancestorOrigins</code><a class="hash-link" aria-label="13-ancestororigins的直接链接" title="13-ancestororigins的直接链接" href="https://quanscheng.vercel.app/blog/2023/06/01/widow-location#13-ancestororigins">​</a></h2>
<p><code>window.location.ancestorOrigins</code>属性返回一个DOMString列表，其中包含了当前页面所有祖先页面的域名（协议+主机名+端口号）。</p>
<p>如果当前页面在一个iframe或嵌套的子页面中，则这个列表会包含所有祖先页面的域名。如果当前页面不在iframe或嵌套的子页面中，则这个列表为空。</p>
<p>这个属性只读，不支持设置。以下是一个示例代码：</p>
<div class="language-javascript codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-javascript codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 获取当前页面所有祖先页面的域名</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">var</span><span class="token plain"> ancestorOrigins </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token dom variable" style="color:#36acaa">window</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">location</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">ancestorOrigins</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 遍历所有祖先页面的域名</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword control-flow" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">var</span><span class="token plain"> i </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> i </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain"> ancestorOrigins</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">length</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> i</span><span class="token operator" style="color:#393A34">++</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ancestorOrigins</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">i</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>如果当前页面在一个iframe或嵌套的子页面中，以上代码会输出所有祖先页面的域名。如果当前页面不在iframe或嵌套的子页面中，则输出一个空列表。</p>
<blockquote>
<p>需要注意的是，<code>window.location.ancestorOrigins</code>属性只在一些较新的浏览器中支持，如果你的代码需要在老旧的浏览器中运行，建议先判断一下是否支持该属性再使用。</p>
</blockquote>
<p>以上就是<code>window.location</code>对象的常用属性及其用法。这些属性可以让我们方便地获取和设置页面的URL信息，从而实现各种功能，例如重定向、切换协议、修改查询参数等等。</p>]]></content>
        <author>
            <name>TransonQ</name>
            <uri>https://github.com/TransonQ</uri>
        </author>
        <category label="JavaScript" term="JavaScript"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[blob 下载函数]]></title>
        <id>https://quanscheng.vercel.app/blog/2023/05/24/download-blob</id>
        <link href="https://quanscheng.vercel.app/blog/2023/05/24/download-blob"/>
        <updated>2023-05-24T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[JavaScript 版本]]></summary>
        <content type="html"><![CDATA[<h2 class="anchor anchorWithStickyNavbar_jjaS" id="javascript-版本">JavaScript 版本<a class="hash-link" aria-label="JavaScript 版本的直接链接" title="JavaScript 版本的直接链接" href="https://quanscheng.vercel.app/blog/2023/05/24/download-blob#javascript-%E7%89%88%E6%9C%AC">​</a></h2>
<div class="language-js codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-js codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">downloadBlob</span><span class="token punctuation" style="color:#393A34">(</span><span class="token parameter">blob</span><span class="token parameter punctuation" style="color:#393A34">,</span><span class="token parameter"> filename</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> url </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">URL</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">createObjectURL</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">blob</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> a </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token dom variable" style="color:#36acaa">document</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">createElement</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'a'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  a</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">href</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> url</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  a</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">download</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> filename</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token dom variable" style="color:#36acaa">document</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">body</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">appendChild</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">a</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  a</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">click</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">setTimeout</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token dom variable" style="color:#36acaa">document</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">body</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">removeChild</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">a</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token constant" style="color:#36acaa">URL</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">revokeObjectURL</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">url</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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>这个函数接收两个参数，第一个参数是一个Blob对象，第二个参数是要下载的文件名。</li>
<li>该函数使用<code>createObjectURL</code>方法将Blob对象转换为URL，然后创建一个a标签并设置其href属性为该URL，download属性为文件名。</li>
<li>接着将a标签添加到DOM中，并模拟用户点击该a标签来触发下载。</li>
<li>最后，我们需要等待浏览器完成下载后，从DOM中移除a标签，并使用<code>revokeObjectURL</code>方法释放该URL。</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_jjaS" id="typescript-版本">TypeScript 版本<a class="hash-link" aria-label="TypeScript 版本的直接链接" title="TypeScript 版本的直接链接" href="https://quanscheng.vercel.app/blog/2023/05/24/download-blob#typescript-%E7%89%88%E6%9C%AC">​</a></h2>
<div class="language-ts codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-ts codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">downloadBlob</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">blob</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> Blob</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> filename</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> url </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">URL</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">createObjectURL</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">blob</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> a </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> document</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">createElement</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'a'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  a</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">href </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> url</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  a</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">download </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> filename</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  document</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">body</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">appendChild</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">a</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  a</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">click</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">setTimeout</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    document</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">body</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">removeChild</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">a</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token constant" style="color:#36acaa">URL</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">revokeObjectURL</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">url</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>这个函数跟上面的代码是一样的，只是加上了类型注解。第一个参数是一个Blob对象，类型为Blob，第二个参数是要下载的文件名，类型为字符串。函数的返回值为void，因为我们只是触发了浏览器的下载操作，并没有返回任何值。</p>]]></content>
        <author>
            <name>TransonQ</name>
            <uri>https://github.com/TransonQ</uri>
        </author>
        <category label="JavaScript" term="JavaScript"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[React项目中使用Google reCAPTCHA]]></title>
        <id>https://quanscheng.vercel.app/blog/2023/04/28/google-recaptcha</id>
        <link href="https://quanscheng.vercel.app/blog/2023/04/28/google-recaptcha"/>
        <updated>2023-04-28T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[一. 注册密钥]]></summary>
        <content type="html"><![CDATA[<h2 class="anchor anchorWithStickyNavbar_jjaS" id="一-注册密钥">一. 注册密钥<a class="hash-link" aria-label="一. 注册密钥的直接链接" title="一. 注册密钥的直接链接" href="https://quanscheng.vercel.app/blog/2023/04/28/google-recaptcha#%E4%B8%80-%E6%B3%A8%E5%86%8C%E5%AF%86%E9%92%A5">​</a></h2>
<p>首先，你需要在 Google reCAPTCHA 网站（<a href="https://www.google.com/recaptcha/admin/create%EF%BC%89%E4%B8%8A%E6%B3%A8%E5%86%8C%E5%B9%B6%E8%8E%B7%E5%8F%96" target="_blank" rel="noopener noreferrer">https://www.google.com/recaptcha/admin/create）上注册并获取</a> API 密钥。完成注册后，你将获得一个 <code>siteKey</code> 和一个 <code>secretKey</code>，这些信息将用于在前端和后端验证 reCAPTCHA 响应。</p>
<h2 class="anchor anchorWithStickyNavbar_jjaS" id="二-安装-recaptcha-包">二. 安装 reCAPTCHA 包<a class="hash-link" aria-label="二. 安装 reCAPTCHA 包的直接链接" title="二. 安装 reCAPTCHA 包的直接链接" href="https://quanscheng.vercel.app/blog/2023/04/28/google-recaptcha#%E4%BA%8C-%E5%AE%89%E8%A3%85-recaptcha-%E5%8C%85">​</a></h2>
<div class="language-bash codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Xkn2">npm</div><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-bash codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">npm install react-google-recaptcha</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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-bash codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Xkn2">yarn</div><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-bash codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">yarn add react-google-recaptcha</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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 anchorWithStickyNavbar_jjaS" id="三-使用">三. 使用<a class="hash-link" aria-label="三. 使用的直接链接" title="三. 使用的直接链接" href="https://quanscheng.vercel.app/blog/2023/04/28/google-recaptcha#%E4%B8%89-%E4%BD%BF%E7%94%A8">​</a></h2>
<div class="language-jsx codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Xkn2">部分代码示意</div><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-jsx codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports maybe-class-name">ReCAPTCHA</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'react-google-recaptcha'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">REACT_APP_RECAPTCHA_KEY</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> process</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">env</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// siteKey 配置进环境变量, 通常测试环境和正式环境是不一样的</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token spread operator" style="color:#393A34">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> recaptchaRef </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useRef</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword null nil" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 可以获取到 recaptcha 自带的方法</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">* 验证用户是否完成了验证码测试的方法 execute: </span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">* recaptchaRef.current.execute()</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">* </span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">* 服务重新启动的方法 reset: </span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">* recaptchaRef.current.reset();</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">*/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">isVertified</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> setIsVertified</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useState</span><span class="token punctuation" style="color:#393A34">(</span><span class="token boolean" style="color:#36acaa">false</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 是否已经验证</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">recaptcha</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> setRecaptcha</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useState</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">''</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 验证码存储, 如果遇到不想更新视图的场景, 考虑使用 useRef 储存</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token function-variable function" style="color:#d73a49">onChange</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token parameter">value</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 拿到用户点击后的验证码, 通常需要后端接收这个验证码, 所以其一般是请求体的某个字段值</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword control-flow" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">value</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">setIsVertified</span><span class="token punctuation" style="color:#393A34">(</span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">setRecaptcha</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">value</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token spread operator" style="color:#393A34">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">  </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">ReCAPTCHA</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">    </span><span class="token tag attr-name" style="color:#00a4db">ref</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:#393A34">=</span><span class="token tag script language-javascript punctuation" style="color:#393A34">{</span><span class="token tag script language-javascript" style="color:#00009f">recaptchaRef</span><span class="token tag script language-javascript punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">    </span><span class="token tag comment" style="color:#999988;font-style:italic">// size="invisible"</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">    </span><span class="token tag attr-name" style="color:#00a4db">sitekey</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:#393A34">=</span><span class="token tag script language-javascript punctuation" style="color:#393A34">{</span><span class="token tag script language-javascript constant" style="color:#36acaa">REACT_APP_RECAPTCHA_KEY</span><span class="token tag script language-javascript punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">    </span><span class="token tag attr-name" style="color:#00a4db">onChange</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:#393A34">=</span><span class="token tag script language-javascript punctuation" style="color:#393A34">{</span><span class="token tag script language-javascript" style="color:#00009f">onChange</span><span class="token tag script language-javascript punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">    </span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">  </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">Button</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">disabled</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:#393A34">=</span><span class="token tag script language-javascript punctuation" style="color:#393A34">{</span><span class="token tag script language-javascript operator" style="color:#393A34">!</span><span class="token tag script language-javascript" style="color:#00009f">isVertified</span><span class="token tag script language-javascript punctuation" style="color:#393A34">}</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">    Submit</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">  </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag class-name" style="color:#00009f">Button</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">  </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>]]></content>
        <author>
            <name>TransonQ</name>
            <uri>https://github.com/TransonQ</uri>
        </author>
        <category label="工具库" term="工具库"/>
        <category label="验证" term="验证"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[react 实用工具UI库]]></title>
        <id>https://quanscheng.vercel.app/blog/2023/04/10/toast-libs</id>
        <link href="https://quanscheng.vercel.app/blog/2023/04/10/toast-libs"/>
        <updated>2023-04-10T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[React Hot Toast]]></summary>
        <content type="html"><![CDATA[<h2 class="anchor anchorWithStickyNavbar_jjaS" id="react-hot-toast"><a href="https://react-hot-toast.com/" target="_blank" rel="noopener noreferrer">React Hot Toast</a><a class="hash-link" aria-label="react-hot-toast的直接链接" title="react-hot-toast的直接链接" href="https://quanscheng.vercel.app/blog/2023/04/10/toast-libs#react-hot-toast">​</a></h2>
<div class="language-bash codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-bash codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">yarn add react-hot-toast</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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-jsx codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Xkn2">App.jsx</div><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-jsx codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function maybe-class-name" style="color:#d73a49">App</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token plain"> </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">Toaster</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">position</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">bottom-center</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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-ts codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Xkn2">hotToast.ts</div><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-ts codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> toast </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'react-hot-toast'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">type</span><span class="token plain"> </span><span class="token class-name">optionProps</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  error</span><span class="token operator" style="color:#393A34">?</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">boolean</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> color </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  critical</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'rgba(216, 44, 13, 1)'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// --p-action-critical 错误色</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">default</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'rgba(32, 33, 35, 1)'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// --p-surface-dark 默认黑色</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token function-variable function" style="color:#d73a49">hotToast</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">msg</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> options</span><span class="token operator" style="color:#393A34">?</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> optionProps</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">toast</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">msg</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    style</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      borderRadius</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'4px'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      background</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">!</span><span class="token plain">options</span><span class="token operator" style="color:#393A34">?.</span><span class="token plain">error </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> color</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">default </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> color</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">critical</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      color</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'#fff'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Xkn2">使用</div><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-js codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">hotToast</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"提示信息"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">hotToast</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"错误信息"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token punctuation" style="color:#393A34">{</span><span class="token literal-property property" style="color:#36acaa">error</span><span class="token operator" style="color:#393A34">:</span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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 anchorWithStickyNavbar_jjaS" id="sonner"><a href="https://sonner.emilkowal.ski/" target="_blank" rel="noopener noreferrer">Sonner</a><a class="hash-link" aria-label="sonner的直接链接" title="sonner的直接链接" href="https://quanscheng.vercel.app/blog/2023/04/10/toast-libs#sonner">​</a></h2>
<div class="language-bash codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-bash codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">yarn add sonner</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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 Hot Toast</code></p>
<h2 class="anchor anchorWithStickyNavbar_jjaS" id="react-wrap-balancer"><a href="https://react-wrap-balancer.vercel.app/" target="_blank" rel="noopener noreferrer">React Wrap Balancer</a><a class="hash-link" aria-label="react-wrap-balancer的直接链接" title="react-wrap-balancer的直接链接" href="https://quanscheng.vercel.app/blog/2023/04/10/toast-libs#react-wrap-balancer">​</a></h2>
<div class="language-bash codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-bash codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">yarn add react-wrap-balancer</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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-jsx codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Xkn2">使用方法</div><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-jsx codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports maybe-class-name">Balancer</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'react-wrap-balancer'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// ...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">h1</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">  </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">Balancer</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text">My Title</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag class-name" style="color:#00009f">Balancer</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text"></span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">h1</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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-jsx codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Xkn2">多个组件可以共享逻辑</div><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-jsx codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"> </span><span class="token imports maybe-class-name">Provider</span><span class="token imports"> </span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'react-wrap-balancer'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// ...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">Provider</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">  </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">App</span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text"></span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag class-name" style="color:#00009f">Provider</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>]]></content>
        <author>
            <name>TransonQ</name>
            <uri>https://github.com/TransonQ</uri>
        </author>
        <category label="工具库" term="工具库"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[MacOS停止制定端口的进程]]></title>
        <id>https://quanscheng.vercel.app/blog/2023/03/31/mac-kill-port</id>
        <link href="https://quanscheng.vercel.app/blog/2023/03/31/mac-kill-port"/>
        <updated>2023-03-31T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[前段时间升级了vscode之后， 发现升级或者在开发服务器未关闭的情况下，重启vscode没有停止对应端口的进程，导致一个现象就是：开发服务器未关闭重启vscode端口被莫名占用。]]></summary>
        <content type="html"><![CDATA[<p>前段时间升级了vscode之后， 发现升级或者在开发服务器未关闭的情况下，重启vscode没有停止对应端口的进程，导致一个现象就是：开发服务器未关闭重启vscode端口被莫名占用。</p>
<p>找到了两个命令查询对应端口占用的进程：</p>
<div class="language-bash codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-bash codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">lsof -i :3000</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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 decoding="async" loading="lazy" alt="macos-lsof" src="https://quanscheng.vercel.app/assets/images/macos-lsof-2ec5f94ecafc2a53f1d9bcc72b541d8a.png" width="866" height="208" class="img_PD5j"></p>
<div class="language-bash codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_Xkn2">停止进程</div><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-bash codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token plain">kill -9 10956</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>]]></content>
        <author>
            <name>TransonQ</name>
            <uri>https://github.com/TransonQ</uri>
        </author>
        <category label="MacOS" term="MacOS"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[useDebounceFn]]></title>
        <id>https://quanscheng.vercel.app/blog/2023/03/13/useDebounceFn</id>
        <link href="https://quanscheng.vercel.app/blog/2023/03/13/useDebounceFn"/>
        <updated>2023-03-13T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[useDebounceFn]]></summary>
        <content type="html"><![CDATA[<h2 class="anchor anchorWithStickyNavbar_jjaS" id="usedebouncefn">useDebounceFn<a class="hash-link" aria-label="useDebounceFn的直接链接" title="useDebounceFn的直接链接" href="https://quanscheng.vercel.app/blog/2023/03/13/useDebounceFn#usedebouncefn">​</a></h2>
<div class="language-ts codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-ts codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> debounce </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'lodash'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> useMemo </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'react'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> useUnmount </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'react-use'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> useLatest </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'./useLatest'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">type</span><span class="token plain"> </span><span class="token class-name">DebounceOptions</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 间隔时间</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  wait</span><span class="token operator" style="color:#393A34">?</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">number</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  leading</span><span class="token operator" style="color:#393A34">?</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">boolean</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  trailing</span><span class="token operator" style="color:#393A34">?</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">boolean</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  maxWait</span><span class="token operator" style="color:#393A34">?</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">number</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">type</span><span class="token plain"> </span><span class="token class-name">useDebounceFnRetrunProps</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function-variable function" style="color:#d73a49">run</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function-variable function" style="color:#d73a49">cancel</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function-variable function" style="color:#d73a49">flush</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// ahooks 参数相同, 用法相同</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> useDebounceFn </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  fn</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">Function</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  options</span><span class="token operator" style="color:#393A34">?</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> DebounceOptions</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> useDebounceFnRetrunProps </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> fnRef </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useLatest</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">fn</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> wait </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> options</span><span class="token operator" style="color:#393A34">?.</span><span class="token plain">wait </span><span class="token operator" style="color:#393A34">??</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1000</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> debounced </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useMemo</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token function" style="color:#d73a49">debounce</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">...</span><span class="token plain">args</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> fnRef</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">current</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">...</span><span class="token plain">args</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        wait</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        options</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 不能加依赖, 否则可能导致死循环</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// eslint-disable-next-line</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">useUnmount</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    debounced</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">cancel</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    run</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> debounced</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    cancel</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> debounced</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">cancel</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    flush</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> debounced</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">flush</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" 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 anchorWithStickyNavbar_jjaS" id="uselatest">useLatest<a class="hash-link" aria-label="useLatest的直接链接" title="useLatest的直接链接" href="https://quanscheng.vercel.app/blog/2023/03/13/useDebounceFn#uselatest">​</a></h2>
<div class="language-ts codeBlockContainer_VvTR theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_l6Dp"><pre tabindex="0" class="prism-code language-ts codeBlock_klVZ thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_Q3jn"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> useRef </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'react'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token generic-function function" style="color:#d73a49">useLatest</span><span class="token generic-function generic class-name operator" style="color:#393A34">&lt;</span><span class="token generic-function generic class-name constant" style="color:#36acaa">T</span><span class="token generic-function generic class-name operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">value</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">T</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> ref </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useRef</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">value</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  ref</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">current </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> value</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> ref</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup_HZbM"><button type="button" aria-label="复制代码到剪贴板" title="复制" class="clean-btn"><span class="copyButtonIcons_f6_W" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_IVf8"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_ZQ2f"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>]]></content>
        <author>
            <name>TransonQ</name>
            <uri>https://github.com/TransonQ</uri>
        </author>
        <category label="useDebounceFn" term="useDebounceFn"/>
        <category label="hooks" term="hooks"/>
    </entry>
</feed>