<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://seyl.me/</id>
    <title>duyl328的技术博客</title>
    <updated>2026-03-09T06:31:05.361Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <author>
        <name>duyl328</name>
        <uri>https://seyl.me/about</uri>
    </author>
    <link rel="alternate" href="https://seyl.me/"/>
    <link rel="self" href="https://seyl.me/atom.xml"/>
    <subtitle>分享全栈开发经验，涵盖Vue、Kotlin、C#、Python、Rust等技术栈</subtitle>
    <logo>https://seyl.me/web-app-manifest-512x512.png</logo>
    <icon>https://seyl.me/favicon.ico</icon>
    <rights>© 2021-2025 duyl328</rights>
    <entry>
        <title type="html"><![CDATA[Time Out to Reachable —— 安全网关搭建指北]]></title>
        <id>https://seyl.me/posts/2026/03/time-out-to-reachable</id>
        <link href="https://seyl.me/posts/2026/03/time-out-to-reachable"/>
        <updated>2026-03-06T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[<h1 id="frontmatter-title" tabindex="-1">{{ $frontmatter.title }} <a class="header-anchor" href="#frontmatter-title" aria-label="Permalink to &quot;{{ $frontmatter.title }}&quot;">&ZeroWidthSpace;</a></h1>
<blockquote>
<p>✒️ 文章摘要</p>
</blockquote>
<!-- DESC SEP -->
<p>想搭建一套既稳、又隐蔽、还能兼顾性能的安全网关，到底该选 REALITY、传统 VLESS+TLS，还是 gRPC+Cloudflare？这篇文章不讲手把手配置，而是从原理、流量路径、伪装方式、抗探测能力、证书与域名成本、源站暴露风险等角度，系统拆解三种主流方案的设计逻辑与适用场景。看完你会明白：为什么 REALITY 适合轻量直连，传统方案更适合多业务整合，而 Cloudflare 方案又为何能在隐藏源站和抗攻击上更进一步。</p>
<!-- DESC SEP -->
<h1 id="time-out-to-reachable-——-安全网关搭建指北" tabindex="-1">Time Out to Reachable —— 安全网关搭建指北 <a class="header-anchor" href="#time-out-to-reachable-——-安全网关搭建指北" aria-label="Permalink to &quot;Time Out to Reachable —— 安全网关搭建指北&quot;">&ZeroWidthSpace;</a></h1>
<blockquote>
<p>此文章只罗列和科普原理，不涉及具体搭建教程</p>
</blockquote>
<h2 id="reality-——-偷一个域名" tabindex="-1">REALITY —— 偷一个域名 <a class="header-anchor" href="#reality-——-偷一个域名" aria-label="Permalink to &quot;REALITY —— 偷一个域名&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="何为-reality" tabindex="-1">何为 REALITY <a class="header-anchor" href="#何为-reality" aria-label="Permalink to &quot;何为 REALITY&quot;">&ZeroWidthSpace;</a></h3>
<p>REALITY 是 Xray-core 推出的一种革命性的 TLS 伪装技术。在配置私有网络隧道和代理服务时，它解决了一个长久以来的痛点：<strong>不再需要自己购买域名、配置 DNS 解析、申请 SSL 证书，也不需要在服务器上搭建真实的 Web 服务作为伪装。</strong></p>
<h3 id="reality-解决的问题" tabindex="-1">REALITY 解决的问题 <a class="header-anchor" href="#reality-解决的问题" aria-label="Permalink to &quot;REALITY 解决的问题&quot;">&ZeroWidthSpace;</a></h3>
<p>传统”TLS 外套”类代理（Trojan、WS+TLS、TLS in TLS）存在两类常见风险：</p>
<ul>
<li><strong>被动识别</strong>：DPI 通过看 TLS 握手里的 SNI、指纹（ClientHello/JA3/JA4）、统计特征来分类。</li>
<li><strong>主动探测</strong>：防火墙会主动连你的 IP:Port，用各种握手探针去“戳”你是不是违规；如果服务端返回“像代理”的特征响应，就会被拉黑。</li>
</ul>
<p>REALITY 的定位是：<strong>替代传统 TLS 作为 Xray 的安全层</strong>，让连接在外观上更像“访问某个真实网站”的 TLS，同时让“主动探测者”拿不到确定证据。</p>
<h3 id="reality-原理" tabindex="-1">REALITY 原理 <a class="header-anchor" href="#reality-原理" aria-label="Permalink to &quot;REALITY 原理&quot;">&ZeroWidthSpace;</a></h3>
<p>REALITY 完全抛弃了自己维护域名的路线。它允许你直接“借用”别人的高信誉域名（例如 <code>www.microsoft.com</code>、<code>www.apple.com</code>）来做伪装。</p>
<p>它的工作流程分为两种情况：</p>
<h4 id="情况-a-你自己的客户端发起连接-合法流量" tabindex="-1">情况 A：你自己的客户端发起连接（合法流量） <a class="header-anchor" href="#情况-a-你自己的客户端发起连接-合法流量" aria-label="Permalink to &quot;情况 A：你自己的客户端发起连接（合法流量）&quot;">&ZeroWidthSpace;</a></h4>
<ol>
<li><strong>客户端发起握手：</strong> 你的本地客户端利用 uTLS 技术，伪装成普通的 Chrome 或 Edge 浏览器，向你的 VPS 发起 TLS Client Hello 握手请求。在这个请求中，SNI（服务器名称指示）写的是你指定的别人家的大型网站，比如 <code>sni: www.apple.com</code>。</li>
<li><strong>验证暗号：</strong> 表面上这是普通的握手，但客户端的请求中隐藏了只有你的服务器才知道的身份验证信息（基于 x25519 密钥交换生成）。</li>
<li><strong>服务器放行：</strong> 你的 VPS 收到请求后，会提取特征并进行解密。因为暗号正确，VPS 知道这是自己人，于是直接接管连接，建立安全的隧道并开始处理你的网络请求。</li>
</ol>
<h4 id="情况-b-防火墙发起主动探测-非法流量" tabindex="-1">情况 B：防火墙发起主动探测（非法流量） <a class="header-anchor" href="#情况-b-防火墙发起主动探测-非法流量" aria-label="Permalink to &quot;情况 B：防火墙发起主动探测（非法流量）&quot;">&ZeroWidthSpace;</a></h4>
<ol>
<li><strong>探测者发起握手：</strong> 防火墙察觉到你的 VPS IP 有异常流量，于是伪装成普通用户，向你的 VPS 发送探测包，试图看看这个 IP 到底在提供什么服务。由于它看到之前的流量 SNI 是 <code>www.apple.com</code>，它也会发送包含该 SNI 的请求。</li>
<li><strong>暗号匹配失败：</strong> 探测者没有你的专属密钥，发出的请求中不包含正确的隐藏验证信息。</li>
<li><strong>REALITY 伪装（完美转发）：</strong> 你的 VPS 发现暗号不对，立刻判定这是探测者。此时，<strong>VPS 会在内网直接向真正的 <code>www.apple.com</code> 发起连接</strong>，并将防火墙发来的探测流量原封不动地转发过去。</li>
<li><strong>完美的假象：</strong> 真正的苹果服务器收到请求后，会返回真实的、由权威机构签发的顶级 SSL 证书。你的 VPS 再把这个真实证书转发给防火墙。</li>
<li><strong>防火墙被骗：</strong> 防火墙拿到证书一查：证书是真的，签发机构是权威的，连向该服务器的特征也完全符合。防火墙就会认为：<strong>“这个 IP 真的只是苹果公司的一个海外 CDN 节点”</strong>，从而放弃封锁。</li>
</ol>
<p>整体时序图如下所示：</p>
<p><img src="./../../../public/posts/2026/03/10001/REALITY-sequence-diagram.png" alt="REALITY-sequence-diagram.png"></p>
<h3 id="reality-协议优势" tabindex="-1">REALITY 协议优势 <a class="header-anchor" href="#reality-协议优势" aria-label="Permalink to &quot;REALITY 协议优势&quot;">&ZeroWidthSpace;</a></h3>
<p><strong>架构极简</strong>，运维成本很低。无需 Nginx 等反代接入</p>
<p><strong>抹除了 CT 记录（Certificate Transparency）的致命伤</strong>，REALITY 不需要申请证书，直接实现了“零 CT 审计留痕”。</p>
<p><strong>消灭了 DNS 解析轨迹</strong>，不需要进行任何 DNS 查询，也就不存在 DNS 污染和解析记录暴露的风险。</p>
<p><strong>白嫖了高信誉域名的“白名单”</strong></p>
<h3 id="reality-需要注意的问题" tabindex="-1">REALITY 需要注意的问题 <a class="header-anchor" href="#reality-需要注意的问题" aria-label="Permalink to &quot;REALITY 需要注意的问题&quot;">&ZeroWidthSpace;</a></h3>
<ol>
<li><strong>服务一定要在 443 端口</strong>，因为在 <strong>443</strong> 端口建立网络服务几乎是事实上的标准，在其他端口建立只会让流量特征变得更加可疑</li>
<li>尽量（<strong>必须</strong>）使用 <strong>TLS 1.3</strong> 协议。TLS 1.2 在握手阶段，服务器向客户端发送数字证书时，是<strong>明文传输</strong>的，如果被旁听可以明确监听到是否进行了伪装。</li>
<li><strong>不要使用自己或小站域名</strong>。域名太新、太冷门、访问量形态怪反而适得其反</li>
<li><strong>尽量不要代理其他业务</strong>。因为只有一个 443 端口，当整个端口都交给 xray 使用后，如果还想进行其他子域名的代理会显的很诡异，比如偷了 apple.com 的域名，又代理自己的子域名，那么对外表现就是即表现出大厂特征，又表现出个人站点特征，这在理论上也是相悖的。虽然 xray 的回落机制可以做到这一点，但不建议这么做</li>
</ol>
<h2 id="传统方案" tabindex="-1">传统方案 <a class="header-anchor" href="#传统方案" aria-label="Permalink to &quot;传统方案&quot;">&ZeroWidthSpace;</a></h2>
<p>当我们使用自己的域名时，我们已经有了自己的域名，并且当我们需要代理更多自己的业务，如 frp、多域名反代或其他等，那么传统的方案可能更好，也就是 <code>VLESS + TCP + TLS</code></p>
<h3 id="模块介绍" tabindex="-1">模块介绍 <a class="header-anchor" href="#模块介绍" aria-label="Permalink to &quot;模块介绍&quot;">&ZeroWidthSpace;</a></h3>
<ul>
<li><strong>VLESS (协议层)：</strong> 负责身份验证和流量路由。客户端将你要访问的请求（比如 Google）打包，贴上你的专属 UUID（相当于通行证），然后交给下层。VLESS 本身是不加密的，它极其轻量，把安全工作完全托付给了 TLS。</li>
<li><strong>TCP (传输层)：</strong> 负责将数据包从你的电脑搬运到服务器。使用最基础、最原生的 TCP 协议，意味着没有 WebSocket (WS) 那种为了伪装成网页请求而强行添加的冗余 HTTP 请求头，传输效率更高，资源占用更低。</li>
<li><strong>TLS (加密与伪装层)：</strong> 它不仅负责把你的数据加密成乱码，防止中间人窃听，更重要的是，它向外展示了一个合法的网站身份。当防火墙看到这股流量时，只会觉得”这是一个用户正在通过标准的 TLS 1.3 协议，安全地访问一个有真实证书的网站”。</li>
</ul>
<h3 id="流量中转方案" tabindex="-1">流量中转方案 <a class="header-anchor" href="#流量中转方案" aria-label="Permalink to &quot;流量中转方案&quot;">&ZeroWidthSpace;</a></h3>
<h4 id="传统流量中转流程-不建议" tabindex="-1">传统流量中转流程（不建议） <a class="header-anchor" href="#传统流量中转流程-不建议" aria-label="Permalink to &quot;传统流量中转流程（不建议）&quot;">&ZeroWidthSpace;</a></h4>
<ol>
<li><strong>统一入口：</strong> 公网流量（无论是正常访客还是特殊访问）访问 <code>https://www.yourdomain.com</code>，统一到达 Nginx 监听的 443 端口。</li>
<li><strong>Nginx 解密：</strong> Nginx 使用配置好的 SSL 证书，将 TLS 加密层剥开，看到内部真实的 HTTP 请求。</li>
<li><strong>按路径分发（核心逻辑）：</strong>
<ul>
<li><strong>正常业务：</strong> 如果请求的路径是 <code>/api</code>、<code>/blog</code> 或者是根目录 <code>/</code>，Nginx 会按照常规配置，把流量转发给你服务器上运行的其他业务（比如跑在 8080 端口的 Java 服务，或者直接返回静态页面）。</li>
<li><strong>特殊业务：</strong> 如果请求的路径是你提前暗中约定好的”秘密通道”（比如 <code>/my-secret-tunnel</code>），并且带有 <code>Upgrade: websocket</code> 的请求头，Nginx 就会知道这是特殊流量，将这个流量转发给 Xray 处理。</li>
</ul>
</li>
<li><strong>移交 Xray：</strong> Nginx 将这个秘密路径的流量，通过反向代理，原封不动地转发给监听在本地内网端口（比如 <code>127.0.0.1:10000</code>）的 Xray。</li>
<li><strong>Xray 处理：</strong> Xray 拿到流量，完成 VLESS 验证，再去请求目标数据，然后原路返回。</li>
</ol>
<h4 id="nginx-前置-sni-四层分流-xray-回落方案-推荐" tabindex="-1">Nginx 前置 SNI 四层分流 + Xray 回落方案（推荐） <a class="header-anchor" href="#nginx-前置-sni-四层分流-xray-回落方案-推荐" aria-label="Permalink to &quot;Nginx 前置 SNI 四层分流 + Xray 回落方案（推荐）&quot;">&ZeroWidthSpace;</a></h4>
<ol>
<li><strong>统一入口与流量窥探 (Nginx 预读)</strong>：所有的公网流量统一经过 443 端口进入 Nginx。当流量到达时，Nginx 启用 <code>stream</code> 模块的 <code>ssl_preread</code> 功能。此时，Nginx <strong>不进行 TLS 解密</strong>，而是仅从 TLS 握手的初始包中，提取出明文的 SNI（访问者请求的域名）。<em>(注：2025年发布的 RFC 9849 虽可协商加密 SNI，但目前尚未全面普及，明文 SNI 仍是当前路由的主流依据。)</em></li>
<li><strong>基于 SNI 的四层路径转发</strong>：Nginx 拿到 SNI 后，开始在 TCP 层级规划流量路径：
<ul>
<li><strong>常规服务转发</strong>：如果 SNI 是常规建站域名（如 <code>blog.domain.com</code>），Nginx 会将流量转发给内部负责建站的 HTTPS 监听端口，随后解密并处理 <code>/api</code>、<code>/blog</code> 等七层路径请求。</li>
<li><strong>核心流量透传 (Secret Tunnel)</strong>：如果我们分配了一个专属的代理域名（如 <code>secret.domain.com</code>），Nginx 一旦检测到该 SNI 流量，将不进行任何干预，直接将<strong>原始的 TCP 流量</strong>透传给内网的 Xray 核心服务（如 <code>127.0.0.1:54321</code>）。</li>
</ul>
</li>
<li><strong>Xray 核心解密与鉴权</strong>：当 Xray 接收到被透传过来的原始 TCP 流量后，会使用协定好的 TLS 方式开始真正的解密操作。解密完成后，Xray 将拿到访问真实服务所需的 UUID 等参数：
<ul>
<li><strong>特殊访问放行</strong>：Xray 在这里判断请求是否合法。如果 UUID 及其他参数完全正确，则放行该请求并提供代理服务。</li>
</ul>
</li>
<li><strong>防御机制与主动回落 (Fallback)</strong>：如果这是一个正常的常规请求（例如没有携带任何特殊参数），或者携带的参数错误（例如遭遇恶意探测），Xray 会果断触发“回落”机制。它会将该请求退回到 Nginx 的特定端口（如 <code>127.0.0.1:8080</code>），将事先准备好的静态博客或其他基础服务展示给对方，以此来证明这是一个“正常”的网站，完美隐藏背后的核心功能。</li>
</ol>
<h3 id="注意事项与处理方案" tabindex="-1">注意事项与处理方案 <a class="header-anchor" href="#注意事项与处理方案" aria-label="Permalink to &quot;注意事项与处理方案&quot;">&ZeroWidthSpace;</a></h3>
<h4 id="_1-前置路由与后置服务的角色解耦-nginx-vs-后置-nginx-caddy" tabindex="-1">1. 前置路由与后置服务的角色解耦 (Nginx vs 后置 Nginx/Caddy) <a class="header-anchor" href="#_1-前置路由与后置服务的角色解耦-nginx-vs-后置-nginx-caddy" aria-label="Permalink to &quot;1. 前置路由与后置服务的角色解耦 (Nginx vs 后置 Nginx/Caddy)&quot;">&ZeroWidthSpace;</a></h4>
<p>在这个架构中，存在“两个”截然不同的 Web 服务角色，物理上它们可以是同一个 Nginx 软件的不同模块，也可以是 Nginx + Caddy 的组合：</p>
<ul>
<li><strong>前置四层路由 (Nginx Stream 模块监听 443 公网端口)：</strong> 它的角色是一个“瞎子快递员”，只看包裹上的运单号（明文 SNI），绝对不拆包裹。它<strong>不需要、也不能</strong>配置任何 SSL 证书，不处理任何 HTTP 请求。</li>
<li><strong>后置七层服务 (监听内网端口如 10443 的 Nginx HTTP 模块或 Caddy)：</strong> 它的角色是“业务前台”。当负责建站的流量（如 <code>blog</code>、<code>api</code>）被前置透传过来时，由它负责拿着对应的 SSL 证书进行真正的 TLS 解密，并处理具体的页面展示、反向代理（如转发给 FRP 面板）等常规业务。</li>
</ul>
<h4 id="_2-证书自动化申请的-80端口死锁-陷阱" tabindex="-1">2. 证书自动化申请的“80端口死锁”陷阱 <a class="header-anchor" href="#_2-证书自动化申请的-80端口死锁-陷阱" aria-label="Permalink to &quot;2. 证书自动化申请的“80端口死锁”陷阱&quot;">&ZeroWidthSpace;</a></h4>
<p>由于 443 端口被前置的 Nginx Stream 强行接管以处理 TCP 流量，传统的通过 443 端口进行 TLS 证书验证的方式将会失效。同时，如果你的 80 端口设置了“无脑强制跳转 HTTPS (443)”，会导致 Let's Encrypt 等机构的 HTTP-01 验证请求被踢入 443 端口的死胡同。</p>
<ul>
<li><strong>处理方案：</strong> 在负责监听 80 端口的配置中，必须采用<strong>精准规则分流</strong>。放行所有针对 <code>/.well-known/acme-challenge/</code> 路径的纯 HTTP 访问，直接在本地返回验证文件；仅对除此以外的正常访客流量执行 301 强制跳转 HTTPS。</li>
</ul>
<h4 id="_3-访客真实-ip-丢失问题-proxy-protocol-传递" tabindex="-1">3. 访客真实 IP 丢失问题 (PROXY Protocol 传递) <a class="header-anchor" href="#_3-访客真实-ip-丢失问题-proxy-protocol-传递" aria-label="Permalink to &quot;3. 访客真实 IP 丢失问题 (PROXY Protocol 传递)&quot;">&ZeroWidthSpace;</a></h4>
<p>流量经过 Nginx Stream 的四层转发后，内网的 Xray 和后置的建站 Web 服务看到的访客源 IP 都会变成 <code>127.0.0.1</code>。这会导致博客无法统计访客真实地域，日志失去审计价值，甚至可能误触后端服务的防 CC 攻击机制。</p>
<ul>
<li><strong>处理方案：</strong> 必须在流量链条上启用代理协议。
<ul>
<li><strong>Nginx 转发侧：</strong> 在 <code>stream</code> 模块的 <code>proxy_pass</code> 下方开启 <code>proxy_protocol on;</code>。</li>
<li><strong>Xray 接收侧：</strong> 在入站规则中开启 <code>acceptProxyProtocol: true</code>，并在回落规则中配置 <code>xver: 1</code> 或 <code>xver: 2</code> 以继续向后传递 IP。</li>
<li><strong>后置 Web 侧：</strong> 在监听端口处加上 <code>proxy_protocol</code> 标识，并使用 <code>set_real_ip_from 127.0.0.1;</code> 来恢复访客的真实 IP。</li>
</ul>
</li>
</ul>
<h4 id="_4-tls-in-tls-特征审计与-xtls-vision" tabindex="-1">4. TLS in TLS 特征审计与 XTLS-Vision <a class="header-anchor" href="#_4-tls-in-tls-特征审计与-xtls-vision" aria-label="Permalink to &quot;4. TLS in TLS 特征审计与 XTLS-Vision&quot;">&ZeroWidthSpace;</a></h4>
<ul>
<li><strong>问题说明：</strong> 当我们通过代理访问一个原本就是 HTTPS 的网站时，流量会被加密两次：内层是目标网站的 TLS 加密，外层是代理协议的 TLS 加密。这种“套娃”式的双重加密（TLS in TLS）会产生独特的握手特征和数据包长度分布（例如典型的握手包大小异常）。现代防火墙可以通过这些统计学特征，轻易识别出这是一条代理隧道并进行干扰。</li>
<li><strong>处理方案：</strong> 得益于我们这套方案让 Xray 掌握了原始 TCP 并亲自处理外层 TLS 握手，我们可以启用 <strong>XTLS-Vision</strong> 技术。
<ul>
<li>在 Xray 的 VLESS 入站配置中，将 <code>flow</code> 设置为 <code>xtls-rprx-vision</code>。</li>
<li><strong>工作原理：</strong> 在完成外层 TLS 握手并验证 UUID 合法后，它会检测内层传输的是否为 TLS 1.2/1.3 流量。如果是，Vision 会停止外层的二次加密，直接将内层的 TLS 流量”拼接”传递出去。这样一来，TLS in TLS 的特征被彻底消除，在防火墙看来，这段流量与普通的单一 HTTPS 流量毫无二致。</li>
</ul>
</li>
</ul>
<p>整体拓扑图如下：</p>
<p><img src="./../../../public/posts/2026/03/10001/traditional-solution-topology-diagram.png" alt="传统方案拓扑图"></p>
<h2 id="grpc-tls-cloudflare-方案" tabindex="-1">gRPC + TLS + Cloudflare 方案 <a class="header-anchor" href="#grpc-tls-cloudflare-方案" aria-label="Permalink to &quot;gRPC + TLS + Cloudflare 方案&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="方案概述" tabindex="-1">方案概述 <a class="header-anchor" href="#方案概述" aria-label="Permalink to &quot;方案概述&quot;">&ZeroWidthSpace;</a></h3>
<p>这个方案依靠 Cloudflare 服务实现流量转发，通过 CDN 网络隐藏源站 IP，并利用 gRPC 协议进行数据传输。</p>
<h3 id="工作流程" tabindex="-1">工作流程 <a class="header-anchor" href="#工作流程" aria-label="Permalink to &quot;工作流程&quot;">&ZeroWidthSpace;</a></h3>
<ol>
<li><strong>统一入口与 CDN 流量接管 (Cloudflare 前置)</strong>：客户端不再直接连接你的服务器 IP，而是将流量发送给 Cloudflare 全球分布的 Anycast 泛播节点。所有的公网流量统一经过 Cloudflare 的 443 端口进入。在这个阶段，<strong>外层 TLS 加密由 Cloudflare 负责终结（解密）</strong>，使用的是托管在 Cloudflare 上的公共域名证书。</li>
<li><strong>基于 HTTP/2 的七层路由与回源 (流量清洗与转发)</strong>：Cloudflare 在解密外层 TLS 后，能够看到完整的 HTTP/2 报文和请求路径（Path）。此时，它开始在七层（应用层）规划流量路径：
<ul>
<li><strong>常规服务转发</strong>：如果访问的是普通的网页路径（如 <code>/</code> 或 <code>/blog</code>），Cloudflare 会按照常规 CDN 逻辑处理，返回缓存或向源站请求网页内容。</li>
<li><strong>核心流量透传 (gRPC 隧道)</strong>：当客户端发出的请求是特定的 gRPC POST 请求（例如路径为 <code>/TunService/Tun</code>，且 Header 包含 <code>content-type: application/grpc</code>），Cloudflare 会识别出这是一个合法的 gRPC API 调用。它会保持 HTTP/2 的多路复用特性，<strong>重新使用 TLS 加密</strong>（回源加密），将这段 gRPC 流量转发给你隐藏在背后的真实服务器 IP。</li>
</ul>
</li>
<li><strong>源站 Xray 核心解密与鉴权 (回源接收)</strong>：你的服务器（源站）上的 Xray 监听着 443 端口，接收来自 Cloudflare 转发过来的回源 TLS 流量。Xray 会使用事先配置好的本地证书进行二次解密。解密完成后，Xray 解析出 gRPC payload 中的 VLESS 协议数据，并提取出 UUID 等参数：
<ul>
<li><strong>特殊访问放行</strong>：Xray 在这里判断 UUID 和 gRPC <code>serviceName</code> 是否合法。如果完全匹配，则放行该请求，提取出真实的目标网站地址，并代为发起访问。</li>
</ul>
</li>
<li><strong>防御机制与流量隔离 (云端与本地双重阻断)</strong>：如果这是一个不合法的请求：
<ul>
<li><strong>云端阻断</strong>：普通的恶意域名扫描或 IP 探测，绝大多数会被 Cloudflare 的 WAF（Web 应用防火墙）直接拦截在海外边缘节点，根本到达不了你的服务器。</li>
<li><strong>本地忽略/回落</strong>：如果探测流量穿透了 CF 到达源站，或者有人直接针对你的服务器真实 IP 发起扫描，由于他们无法提供正确的 gRPC 路径和 VLESS UUID，Xray 会直接断开连接或根据配置回落到伪装网站，保护核心服务不被发现。</li>
</ul>
</li>
</ol>
<h3 id="方案优势" tabindex="-1">方案优势 <a class="header-anchor" href="#方案优势" aria-label="Permalink to &quot;方案优势&quot;">&ZeroWidthSpace;</a></h3>
<h4 id="_1-ip-隐藏与源站保护-核心优势" tabindex="-1">1. IP 隐藏与源站保护（核心优势） <a class="header-anchor" href="#_1-ip-隐藏与源站保护-核心优势" aria-label="Permalink to &quot;1. IP 隐藏与源站保护（核心优势）&quot;">&ZeroWidthSpace;</a></h4>
<p><strong>完全隐藏源站 IP</strong>：客户端只需要知道 Cloudflare 托管的域名（如 <code>proxy.yourdomain.com</code>），无需知道真实服务器 IP。所有流量都先到达 CF 的边缘节点，再由 CF 回源到你的服务器。即使有人想要探测或攻击，他们面对的是 Cloudflare 的全球分布式网络，而不是你的单台 VPS。</p>
<p><strong>天然抗 DDoS</strong>：Cloudflare 提供企业级的 DDoS 防护能力。无论是 SYN Flood、UDP Flood 还是应用层攻击，绝大多数恶意流量会被 CF 的边缘节点直接过滤，根本到达不了源站。这对于个人 VPS 来说，相当于免费获得了价值数千美元的防护服务。</p>
<p><strong>域名扫描免疫</strong>：传统方案中，如果有人通过 CT 日志、DNS 历史记录等手段发现了你的域名，可以直接解析出服务器 IP 并进行探测。而使用 Cloudflare 后，域名解析指向的是 CF 的 IP 段，攻击者无法通过域名反查到源站真实位置。</p>
<h4 id="_2-流量特征混淆与合法性伪装" tabindex="-1">2. 流量特征混淆与合法性伪装 <a class="header-anchor" href="#_2-流量特征混淆与合法性伪装" aria-label="Permalink to &quot;2. 流量特征混淆与合法性伪装&quot;">&ZeroWidthSpace;</a></h4>
<p><strong>gRPC 协议的天然优势</strong>：gRPC 是 Google 开发的现代 RPC 框架，基于 HTTP/2 协议，在企业级微服务架构中被广泛使用。当你的流量以 gRPC 形式传输时，在防火墙看来，这就是一个普通的 API 服务调用，与 Google、Netflix、Uber 等大厂的内部服务通信毫无二致。</p>
<p><strong>HTTP/2 多路复用特性</strong>：gRPC 基于 HTTP/2，支持在单一 TCP 连接上并发传输多个请求。这意味着你的代理流量可以与正常的网页访问、API 调用混合在同一条连接中，流量模式更加自然，难以被统计学分析识别。</p>
<p><strong>CDN 流量掩护</strong>：所有流量都经过 Cloudflare 的 CDN 网络，在外部观察者看来，这只是一个使用了 CF 加速的普通网站。由于全球有数百万网站使用 Cloudflare，你的流量完全淹没在海量的正常 CDN 流量中，不会引起任何特殊关注。</p>
<h4 id="_3-零证书管理成本" tabindex="-1">3. 零证书管理成本 <a class="header-anchor" href="#_3-零证书管理成本" aria-label="Permalink to &quot;3. 零证书管理成本&quot;">&ZeroWidthSpace;</a></h4>
<p><strong>Cloudflare 托管证书</strong>：外层 TLS 证书由 Cloudflare 自动签发和续期，你无需关心证书过期问题。CF 使用的是权威 CA 签发的证书，浏览器和客户端完全信任。</p>
<p><strong>回源证书灵活性</strong>：源站到 Cloudflare 的回源连接，可以使用 CF 提供的 Origin CA 证书（15 年有效期），也可以使用自签名证书。由于这段连接只在 CF 和你的服务器之间，不会被外部审计，配置极其简单。</p>
<h4 id="_4-全球加速与智能路由" tabindex="-1">4. 全球加速与智能路由 <a class="header-anchor" href="#_4-全球加速与智能路由" aria-label="Permalink to &quot;4. 全球加速与智能路由&quot;">&ZeroWidthSpace;</a></h4>
<p><strong>Anycast 网络</strong>：Cloudflare 在全球拥有 300+ 个数据中心，使用 Anycast 技术。客户端会自动连接到地理位置最近的 CF 节点，大幅降低首包延迟。</p>
<p><strong>智能回源优化</strong>：CF 会根据网络状况，选择最优的回源路径。即使你的服务器位于美国西海岸，亚洲用户也能先连接到亚洲的 CF 节点，再由 CF 的骨干网高速回源，避免了跨洋链路的丢包和延迟。</p>
<h4 id="_5-配置简单-维护成本低" tabindex="-1">5. 配置简单，维护成本低 <a class="header-anchor" href="#_5-配置简单-维护成本低" aria-label="Permalink to &quot;5. 配置简单，维护成本低&quot;">&ZeroWidthSpace;</a></h4>
<p><strong>无需复杂的 Nginx 分流</strong>：不需要配置 Nginx Stream 模块的 SNI 分流、PROXY Protocol 传递等复杂逻辑。Xray 直接监听 443 端口，接收 CF 的回源流量即可。</p>
<p><strong>统一的流量入口</strong>：所有业务（网站、API、代理）都可以通过同一个域名和端口提供服务，由 Cloudflare 根据路径进行智能分发。配置清晰，易于管理。</p>
<h3 id="注意事项" tabindex="-1">注意事项 <a class="header-anchor" href="#注意事项" aria-label="Permalink to &quot;注意事项&quot;">&ZeroWidthSpace;</a></h3>
<h4 id="优质直连线路-如-cn2-gia-的路由失效与资源浪费" tabindex="-1">优质直连线路 (如 CN2 GIA) 的路由失效与资源浪费 <a class="header-anchor" href="#优质直连线路-如-cn2-gia-的路由失效与资源浪费" aria-label="Permalink to &quot;优质直连线路 (如 CN2 GIA) 的路由失效与资源浪费&quot;">&ZeroWidthSpace;</a></h4>
<ul>
<li><strong>问题说明：</strong> 引入 Cloudflare 作为前置代理的核心代价，是彻底丧失服务器原有的优质物理链路（如电信 CN2 GIA、移动 CMIN2 等针对亚洲优化的专线）优势。流量路径从”客户端专属高速直连”变成了”客户端先连接 Cloudflare 就近泛播节点，再由 CF 骨干网回源”。国内连接免费版 CF 节点通常走拥堵的普通公网，受限于”木桶效应”，原本极优的网络体验在晚高峰时会被 CF 的入站线路瓶颈所严重拖累。</li>
</ul>
<h3 id="方案对比" tabindex="-1">方案对比 <a class="header-anchor" href="#方案对比" aria-label="Permalink to &quot;方案对比&quot;">&ZeroWidthSpace;</a></h3>
<p><img src="./../../../public/posts/2026/03/10001/gRPC-CF-solution-and-direct-connection-comparison.png" alt="gRPC-CF-solution-and-direct-connection-comparison.png"></p>
<h2 id="三种方案综合对比" tabindex="-1">三种方案综合对比 <a class="header-anchor" href="#三种方案综合对比" aria-label="Permalink to &quot;三种方案综合对比&quot;">&ZeroWidthSpace;</a></h2>
<p>| 对比维度 | REALITY | 传统方案 (VLESS+TLS) | gRPC+Cloudflare |
|</p>
]]></summary>
        <content type="html"><![CDATA[<h1 id="frontmatter-title" tabindex="-1">{{ $frontmatter.title }} <a class="header-anchor" href="#frontmatter-title" aria-label="Permalink to &quot;{{ $frontmatter.title }}&quot;">&ZeroWidthSpace;</a></h1>
<blockquote>
<p>✒️ 文章摘要</p>
</blockquote>
<!-- DESC SEP -->
<p>想搭建一套既稳、又隐蔽、还能兼顾性能的安全网关，到底该选 REALITY、传统 VLESS+TLS，还是 gRPC+Cloudflare？这篇文章不讲手把手配置，而是从原理、流量路径、伪装方式、抗探测能力、证书与域名成本、源站暴露风险等角度，系统拆解三种主流方案的设计逻辑与适用场景。看完你会明白：为什么 REALITY 适合轻量直连，传统方案更适合多业务整合，而 Cloudflare 方案又为何能在隐藏源站和抗攻击上更进一步。</p>
<!-- DESC SEP -->
<h1 id="time-out-to-reachable-——-安全网关搭建指北" tabindex="-1">Time Out to Reachable —— 安全网关搭建指北 <a class="header-anchor" href="#time-out-to-reachable-——-安全网关搭建指北" aria-label="Permalink to &quot;Time Out to Reachable —— 安全网关搭建指北&quot;">&ZeroWidthSpace;</a></h1>
<blockquote>
<p>此文章只罗列和科普原理，不涉及具体搭建教程</p>
</blockquote>
<h2 id="reality-——-偷一个域名" tabindex="-1">REALITY —— 偷一个域名 <a class="header-anchor" href="#reality-——-偷一个域名" aria-label="Permalink to &quot;REALITY —— 偷一个域名&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="何为-reality" tabindex="-1">何为 REALITY <a class="header-anchor" href="#何为-reality" aria-label="Permalink to &quot;何为 REALITY&quot;">&ZeroWidthSpace;</a></h3>
<p>REALITY 是 Xray-core 推出的一种革命性的 TLS 伪装技术。在配置私有网络隧道和代理服务时，它解决了一个长久以来的痛点：<strong>不再需要自己购买域名、配置 DNS 解析、申请 SSL 证书，也不需要在服务器上搭建真实的 Web 服务作为伪装。</strong></p>
<h3 id="reality-解决的问题" tabindex="-1">REALITY 解决的问题 <a class="header-anchor" href="#reality-解决的问题" aria-label="Permalink to &quot;REALITY 解决的问题&quot;">&ZeroWidthSpace;</a></h3>
<p>传统”TLS 外套”类代理（Trojan、WS+TLS、TLS in TLS）存在两类常见风险：</p>
<ul>
<li><strong>被动识别</strong>：DPI 通过看 TLS 握手里的 SNI、指纹（ClientHello/JA3/JA4）、统计特征来分类。</li>
<li><strong>主动探测</strong>：防火墙会主动连你的 IP:Port，用各种握手探针去“戳”你是不是违规；如果服务端返回“像代理”的特征响应，就会被拉黑。</li>
</ul>
<p>REALITY 的定位是：<strong>替代传统 TLS 作为 Xray 的安全层</strong>，让连接在外观上更像“访问某个真实网站”的 TLS，同时让“主动探测者”拿不到确定证据。</p>
<h3 id="reality-原理" tabindex="-1">REALITY 原理 <a class="header-anchor" href="#reality-原理" aria-label="Permalink to &quot;REALITY 原理&quot;">&ZeroWidthSpace;</a></h3>
<p>REALITY 完全抛弃了自己维护域名的路线。它允许你直接“借用”别人的高信誉域名（例如 <code>www.microsoft.com</code>、<code>www.apple.com</code>）来做伪装。</p>
<p>它的工作流程分为两种情况：</p>
<h4 id="情况-a-你自己的客户端发起连接-合法流量" tabindex="-1">情况 A：你自己的客户端发起连接（合法流量） <a class="header-anchor" href="#情况-a-你自己的客户端发起连接-合法流量" aria-label="Permalink to &quot;情况 A：你自己的客户端发起连接（合法流量）&quot;">&ZeroWidthSpace;</a></h4>
<ol>
<li><strong>客户端发起握手：</strong> 你的本地客户端利用 uTLS 技术，伪装成普通的 Chrome 或 Edge 浏览器，向你的 VPS 发起 TLS Client Hello 握手请求。在这个请求中，SNI（服务器名称指示）写的是你指定的别人家的大型网站，比如 <code>sni: www.apple.com</code>。</li>
<li><strong>验证暗号：</strong> 表面上这是普通的握手，但客户端的请求中隐藏了只有你的服务器才知道的身份验证信息（基于 x25519 密钥交换生成）。</li>
<li><strong>服务器放行：</strong> 你的 VPS 收到请求后，会提取特征并进行解密。因为暗号正确，VPS 知道这是自己人，于是直接接管连接，建立安全的隧道并开始处理你的网络请求。</li>
</ol>
<h4 id="情况-b-防火墙发起主动探测-非法流量" tabindex="-1">情况 B：防火墙发起主动探测（非法流量） <a class="header-anchor" href="#情况-b-防火墙发起主动探测-非法流量" aria-label="Permalink to &quot;情况 B：防火墙发起主动探测（非法流量）&quot;">&ZeroWidthSpace;</a></h4>
<ol>
<li><strong>探测者发起握手：</strong> 防火墙察觉到你的 VPS IP 有异常流量，于是伪装成普通用户，向你的 VPS 发送探测包，试图看看这个 IP 到底在提供什么服务。由于它看到之前的流量 SNI 是 <code>www.apple.com</code>，它也会发送包含该 SNI 的请求。</li>
<li><strong>暗号匹配失败：</strong> 探测者没有你的专属密钥，发出的请求中不包含正确的隐藏验证信息。</li>
<li><strong>REALITY 伪装（完美转发）：</strong> 你的 VPS 发现暗号不对，立刻判定这是探测者。此时，<strong>VPS 会在内网直接向真正的 <code>www.apple.com</code> 发起连接</strong>，并将防火墙发来的探测流量原封不动地转发过去。</li>
<li><strong>完美的假象：</strong> 真正的苹果服务器收到请求后，会返回真实的、由权威机构签发的顶级 SSL 证书。你的 VPS 再把这个真实证书转发给防火墙。</li>
<li><strong>防火墙被骗：</strong> 防火墙拿到证书一查：证书是真的，签发机构是权威的，连向该服务器的特征也完全符合。防火墙就会认为：<strong>“这个 IP 真的只是苹果公司的一个海外 CDN 节点”</strong>，从而放弃封锁。</li>
</ol>
<p>整体时序图如下所示：</p>
<p><img src="./../../../public/posts/2026/03/10001/REALITY-sequence-diagram.png" alt="REALITY-sequence-diagram.png"></p>
<h3 id="reality-协议优势" tabindex="-1">REALITY 协议优势 <a class="header-anchor" href="#reality-协议优势" aria-label="Permalink to &quot;REALITY 协议优势&quot;">&ZeroWidthSpace;</a></h3>
<p><strong>架构极简</strong>，运维成本很低。无需 Nginx 等反代接入</p>
<p><strong>抹除了 CT 记录（Certificate Transparency）的致命伤</strong>，REALITY 不需要申请证书，直接实现了“零 CT 审计留痕”。</p>
<p><strong>消灭了 DNS 解析轨迹</strong>，不需要进行任何 DNS 查询，也就不存在 DNS 污染和解析记录暴露的风险。</p>
<p><strong>白嫖了高信誉域名的“白名单”</strong></p>
<h3 id="reality-需要注意的问题" tabindex="-1">REALITY 需要注意的问题 <a class="header-anchor" href="#reality-需要注意的问题" aria-label="Permalink to &quot;REALITY 需要注意的问题&quot;">&ZeroWidthSpace;</a></h3>
<ol>
<li><strong>服务一定要在 443 端口</strong>，因为在 <strong>443</strong> 端口建立网络服务几乎是事实上的标准，在其他端口建立只会让流量特征变得更加可疑</li>
<li>尽量（<strong>必须</strong>）使用 <strong>TLS 1.3</strong> 协议。TLS 1.2 在握手阶段，服务器向客户端发送数字证书时，是<strong>明文传输</strong>的，如果被旁听可以明确监听到是否进行了伪装。</li>
<li><strong>不要使用自己或小站域名</strong>。域名太新、太冷门、访问量形态怪反而适得其反</li>
<li><strong>尽量不要代理其他业务</strong>。因为只有一个 443 端口，当整个端口都交给 xray 使用后，如果还想进行其他子域名的代理会显的很诡异，比如偷了 apple.com 的域名，又代理自己的子域名，那么对外表现就是即表现出大厂特征，又表现出个人站点特征，这在理论上也是相悖的。虽然 xray 的回落机制可以做到这一点，但不建议这么做</li>
</ol>
<h2 id="传统方案" tabindex="-1">传统方案 <a class="header-anchor" href="#传统方案" aria-label="Permalink to &quot;传统方案&quot;">&ZeroWidthSpace;</a></h2>
<p>当我们使用自己的域名时，我们已经有了自己的域名，并且当我们需要代理更多自己的业务，如 frp、多域名反代或其他等，那么传统的方案可能更好，也就是 <code>VLESS + TCP + TLS</code></p>
<h3 id="模块介绍" tabindex="-1">模块介绍 <a class="header-anchor" href="#模块介绍" aria-label="Permalink to &quot;模块介绍&quot;">&ZeroWidthSpace;</a></h3>
<ul>
<li><strong>VLESS (协议层)：</strong> 负责身份验证和流量路由。客户端将你要访问的请求（比如 Google）打包，贴上你的专属 UUID（相当于通行证），然后交给下层。VLESS 本身是不加密的，它极其轻量，把安全工作完全托付给了 TLS。</li>
<li><strong>TCP (传输层)：</strong> 负责将数据包从你的电脑搬运到服务器。使用最基础、最原生的 TCP 协议，意味着没有 WebSocket (WS) 那种为了伪装成网页请求而强行添加的冗余 HTTP 请求头，传输效率更高，资源占用更低。</li>
<li><strong>TLS (加密与伪装层)：</strong> 它不仅负责把你的数据加密成乱码，防止中间人窃听，更重要的是，它向外展示了一个合法的网站身份。当防火墙看到这股流量时，只会觉得”这是一个用户正在通过标准的 TLS 1.3 协议，安全地访问一个有真实证书的网站”。</li>
</ul>
<h3 id="流量中转方案" tabindex="-1">流量中转方案 <a class="header-anchor" href="#流量中转方案" aria-label="Permalink to &quot;流量中转方案&quot;">&ZeroWidthSpace;</a></h3>
<h4 id="传统流量中转流程-不建议" tabindex="-1">传统流量中转流程（不建议） <a class="header-anchor" href="#传统流量中转流程-不建议" aria-label="Permalink to &quot;传统流量中转流程（不建议）&quot;">&ZeroWidthSpace;</a></h4>
<ol>
<li><strong>统一入口：</strong> 公网流量（无论是正常访客还是特殊访问）访问 <code>https://www.yourdomain.com</code>，统一到达 Nginx 监听的 443 端口。</li>
<li><strong>Nginx 解密：</strong> Nginx 使用配置好的 SSL 证书，将 TLS 加密层剥开，看到内部真实的 HTTP 请求。</li>
<li><strong>按路径分发（核心逻辑）：</strong>
<ul>
<li><strong>正常业务：</strong> 如果请求的路径是 <code>/api</code>、<code>/blog</code> 或者是根目录 <code>/</code>，Nginx 会按照常规配置，把流量转发给你服务器上运行的其他业务（比如跑在 8080 端口的 Java 服务，或者直接返回静态页面）。</li>
<li><strong>特殊业务：</strong> 如果请求的路径是你提前暗中约定好的”秘密通道”（比如 <code>/my-secret-tunnel</code>），并且带有 <code>Upgrade: websocket</code> 的请求头，Nginx 就会知道这是特殊流量，将这个流量转发给 Xray 处理。</li>
</ul>
</li>
<li><strong>移交 Xray：</strong> Nginx 将这个秘密路径的流量，通过反向代理，原封不动地转发给监听在本地内网端口（比如 <code>127.0.0.1:10000</code>）的 Xray。</li>
<li><strong>Xray 处理：</strong> Xray 拿到流量，完成 VLESS 验证，再去请求目标数据，然后原路返回。</li>
</ol>
<h4 id="nginx-前置-sni-四层分流-xray-回落方案-推荐" tabindex="-1">Nginx 前置 SNI 四层分流 + Xray 回落方案（推荐） <a class="header-anchor" href="#nginx-前置-sni-四层分流-xray-回落方案-推荐" aria-label="Permalink to &quot;Nginx 前置 SNI 四层分流 + Xray 回落方案（推荐）&quot;">&ZeroWidthSpace;</a></h4>
<ol>
<li><strong>统一入口与流量窥探 (Nginx 预读)</strong>：所有的公网流量统一经过 443 端口进入 Nginx。当流量到达时，Nginx 启用 <code>stream</code> 模块的 <code>ssl_preread</code> 功能。此时，Nginx <strong>不进行 TLS 解密</strong>，而是仅从 TLS 握手的初始包中，提取出明文的 SNI（访问者请求的域名）。<em>(注：2025年发布的 RFC 9849 虽可协商加密 SNI，但目前尚未全面普及，明文 SNI 仍是当前路由的主流依据。)</em></li>
<li><strong>基于 SNI 的四层路径转发</strong>：Nginx 拿到 SNI 后，开始在 TCP 层级规划流量路径：
<ul>
<li><strong>常规服务转发</strong>：如果 SNI 是常规建站域名（如 <code>blog.domain.com</code>），Nginx 会将流量转发给内部负责建站的 HTTPS 监听端口，随后解密并处理 <code>/api</code>、<code>/blog</code> 等七层路径请求。</li>
<li><strong>核心流量透传 (Secret Tunnel)</strong>：如果我们分配了一个专属的代理域名（如 <code>secret.domain.com</code>），Nginx 一旦检测到该 SNI 流量，将不进行任何干预，直接将<strong>原始的 TCP 流量</strong>透传给内网的 Xray 核心服务（如 <code>127.0.0.1:54321</code>）。</li>
</ul>
</li>
<li><strong>Xray 核心解密与鉴权</strong>：当 Xray 接收到被透传过来的原始 TCP 流量后，会使用协定好的 TLS 方式开始真正的解密操作。解密完成后，Xray 将拿到访问真实服务所需的 UUID 等参数：
<ul>
<li><strong>特殊访问放行</strong>：Xray 在这里判断请求是否合法。如果 UUID 及其他参数完全正确，则放行该请求并提供代理服务。</li>
</ul>
</li>
<li><strong>防御机制与主动回落 (Fallback)</strong>：如果这是一个正常的常规请求（例如没有携带任何特殊参数），或者携带的参数错误（例如遭遇恶意探测），Xray 会果断触发“回落”机制。它会将该请求退回到 Nginx 的特定端口（如 <code>127.0.0.1:8080</code>），将事先准备好的静态博客或其他基础服务展示给对方，以此来证明这是一个“正常”的网站，完美隐藏背后的核心功能。</li>
</ol>
<h3 id="注意事项与处理方案" tabindex="-1">注意事项与处理方案 <a class="header-anchor" href="#注意事项与处理方案" aria-label="Permalink to &quot;注意事项与处理方案&quot;">&ZeroWidthSpace;</a></h3>
<h4 id="_1-前置路由与后置服务的角色解耦-nginx-vs-后置-nginx-caddy" tabindex="-1">1. 前置路由与后置服务的角色解耦 (Nginx vs 后置 Nginx/Caddy) <a class="header-anchor" href="#_1-前置路由与后置服务的角色解耦-nginx-vs-后置-nginx-caddy" aria-label="Permalink to &quot;1. 前置路由与后置服务的角色解耦 (Nginx vs 后置 Nginx/Caddy)&quot;">&ZeroWidthSpace;</a></h4>
<p>在这个架构中，存在“两个”截然不同的 Web 服务角色，物理上它们可以是同一个 Nginx 软件的不同模块，也可以是 Nginx + Caddy 的组合：</p>
<ul>
<li><strong>前置四层路由 (Nginx Stream 模块监听 443 公网端口)：</strong> 它的角色是一个“瞎子快递员”，只看包裹上的运单号（明文 SNI），绝对不拆包裹。它<strong>不需要、也不能</strong>配置任何 SSL 证书，不处理任何 HTTP 请求。</li>
<li><strong>后置七层服务 (监听内网端口如 10443 的 Nginx HTTP 模块或 Caddy)：</strong> 它的角色是“业务前台”。当负责建站的流量（如 <code>blog</code>、<code>api</code>）被前置透传过来时，由它负责拿着对应的 SSL 证书进行真正的 TLS 解密，并处理具体的页面展示、反向代理（如转发给 FRP 面板）等常规业务。</li>
</ul>
<h4 id="_2-证书自动化申请的-80端口死锁-陷阱" tabindex="-1">2. 证书自动化申请的“80端口死锁”陷阱 <a class="header-anchor" href="#_2-证书自动化申请的-80端口死锁-陷阱" aria-label="Permalink to &quot;2. 证书自动化申请的“80端口死锁”陷阱&quot;">&ZeroWidthSpace;</a></h4>
<p>由于 443 端口被前置的 Nginx Stream 强行接管以处理 TCP 流量，传统的通过 443 端口进行 TLS 证书验证的方式将会失效。同时，如果你的 80 端口设置了“无脑强制跳转 HTTPS (443)”，会导致 Let's Encrypt 等机构的 HTTP-01 验证请求被踢入 443 端口的死胡同。</p>
<ul>
<li><strong>处理方案：</strong> 在负责监听 80 端口的配置中，必须采用<strong>精准规则分流</strong>。放行所有针对 <code>/.well-known/acme-challenge/</code> 路径的纯 HTTP 访问，直接在本地返回验证文件；仅对除此以外的正常访客流量执行 301 强制跳转 HTTPS。</li>
</ul>
<h4 id="_3-访客真实-ip-丢失问题-proxy-protocol-传递" tabindex="-1">3. 访客真实 IP 丢失问题 (PROXY Protocol 传递) <a class="header-anchor" href="#_3-访客真实-ip-丢失问题-proxy-protocol-传递" aria-label="Permalink to &quot;3. 访客真实 IP 丢失问题 (PROXY Protocol 传递)&quot;">&ZeroWidthSpace;</a></h4>
<p>流量经过 Nginx Stream 的四层转发后，内网的 Xray 和后置的建站 Web 服务看到的访客源 IP 都会变成 <code>127.0.0.1</code>。这会导致博客无法统计访客真实地域，日志失去审计价值，甚至可能误触后端服务的防 CC 攻击机制。</p>
<ul>
<li><strong>处理方案：</strong> 必须在流量链条上启用代理协议。
<ul>
<li><strong>Nginx 转发侧：</strong> 在 <code>stream</code> 模块的 <code>proxy_pass</code> 下方开启 <code>proxy_protocol on;</code>。</li>
<li><strong>Xray 接收侧：</strong> 在入站规则中开启 <code>acceptProxyProtocol: true</code>，并在回落规则中配置 <code>xver: 1</code> 或 <code>xver: 2</code> 以继续向后传递 IP。</li>
<li><strong>后置 Web 侧：</strong> 在监听端口处加上 <code>proxy_protocol</code> 标识，并使用 <code>set_real_ip_from 127.0.0.1;</code> 来恢复访客的真实 IP。</li>
</ul>
</li>
</ul>
<h4 id="_4-tls-in-tls-特征审计与-xtls-vision" tabindex="-1">4. TLS in TLS 特征审计与 XTLS-Vision <a class="header-anchor" href="#_4-tls-in-tls-特征审计与-xtls-vision" aria-label="Permalink to &quot;4. TLS in TLS 特征审计与 XTLS-Vision&quot;">&ZeroWidthSpace;</a></h4>
<ul>
<li><strong>问题说明：</strong> 当我们通过代理访问一个原本就是 HTTPS 的网站时，流量会被加密两次：内层是目标网站的 TLS 加密，外层是代理协议的 TLS 加密。这种“套娃”式的双重加密（TLS in TLS）会产生独特的握手特征和数据包长度分布（例如典型的握手包大小异常）。现代防火墙可以通过这些统计学特征，轻易识别出这是一条代理隧道并进行干扰。</li>
<li><strong>处理方案：</strong> 得益于我们这套方案让 Xray 掌握了原始 TCP 并亲自处理外层 TLS 握手，我们可以启用 <strong>XTLS-Vision</strong> 技术。
<ul>
<li>在 Xray 的 VLESS 入站配置中，将 <code>flow</code> 设置为 <code>xtls-rprx-vision</code>。</li>
<li><strong>工作原理：</strong> 在完成外层 TLS 握手并验证 UUID 合法后，它会检测内层传输的是否为 TLS 1.2/1.3 流量。如果是，Vision 会停止外层的二次加密，直接将内层的 TLS 流量”拼接”传递出去。这样一来，TLS in TLS 的特征被彻底消除，在防火墙看来，这段流量与普通的单一 HTTPS 流量毫无二致。</li>
</ul>
</li>
</ul>
<p>整体拓扑图如下：</p>
<p><img src="./../../../public/posts/2026/03/10001/traditional-solution-topology-diagram.png" alt="传统方案拓扑图"></p>
<h2 id="grpc-tls-cloudflare-方案" tabindex="-1">gRPC + TLS + Cloudflare 方案 <a class="header-anchor" href="#grpc-tls-cloudflare-方案" aria-label="Permalink to &quot;gRPC + TLS + Cloudflare 方案&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="方案概述" tabindex="-1">方案概述 <a class="header-anchor" href="#方案概述" aria-label="Permalink to &quot;方案概述&quot;">&ZeroWidthSpace;</a></h3>
<p>这个方案依靠 Cloudflare 服务实现流量转发，通过 CDN 网络隐藏源站 IP，并利用 gRPC 协议进行数据传输。</p>
<h3 id="工作流程" tabindex="-1">工作流程 <a class="header-anchor" href="#工作流程" aria-label="Permalink to &quot;工作流程&quot;">&ZeroWidthSpace;</a></h3>
<ol>
<li><strong>统一入口与 CDN 流量接管 (Cloudflare 前置)</strong>：客户端不再直接连接你的服务器 IP，而是将流量发送给 Cloudflare 全球分布的 Anycast 泛播节点。所有的公网流量统一经过 Cloudflare 的 443 端口进入。在这个阶段，<strong>外层 TLS 加密由 Cloudflare 负责终结（解密）</strong>，使用的是托管在 Cloudflare 上的公共域名证书。</li>
<li><strong>基于 HTTP/2 的七层路由与回源 (流量清洗与转发)</strong>：Cloudflare 在解密外层 TLS 后，能够看到完整的 HTTP/2 报文和请求路径（Path）。此时，它开始在七层（应用层）规划流量路径：
<ul>
<li><strong>常规服务转发</strong>：如果访问的是普通的网页路径（如 <code>/</code> 或 <code>/blog</code>），Cloudflare 会按照常规 CDN 逻辑处理，返回缓存或向源站请求网页内容。</li>
<li><strong>核心流量透传 (gRPC 隧道)</strong>：当客户端发出的请求是特定的 gRPC POST 请求（例如路径为 <code>/TunService/Tun</code>，且 Header 包含 <code>content-type: application/grpc</code>），Cloudflare 会识别出这是一个合法的 gRPC API 调用。它会保持 HTTP/2 的多路复用特性，<strong>重新使用 TLS 加密</strong>（回源加密），将这段 gRPC 流量转发给你隐藏在背后的真实服务器 IP。</li>
</ul>
</li>
<li><strong>源站 Xray 核心解密与鉴权 (回源接收)</strong>：你的服务器（源站）上的 Xray 监听着 443 端口，接收来自 Cloudflare 转发过来的回源 TLS 流量。Xray 会使用事先配置好的本地证书进行二次解密。解密完成后，Xray 解析出 gRPC payload 中的 VLESS 协议数据，并提取出 UUID 等参数：
<ul>
<li><strong>特殊访问放行</strong>：Xray 在这里判断 UUID 和 gRPC <code>serviceName</code> 是否合法。如果完全匹配，则放行该请求，提取出真实的目标网站地址，并代为发起访问。</li>
</ul>
</li>
<li><strong>防御机制与流量隔离 (云端与本地双重阻断)</strong>：如果这是一个不合法的请求：
<ul>
<li><strong>云端阻断</strong>：普通的恶意域名扫描或 IP 探测，绝大多数会被 Cloudflare 的 WAF（Web 应用防火墙）直接拦截在海外边缘节点，根本到达不了你的服务器。</li>
<li><strong>本地忽略/回落</strong>：如果探测流量穿透了 CF 到达源站，或者有人直接针对你的服务器真实 IP 发起扫描，由于他们无法提供正确的 gRPC 路径和 VLESS UUID，Xray 会直接断开连接或根据配置回落到伪装网站，保护核心服务不被发现。</li>
</ul>
</li>
</ol>
<h3 id="方案优势" tabindex="-1">方案优势 <a class="header-anchor" href="#方案优势" aria-label="Permalink to &quot;方案优势&quot;">&ZeroWidthSpace;</a></h3>
<h4 id="_1-ip-隐藏与源站保护-核心优势" tabindex="-1">1. IP 隐藏与源站保护（核心优势） <a class="header-anchor" href="#_1-ip-隐藏与源站保护-核心优势" aria-label="Permalink to &quot;1. IP 隐藏与源站保护（核心优势）&quot;">&ZeroWidthSpace;</a></h4>
<p><strong>完全隐藏源站 IP</strong>：客户端只需要知道 Cloudflare 托管的域名（如 <code>proxy.yourdomain.com</code>），无需知道真实服务器 IP。所有流量都先到达 CF 的边缘节点，再由 CF 回源到你的服务器。即使有人想要探测或攻击，他们面对的是 Cloudflare 的全球分布式网络，而不是你的单台 VPS。</p>
<p><strong>天然抗 DDoS</strong>：Cloudflare 提供企业级的 DDoS 防护能力。无论是 SYN Flood、UDP Flood 还是应用层攻击，绝大多数恶意流量会被 CF 的边缘节点直接过滤，根本到达不了源站。这对于个人 VPS 来说，相当于免费获得了价值数千美元的防护服务。</p>
<p><strong>域名扫描免疫</strong>：传统方案中，如果有人通过 CT 日志、DNS 历史记录等手段发现了你的域名，可以直接解析出服务器 IP 并进行探测。而使用 Cloudflare 后，域名解析指向的是 CF 的 IP 段，攻击者无法通过域名反查到源站真实位置。</p>
<h4 id="_2-流量特征混淆与合法性伪装" tabindex="-1">2. 流量特征混淆与合法性伪装 <a class="header-anchor" href="#_2-流量特征混淆与合法性伪装" aria-label="Permalink to &quot;2. 流量特征混淆与合法性伪装&quot;">&ZeroWidthSpace;</a></h4>
<p><strong>gRPC 协议的天然优势</strong>：gRPC 是 Google 开发的现代 RPC 框架，基于 HTTP/2 协议，在企业级微服务架构中被广泛使用。当你的流量以 gRPC 形式传输时，在防火墙看来，这就是一个普通的 API 服务调用，与 Google、Netflix、Uber 等大厂的内部服务通信毫无二致。</p>
<p><strong>HTTP/2 多路复用特性</strong>：gRPC 基于 HTTP/2，支持在单一 TCP 连接上并发传输多个请求。这意味着你的代理流量可以与正常的网页访问、API 调用混合在同一条连接中，流量模式更加自然，难以被统计学分析识别。</p>
<p><strong>CDN 流量掩护</strong>：所有流量都经过 Cloudflare 的 CDN 网络，在外部观察者看来，这只是一个使用了 CF 加速的普通网站。由于全球有数百万网站使用 Cloudflare，你的流量完全淹没在海量的正常 CDN 流量中，不会引起任何特殊关注。</p>
<h4 id="_3-零证书管理成本" tabindex="-1">3. 零证书管理成本 <a class="header-anchor" href="#_3-零证书管理成本" aria-label="Permalink to &quot;3. 零证书管理成本&quot;">&ZeroWidthSpace;</a></h4>
<p><strong>Cloudflare 托管证书</strong>：外层 TLS 证书由 Cloudflare 自动签发和续期，你无需关心证书过期问题。CF 使用的是权威 CA 签发的证书，浏览器和客户端完全信任。</p>
<p><strong>回源证书灵活性</strong>：源站到 Cloudflare 的回源连接，可以使用 CF 提供的 Origin CA 证书（15 年有效期），也可以使用自签名证书。由于这段连接只在 CF 和你的服务器之间，不会被外部审计，配置极其简单。</p>
<h4 id="_4-全球加速与智能路由" tabindex="-1">4. 全球加速与智能路由 <a class="header-anchor" href="#_4-全球加速与智能路由" aria-label="Permalink to &quot;4. 全球加速与智能路由&quot;">&ZeroWidthSpace;</a></h4>
<p><strong>Anycast 网络</strong>：Cloudflare 在全球拥有 300+ 个数据中心，使用 Anycast 技术。客户端会自动连接到地理位置最近的 CF 节点，大幅降低首包延迟。</p>
<p><strong>智能回源优化</strong>：CF 会根据网络状况，选择最优的回源路径。即使你的服务器位于美国西海岸，亚洲用户也能先连接到亚洲的 CF 节点，再由 CF 的骨干网高速回源，避免了跨洋链路的丢包和延迟。</p>
<h4 id="_5-配置简单-维护成本低" tabindex="-1">5. 配置简单，维护成本低 <a class="header-anchor" href="#_5-配置简单-维护成本低" aria-label="Permalink to &quot;5. 配置简单，维护成本低&quot;">&ZeroWidthSpace;</a></h4>
<p><strong>无需复杂的 Nginx 分流</strong>：不需要配置 Nginx Stream 模块的 SNI 分流、PROXY Protocol 传递等复杂逻辑。Xray 直接监听 443 端口，接收 CF 的回源流量即可。</p>
<p><strong>统一的流量入口</strong>：所有业务（网站、API、代理）都可以通过同一个域名和端口提供服务，由 Cloudflare 根据路径进行智能分发。配置清晰，易于管理。</p>
<h3 id="注意事项" tabindex="-1">注意事项 <a class="header-anchor" href="#注意事项" aria-label="Permalink to &quot;注意事项&quot;">&ZeroWidthSpace;</a></h3>
<h4 id="优质直连线路-如-cn2-gia-的路由失效与资源浪费" tabindex="-1">优质直连线路 (如 CN2 GIA) 的路由失效与资源浪费 <a class="header-anchor" href="#优质直连线路-如-cn2-gia-的路由失效与资源浪费" aria-label="Permalink to &quot;优质直连线路 (如 CN2 GIA) 的路由失效与资源浪费&quot;">&ZeroWidthSpace;</a></h4>
<ul>
<li><strong>问题说明：</strong> 引入 Cloudflare 作为前置代理的核心代价，是彻底丧失服务器原有的优质物理链路（如电信 CN2 GIA、移动 CMIN2 等针对亚洲优化的专线）优势。流量路径从”客户端专属高速直连”变成了”客户端先连接 Cloudflare 就近泛播节点，再由 CF 骨干网回源”。国内连接免费版 CF 节点通常走拥堵的普通公网，受限于”木桶效应”，原本极优的网络体验在晚高峰时会被 CF 的入站线路瓶颈所严重拖累。</li>
</ul>
<h3 id="方案对比" tabindex="-1">方案对比 <a class="header-anchor" href="#方案对比" aria-label="Permalink to &quot;方案对比&quot;">&ZeroWidthSpace;</a></h3>
<p><img src="./../../../public/posts/2026/03/10001/gRPC-CF-solution-and-direct-connection-comparison.png" alt="gRPC-CF-solution-and-direct-connection-comparison.png"></p>
<h2 id="三种方案综合对比" tabindex="-1">三种方案综合对比 <a class="header-anchor" href="#三种方案综合对比" aria-label="Permalink to &quot;三种方案综合对比&quot;">&ZeroWidthSpace;</a></h2>
<table>
<thead>
<tr>
<th>对比维度</th>
<th>REALITY</th>
<th>传统方案 (VLESS+TLS)</th>
<th>gRPC+Cloudflare</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>部署难度</strong></td>
<td>⭐⭐ 简单</td>
<td>⭐⭐⭐⭐ 复杂</td>
<td>⭐⭐⭐ 中等</td>
</tr>
<tr>
<td><strong>是否需要域名</strong></td>
<td>❌ 不需要</td>
<td>✅ 必须</td>
<td>✅ 必须</td>
</tr>
<tr>
<td><strong>是否需要证书</strong></td>
<td>❌ 不需要</td>
<td>✅ 需要申请和续期</td>
<td>⚠️ CF 自动管理</td>
</tr>
<tr>
<td><strong>源站 IP 暴露风险</strong></td>
<td>⚠️ 直接暴露</td>
<td>⚠️ 直接暴露</td>
<td>✅ 完全隐藏</td>
</tr>
<tr>
<td><strong>抗主动探测能力</strong></td>
<td>⭐⭐⭐⭐⭐ 极强</td>
<td>⭐⭐⭐⭐ 强</td>
<td>⭐⭐⭐⭐⭐ 极强</td>
</tr>
<tr>
<td><strong>抗 DDoS 能力</strong></td>
<td>⭐⭐ 弱</td>
<td>⭐⭐ 弱</td>
<td>⭐⭐⭐⭐⭐ 极强</td>
</tr>
<tr>
<td><strong>流量特征</strong></td>
<td>伪装成访问大厂网站</td>
<td>无需伪装，真实小站</td>
<td>伪装成 API 调用</td>
</tr>
<tr>
<td><strong>CT 日志风险</strong></td>
<td>✅ 无记录</td>
<td>⚠️ 有记录</td>
<td>⚠️ 有记录（CF 托管）</td>
</tr>
<tr>
<td><strong>DNS 解析风险</strong></td>
<td>✅ 无需解析</td>
<td>⚠️ 需要解析</td>
<td>⚠️ 需要解析</td>
</tr>
<tr>
<td><strong>网络性能</strong></td>
<td>⭐⭐⭐⭐⭐ 直连最优</td>
<td>⭐⭐⭐⭐⭐ 直连最优</td>
<td>⭐⭐⭐ 受 CF 节点影响</td>
</tr>
<tr>
<td><strong>延迟表现</strong></td>
<td>最低（直连）</td>
<td>最低（直连）</td>
<td>较高（多一跳 CDN）</td>
</tr>
<tr>
<td><strong>适合 CN2 GIA 等优质线路</strong></td>
<td>✅ 完美发挥</td>
<td>✅ 完美发挥</td>
<td>❌ 优势浪费</td>
</tr>
<tr>
<td><strong>多业务共存</strong></td>
<td>❌ 不建议</td>
<td>✅ 支持良好</td>
<td>✅ 支持良好</td>
</tr>
<tr>
<td><strong>配置复杂度</strong></td>
<td>简单（仅 Xray）</td>
<td>复杂（Nginx+Xray）</td>
<td>中等（Xray+CF 配置）</td>
</tr>
<tr>
<td><strong>维护成本</strong></td>
<td>低</td>
<td>高（证书续期、Nginx 配置）</td>
<td>低（CF 自动化）</td>
</tr>
<tr>
<td><strong>被封后恢复</strong></td>
<td>换 IP</td>
<td>换 IP</td>
<td>换域名（IP 无影响）</td>
</tr>
<tr>
<td><strong>适用场景</strong></td>
<td>个人轻量使用</td>
<td>多业务整合</td>
<td>高安全需求</td>
</tr>
</tbody>
</table>
]]></content>
        <author>
            <name>duyl328</name>
            <uri>https://seyl.me/about</uri>
        </author>
        <category label="思考"/>
        <category label="原创"/>
        <category label="网络"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[从痛点到解决方案：PLC数据格式转换调试工具的诞生]]></title>
        <id>https://seyl.me/posts/2025/07/plc-data-converter-debugger</id>
        <link href="https://seyl.me/posts/2025/07/plc-data-converter-debugger"/>
        <updated>2025-07-22T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[<h1 id="frontmatter-title" tabindex="-1">{{ $frontmatter.title }} <a class="header-anchor" href="#frontmatter-title" aria-label="Permalink to &quot;{{ $frontmatter.title }}&quot;">&ZeroWidthSpace;</a></h1>
<blockquote>
<p>✒️ 文章摘要</p>
</blockquote>
<!-- DESC SEP -->
<p>这篇文章记录了一个PLC数据格式转换调试工具的完整开发历程。作为工控工程师，作者深受各种PLC品牌数据格式差异之苦——西门子的CDAB字节序、欧姆龙的BADC排列、各种BCD/DEC编码格式，每次调试都需要翻阅文档、编写测试代码、反复试错。
受到&quot;暴力美学&quot;思维启发，作者决定开发一个纯前端工具，通过穷举所有可能的组合（字节序×编码格式×数据类型），让用户一次性看到所有转换结果，从中找到正确答案。工具采用HTML+JavaScript实现，无需后端依赖，支持详细的计算过程展示和一键复制功能。</p>
<p>文章详细分析了目标用户群体（自动化工程师、嵌入式开发者、系统集成商），通过西门子S7-1200、欧姆龙CP1E等实际案例展示工具价值，并分享了开发过程中的技术选型考虑和用户体验设计思路。最终选择开源，希望通过集体智慧让更多工程师受益，让PLC数据转换不再是技术噩梦。</p>
<!-- DESC SEP -->
<h2 id="前言-一个初学-plc-的日常困扰" tabindex="-1">前言：一个初学 PLC 的日常困扰 <a class="header-anchor" href="#前言-一个初学-plc-的日常困扰" aria-label="Permalink to &quot;前言：一个初学 PLC 的日常困扰&quot;">&ZeroWidthSpace;</a></h2>
<p>作为一名与PLC打交道的工程师，你是否也遇到过这样的场景：</p>
<ul>
<li>拿到一串神秘的数据：<code>[13312, 16128, 13312, 8704, 5888]</code></li>
<li>不知道这是什么格式，是大端还是小端？</li>
<li>是BCD编码还是普通的十进制？</li>
<li>需要翻阅厚厚的设备手册，寻找数据格式说明</li>
<li>写测试代码验证各种可能的组合</li>
<li>反复试错，直到找到正确的解析方式</li>
</ul>
<p>这种痛苦的经历，相信每个做自动化、工控、嵌入式开发的朋友都不陌生。正是这种日复一日的折磨，催生了这个PLC数据格式转换调试工具的想法。</p>
<h2 id="痛点分析-为什么plc数据转换这么复杂" tabindex="-1">痛点分析：为什么PLC数据转换这么复杂？ <a class="header-anchor" href="#痛点分析-为什么plc数据转换这么复杂" aria-label="Permalink to &quot;痛点分析：为什么PLC数据转换这么复杂？&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="_1-品牌差异化的-特色" tabindex="-1">1. 品牌差异化的&quot;特色&quot; <a class="header-anchor" href="#_1-品牌差异化的-特色" aria-label="Permalink to &quot;1. 品牌差异化的&quot;特色&quot;&quot;">&ZeroWidthSpace;</a></h3>
<p>每个PLC品牌都有自己的数据解析方式：</p>
<ul>
<li><strong>西门子</strong>：常用CDAB字节序</li>
<li><strong>欧姆龙</strong>：偏爱BADC排列</li>
<li><strong>三菱</strong>：有自己的一套规则</li>
<li><strong>施耐德、AB、台达</strong>...每家都不一样</li>
</ul>
<h3 id="_2-多样的数据编码格式" tabindex="-1">2. 多样的数据编码格式 <a class="header-anchor" href="#_2-多样的数据编码格式" aria-label="Permalink to &quot;2. 多样的数据编码格式&quot;">&ZeroWidthSpace;</a></h3>
<ul>
<li><strong>DEC</strong>：标准十进制编码</li>
<li><strong>BCD</strong>：二进制编码十进制（每个半字节0~9）</li>
<li><strong>HEX</strong>：十六进制直接转换</li>
<li><strong>ASCII</strong>：字符串编码</li>
<li>还有各种自定义格式...</li>
</ul>
<h3 id="_3-字节序的迷宫" tabindex="-1">3. 字节序的迷宫 <a class="header-anchor" href="#_3-字节序的迷宫" aria-label="Permalink to &quot;3. 字节序的迷宫&quot;">&ZeroWidthSpace;</a></h3>
<ul>
<li><strong>ABCD</strong>（大端）：网络字节序</li>
<li><strong>DCBA</strong>（小端）：Intel x86常见</li>
<li><strong>CDAB</strong>：中间字节交换</li>
<li><strong>BADC</strong>：另一种交换方式</li>
</ul>
<h3 id="_4-数据类型的复杂映射" tabindex="-1">4. 数据类型的复杂映射 <a class="header-anchor" href="#_4-数据类型的复杂映射" aria-label="Permalink to &quot;4. 数据类型的复杂映射&quot;">&ZeroWidthSpace;</a></h3>
<p>同样的原始数据，可能是：</p>
<ul>
<li><code>bool</code>、<code>byte</code>、<code>sbyte</code></li>
<li><code>short</code>、<code>ushort</code>、<code>int</code>、<code>uint</code></li>
<li><code>long</code>、<code>ulong</code>、<code>float</code>、<code>double</code></li>
<li>甚至是字符串或时间戳</li>
</ul>
<h2 id="灵感时刻-暴力美学的解决思路" tabindex="-1">灵感时刻：暴力美学的解决思路 <a class="header-anchor" href="#灵感时刻-暴力美学的解决思路" aria-label="Permalink to &quot;灵感时刻：暴力美学的解决思路&quot;">&ZeroWidthSpace;</a></h2>
<p>在又一次被数据格式折磨后，我突然想到：</p>
<blockquote>
<p>&quot;转换方式不知道？没关系，我让程序全算一遍，我只用看哪个是对的就好了！&quot;</p>
</blockquote>
<p>这就是典型的<strong>暴力美学</strong>思维：</p>
<ul>
<li>与其猜测，不如穷举</li>
<li>与其试错，不如全试</li>
<li>与其查手册，不如让计算机帮我们计算所有可能的组合</li>
</ul>
<h3 id="核心思路" tabindex="-1">核心思路 <a class="header-anchor" href="#核心思路" aria-label="Permalink to &quot;核心思路&quot;">&ZeroWidthSpace;</a></h3>
<ol>
<li><strong>输入原始数据</strong>：支持各种格式（byte[]、ushort[]、hex等）</li>
<li><strong>自动排列组合</strong>：字节序 × 编码格式 × 数据类型 = 所有可能结果</li>
<li><strong>一次性输出</strong>：让用户一眼看到哪个结果是合理的</li>
<li><strong>详细解释</strong>：告诉用户每种转换是怎么计算的</li>
</ol>
<h2 id="需求分析-这个工具应该为谁服务" tabindex="-1">需求分析：这个工具应该为谁服务？ <a class="header-anchor" href="#需求分析-这个工具应该为谁服务" aria-label="Permalink to &quot;需求分析：这个工具应该为谁服务？&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="目标用户群体" tabindex="-1">目标用户群体 <a class="header-anchor" href="#目标用户群体" aria-label="Permalink to &quot;目标用户群体&quot;">&ZeroWidthSpace;</a></h3>
<ol>
<li>
<p><strong>自动化工程师</strong></p>
<ul>
<li>需要对接各种品牌PLC</li>
<li>经常遇到数据格式不明的情况</li>
<li>希望快速验证数据解析结果</li>
</ul>
</li>
<li>
<p><strong>嵌入式开发者</strong></p>
<ul>
<li>处理Modbus、CAN、串口等协议数据</li>
<li>需要在不同字节序间转换</li>
<li>调试通信协议时需要数据格式验证</li>
</ul>
</li>
<li>
<p><strong>系统集成商</strong></p>
<ul>
<li>对接多种设备和协议</li>
<li>需要快速理解设备数据格式</li>
<li>项目时间紧，不想深入研究每种设备的文档</li>
</ul>
</li>
<li>
<p><strong>学习者和研究人员</strong></p>
<ul>
<li>学习PLC通信协议</li>
<li>了解不同数据编码方式</li>
<li>需要直观的工具来理解概念</li>
</ul>
</li>
</ol>
<h3 id="用户场景" tabindex="-1">用户场景 <a class="header-anchor" href="#用户场景" aria-label="Permalink to &quot;用户场景&quot;">&ZeroWidthSpace;</a></h3>
<p><strong>场景1：新项目对接</strong></p>
<div class="language- vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>工程师接到任务，需要对接一台新的PLC设备</span></span>
<span class="line"><span>拿到一串数据：[0x34, 0x00, 0x3F, 0x00, 0x34, 0x00]</span></span>
<span class="line"><span>不确定是什么格式，使用工具一键获得所有可能的解析结果</span></span></code></pre>
</div><p><strong>场景2：调试通信协议</strong></p>
<div class="language- vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>Modbus通信中收到异常数据，怀疑是字节序问题</span></span>
<span class="line"><span>将数据输入工具，对比各种字节序的结果</span></span>
<span class="line"><span>快速定位问题所在</span></span></code></pre>
</div><p><strong>场景3：学习和验证</strong></p>
<div class="language- vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>学习BCD编码的原理</span></span>
<span class="line"><span>输入测试数据，查看详细的转换过程</span></span>
<span class="line"><span>理解每一步计算的逻辑</span></span></code></pre>
</div><h2 id="设计理念-简单而强大" tabindex="-1">设计理念：简单而强大 <a class="header-anchor" href="#设计理念-简单而强大" aria-label="Permalink to &quot;设计理念：简单而强大&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="_1-纯前端解决方案" tabindex="-1">1. 纯前端解决方案 <a class="header-anchor" href="#_1-纯前端解决方案" aria-label="Permalink to &quot;1. 纯前端解决方案&quot;">&ZeroWidthSpace;</a></h3>
<p><strong>为什么选择纯前端？</strong></p>
<ul>
<li><strong>无依赖</strong>：打开浏览器就能用，不需要安装任何软件</li>
<li><strong>隐私安全</strong>：数据不会上传到服务器，完全本地处理</li>
<li><strong>跨平台</strong>：Windows、Mac、Linux都能用</li>
<li><strong>便携性</strong>：可以保存到本地，随时随地使用</li>
</ul>
<h3 id="_2-暴力穷举策略" tabindex="-1">2. 暴力穷举策略 <a class="header-anchor" href="#_2-暴力穷举策略" aria-label="Permalink to &quot;2. 暴力穷举策略&quot;">&ZeroWidthSpace;</a></h3>
<p><strong>核心算法思路：</strong></p>
<div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (每种字节序) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (每种编码格式) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (每种数据类型) {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            计算结果并展示</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div><p>这种&quot;笨办法&quot;看起来低效，但实际上：</p>
<ul>
<li>计算量并不大（现代浏览器完全能处理）</li>
<li>用户体验极佳（一次查看所有可能）</li>
<li>避免了用户的试错成本</li>
</ul>
<h3 id="_3-教育式交互" tabindex="-1">3. 教育式交互 <a class="header-anchor" href="#_3-教育式交互" aria-label="Permalink to &quot;3. 教育式交互&quot;">&ZeroWidthSpace;</a></h3>
<p>不仅要给出结果，还要告诉用户<strong>为什么</strong>是这个结果：</p>
<div class="language- vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>详细计算过程：</span></span>
<span class="line"><span>1. 原始数据：[13312, 16128]（ushort[]）</span></span>
<span class="line"><span>2. 转换为字节：[00, 34, 00, 3F]</span></span>
<span class="line"><span>3. 应用CDAB字节序：[34, 00, 3F, 00]</span></span>
<span class="line"><span>4. 按int32解析：0x003F0034 = 4128820</span></span>
<span class="line"><span>5. 结果：4128820</span></span></code></pre>
</div><h2 id="功能设计-覆盖所有可能的场景" tabindex="-1">功能设计：覆盖所有可能的场景 <a class="header-anchor" href="#功能设计-覆盖所有可能的场景" aria-label="Permalink to &quot;功能设计：覆盖所有可能的场景&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="核心功能模块" tabindex="-1">核心功能模块 <a class="header-anchor" href="#核心功能模块" aria-label="Permalink to &quot;核心功能模块&quot;">&ZeroWidthSpace;</a></h3>
<h4 id="_1-数据输入模块" tabindex="-1">1. 数据输入模块 <a class="header-anchor" href="#_1-数据输入模块" aria-label="Permalink to &quot;1. 数据输入模块&quot;">&ZeroWidthSpace;</a></h4>
<div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 支持多种输入格式</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> byte[]: [</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0x01</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0x00</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0x00</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0x00</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ushort[]: [</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">256</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">512</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> 十六进制</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">01</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 00</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 00</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 00</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> 十进制数组</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: [</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]</span></span></code></pre>
</div><h4 id="_2-转换引擎" tabindex="-1">2. 转换引擎 <a class="header-anchor" href="#_2-转换引擎" aria-label="Permalink to &quot;2. 转换引擎&quot;">&ZeroWidthSpace;</a></h4>
<div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 字节序处理</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> byteOrders</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'ABCD'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">bytes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> bytes,                    </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 大端</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'DCBA'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">bytes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> bytes.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">reverse</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(),          </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 小端</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'CDAB'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">bytes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> swapWords</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(bytes),         </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 西门子</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'BADC'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">bytes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> swapWordBytes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(bytes)      </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 欧姆龙</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 编码处理</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> encodings</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'DEC'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">value</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> value,                     </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 普通十进制</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'BCD'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">value</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> decodeBCD</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(value),          </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// BCD解码</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'HEX'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">value</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> value.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">toString</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">16</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)         </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 十六进制</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">};</span></span></code></pre>
</div><h4 id="_3-结果展示模块" tabindex="-1">3. 结果展示模块 <a class="header-anchor" href="#_3-结果展示模块" aria-label="Permalink to &quot;3. 结果展示模块&quot;">&ZeroWidthSpace;</a></h4>
<ul>
<li>表格形式展示所有组合结果</li>
<li>智能高亮异常值</li>
<li>支持按类型、字节序、编码分组</li>
<li>一键复制功能</li>
</ul>
<h4 id="_4-详细解释模块" tabindex="-1">4. 详细解释模块 <a class="header-anchor" href="#_4-详细解释模块" aria-label="Permalink to &quot;4. 详细解释模块&quot;">&ZeroWidthSpace;</a></h4>
<ul>
<li>步骤化展示计算过程</li>
<li>二进制、十六进制、十进制多重显示</li>
<li>字节操作可视化</li>
</ul>
<h3 id="高级功能" tabindex="-1">高级功能 <a class="header-anchor" href="#高级功能" aria-label="Permalink to &quot;高级功能&quot;">&ZeroWidthSpace;</a></h3>
<h4 id="_1-智能验证" tabindex="-1">1. 智能验证 <a class="header-anchor" href="#_1-智能验证" aria-label="Permalink to &quot;1. 智能验证&quot;">&ZeroWidthSpace;</a></h4>
<div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// BCD格式验证</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">function</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> isValidBCD</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">value</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> value.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">toString</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">16</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">split</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">every</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">digit</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        digit </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">>=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> '0'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> &#x26;&#x26;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> digit </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> '9'</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    );</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 浮点数合理性检查</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">function</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> isReasonableFloat</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">value</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> !</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">isNaN</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(value) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;&#x26;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> isFinite</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(value) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;&#x26;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">           Math.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">abs</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(value) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1e10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div><h4 id="_2-品牌预设" tabindex="-1">2. 品牌预设 <a class="header-anchor" href="#_2-品牌预设" aria-label="Permalink to &quot;2. 品牌预设&quot;">&ZeroWidthSpace;</a></h4>
<div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> plcPresets</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    '西门子S7'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: { byteOrder: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'CDAB'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, encoding: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'DEC'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> },</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    '欧姆龙CP1E'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: { byteOrder: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'BADC'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, encoding: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'DEC'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> },</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    '三菱FX'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: { byteOrder: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'ABCD'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, encoding: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'BCD'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> },</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // ...更多品牌预设</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">};</span></span></code></pre>
</div><h2 id="技术实现-简洁而高效" tabindex="-1">技术实现：简洁而高效 <a class="header-anchor" href="#技术实现-简洁而高效" aria-label="Permalink to &quot;技术实现：简洁而高效&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="技术栈选择" tabindex="-1">技术栈选择 <a class="header-anchor" href="#技术栈选择" aria-label="Permalink to &quot;技术栈选择&quot;">&ZeroWidthSpace;</a></h3>
<p><strong>HTML5 + Vanilla JavaScript + CSS3</strong></p>
<p><strong>为什么不用框架？</strong></p>
<ul>
<li><strong>轻量级</strong>：整个工具就一个HTML文件，易于分发</li>
<li><strong>兼容性好</strong>：不依赖特定版本的框架</li>
<li><strong>学习成本低</strong>：任何前端开发者都能理解和修改</li>
<li><strong>性能优异</strong>：没有框架开销，原生JS性能最佳</li>
</ul>
<h3 id="核心算法" tabindex="-1">核心算法 <a class="header-anchor" href="#核心算法" aria-label="Permalink to &quot;核心算法&quot;">&ZeroWidthSpace;</a></h3>
<h4 id="_1-字节序转换算法" tabindex="-1">1. 字节序转换算法 <a class="header-anchor" href="#_1-字节序转换算法" aria-label="Permalink to &quot;1. 字节序转换算法&quot;">&ZeroWidthSpace;</a></h4>
<div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">function</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> reorderBytes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">bytes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">order</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> result</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Uint8Array</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(bytes.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">length</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> wordSize</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 16位为一个字</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> bytes.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">length</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> wordSize </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> word1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> bytes.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">slice</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(i, i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> wordSize);</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> word2</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> bytes.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">slice</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> wordSize, i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> wordSize </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        switch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(order) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            case</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'ABCD'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 不变</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                result.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(word1, i);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                result.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(word2, i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> wordSize);</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                break</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            case</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'CDAB'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 字交换</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                result.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(word2, i);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                result.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(word1, i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> wordSize);</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                break</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">            // ... 其他情况</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> result;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div><h4 id="_2-bcd解码算法" tabindex="-1">2. BCD解码算法 <a class="header-anchor" href="#_2-bcd解码算法" aria-label="Permalink to &quot;2. BCD解码算法&quot;">&ZeroWidthSpace;</a></h4>
<div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">function</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> decodeBCD</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">value</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> result </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> multiplier </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    while</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (value </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">></span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> digit</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> value </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0xF</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 取低4位</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (digit </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">></span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 9</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> NaN</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 非法BCD</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        result </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> digit </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> multiplier;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        multiplier </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        value </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">>>=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 右移4位</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> result;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div><h3 id="性能优化" tabindex="-1">性能优化 <a class="header-anchor" href="#性能优化" aria-label="Permalink to &quot;性能优化&quot;">&ZeroWidthSpace;</a></h3>
<h4 id="_1-web-worker支持" tabindex="-1">1. Web Worker支持 <a class="header-anchor" href="#_1-web-worker支持" aria-label="Permalink to &quot;1. Web Worker支持&quot;">&ZeroWidthSpace;</a></h4>
<p>对于大数据量的处理，使用Web Worker避免阻塞UI：</p>
<div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 主线程</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> worker</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Worker</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'converter-worker.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">worker.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">postMessage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">({ data: largeDataArray });</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">worker.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">onmessage</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">e</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    displayResults</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(e.data.results);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// Worker线程</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">self.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">onmessage</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> function</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">e</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> results</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> processAllCombinations</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(e.data.data);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    self.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">postMessage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">({ results });</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">};</span></span></code></pre>
</div><h4 id="_2-结果缓存" tabindex="-1">2. 结果缓存 <a class="header-anchor" href="#_2-结果缓存" aria-label="Permalink to &quot;2. 结果缓存&quot;">&ZeroWidthSpace;</a></h4>
<div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> resultCache</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Map</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">function</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> getCachedResult</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">data</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">config</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> key</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> `${</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">JSON</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">stringify</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">data</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}-${</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">JSON</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">stringify</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">config</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (resultCache.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">has</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(key)) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> resultCache.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(key);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> result</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> calculateResult</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(data, config);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    resultCache.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(key, result);</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> result;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div><h2 id="用户体验设计-让复杂变简单" tabindex="-1">用户体验设计：让复杂变简单 <a class="header-anchor" href="#用户体验设计-让复杂变简单" aria-label="Permalink to &quot;用户体验设计：让复杂变简单&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="交互流程设计" tabindex="-1">交互流程设计 <a class="header-anchor" href="#交互流程设计" aria-label="Permalink to &quot;交互流程设计&quot;">&ZeroWidthSpace;</a></h3>
<div class="language- vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>1. 用户输入原始数据</span></span>
<span class="line"><span>   ↓</span></span>
<span class="line"><span>2. 选择输入数据类型</span></span>
<span class="line"><span>   ↓</span></span>
<span class="line"><span>3. 点击"分析所有可能"</span></span>
<span class="line"><span>   ↓</span></span>
<span class="line"><span>4. 查看结果表格，找到合理的结果</span></span>
<span class="line"><span>   ↓</span></span>
<span class="line"><span>5. 点击"详细说明"了解计算过程</span></span>
<span class="line"><span>   ↓</span></span>
<span class="line"><span>6. 复制正确的结果用于实际项目</span></span></code></pre>
</div><h3 id="ui布局设计" tabindex="-1">UI布局设计 <a class="header-anchor" href="#ui布局设计" aria-label="Permalink to &quot;UI布局设计&quot;">&ZeroWidthSpace;</a></h3>
<div class="language- vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>┌─────────────────────────────────────┐</span></span>
<span class="line"><span>│              数据输入区              │</span></span>
<span class="line"><span>│  [                               ]  │</span></span>
<span class="line"><span>│  输入格式: [byte[] ▼] [分析所有可能]  │</span></span>
<span class="line"><span>└─────────────────────────────────────┘</span></span>
<span class="line"><span>┌─────────────────────────────────────┐</span></span>
<span class="line"><span>│              控制选项区              │</span></span>
<span class="line"><span>│  字节序: [全部▼]  编码: [全部▼]     │</span></span>
<span class="line"><span>│  数据类型: [全部▼]                  │</span></span>
<span class="line"><span>└─────────────────────────────────────┘</span></span>
<span class="line"><span>┌─────────────────────────────────────┐</span></span>
<span class="line"><span>│              结果展示区              │</span></span>
<span class="line"><span>│  │字节序│编码│类型│结果  │操作│     │</span></span>
<span class="line"><span>│  │ABCD │DEC │int │xxxxx │详情│复制│ │</span></span>
<span class="line"><span>│  │CDAB │DEC │int │yyyyy │详情│复制│ │</span></span>
<span class="line"><span>│  │...  │... │... │...   │... │... │ │</span></span>
<span class="line"><span>└─────────────────────────────────────┘</span></span></code></pre>
</div><h3 id="错误处理和用户引导" tabindex="-1">错误处理和用户引导 <a class="header-anchor" href="#错误处理和用户引导" aria-label="Permalink to &quot;错误处理和用户引导&quot;">&ZeroWidthSpace;</a></h3>
<div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 输入验证</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">function</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> validateInput</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">input</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">type</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (type </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">===</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'byte[]'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // 检查是否为有效的字节数组</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> input.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">every</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">val</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> val </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">>=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> &#x26;&#x26;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> val </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 255</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">else</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (type </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">===</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'ushort[]'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // 检查是否为有效的无符号短整型数组</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> input.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">every</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">val</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> val </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">>=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> &#x26;&#x26;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> val </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 65535</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 友好的错误提示</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">function</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> showUserFriendlyError</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">errorType</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> messages</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">        'invalid_byte'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'输入的字节值必须在0-255之间'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">        'invalid_ushort'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'输入的ushort值必须在0-65535之间'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">        'empty_input'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'请输入要转换的数据'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">        'invalid_format'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'数据格式不正确，请检查输入'</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    };</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    showToast</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(messages[errorType] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">||</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> '未知错误'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div><h2 id="实际应用案例" tabindex="-1">实际应用案例 <a class="header-anchor" href="#实际应用案例" aria-label="Permalink to &quot;实际应用案例&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="案例1-西门子s7-1200数据解析" tabindex="-1">案例1：西门子S7-1200数据解析 <a class="header-anchor" href="#案例1-西门子s7-1200数据解析" aria-label="Permalink to &quot;案例1：西门子S7-1200数据解析&quot;">&ZeroWidthSpace;</a></h3>
<p><strong>背景</strong>：某工厂的温度监控系统，从西门子PLC读取到数据：<code>[0x41, 0xA0, 0x00, 0x00]</code></p>
<p><strong>使用工具分析</strong>：</p>
<ol>
<li>输入数据：<code>[65, 160, 0, 0]</code>（转换为byte[]）</li>
<li>选择&quot;分析所有可能&quot;</li>
<li>查看结果表格：</li>
</ol>
<p>| 字节序 | 编码 | 类型 | 结果 |
|</p>
]]></summary>
        <content type="html"><![CDATA[<h1 id="frontmatter-title" tabindex="-1">{{ $frontmatter.title }} <a class="header-anchor" href="#frontmatter-title" aria-label="Permalink to &quot;{{ $frontmatter.title }}&quot;">&ZeroWidthSpace;</a></h1>
<blockquote>
<p>✒️ 文章摘要</p>
</blockquote>
<!-- DESC SEP -->
<p>这篇文章记录了一个PLC数据格式转换调试工具的完整开发历程。作为工控工程师，作者深受各种PLC品牌数据格式差异之苦——西门子的CDAB字节序、欧姆龙的BADC排列、各种BCD/DEC编码格式，每次调试都需要翻阅文档、编写测试代码、反复试错。
受到&quot;暴力美学&quot;思维启发，作者决定开发一个纯前端工具，通过穷举所有可能的组合（字节序×编码格式×数据类型），让用户一次性看到所有转换结果，从中找到正确答案。工具采用HTML+JavaScript实现，无需后端依赖，支持详细的计算过程展示和一键复制功能。</p>
<p>文章详细分析了目标用户群体（自动化工程师、嵌入式开发者、系统集成商），通过西门子S7-1200、欧姆龙CP1E等实际案例展示工具价值，并分享了开发过程中的技术选型考虑和用户体验设计思路。最终选择开源，希望通过集体智慧让更多工程师受益，让PLC数据转换不再是技术噩梦。</p>
<!-- DESC SEP -->
<h2 id="前言-一个初学-plc-的日常困扰" tabindex="-1">前言：一个初学 PLC 的日常困扰 <a class="header-anchor" href="#前言-一个初学-plc-的日常困扰" aria-label="Permalink to &quot;前言：一个初学 PLC 的日常困扰&quot;">&ZeroWidthSpace;</a></h2>
<p>作为一名与PLC打交道的工程师，你是否也遇到过这样的场景：</p>
<ul>
<li>拿到一串神秘的数据：<code>[13312, 16128, 13312, 8704, 5888]</code></li>
<li>不知道这是什么格式，是大端还是小端？</li>
<li>是BCD编码还是普通的十进制？</li>
<li>需要翻阅厚厚的设备手册，寻找数据格式说明</li>
<li>写测试代码验证各种可能的组合</li>
<li>反复试错，直到找到正确的解析方式</li>
</ul>
<p>这种痛苦的经历，相信每个做自动化、工控、嵌入式开发的朋友都不陌生。正是这种日复一日的折磨，催生了这个PLC数据格式转换调试工具的想法。</p>
<h2 id="痛点分析-为什么plc数据转换这么复杂" tabindex="-1">痛点分析：为什么PLC数据转换这么复杂？ <a class="header-anchor" href="#痛点分析-为什么plc数据转换这么复杂" aria-label="Permalink to &quot;痛点分析：为什么PLC数据转换这么复杂？&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="_1-品牌差异化的-特色" tabindex="-1">1. 品牌差异化的&quot;特色&quot; <a class="header-anchor" href="#_1-品牌差异化的-特色" aria-label="Permalink to &quot;1. 品牌差异化的&quot;特色&quot;&quot;">&ZeroWidthSpace;</a></h3>
<p>每个PLC品牌都有自己的数据解析方式：</p>
<ul>
<li><strong>西门子</strong>：常用CDAB字节序</li>
<li><strong>欧姆龙</strong>：偏爱BADC排列</li>
<li><strong>三菱</strong>：有自己的一套规则</li>
<li><strong>施耐德、AB、台达</strong>...每家都不一样</li>
</ul>
<h3 id="_2-多样的数据编码格式" tabindex="-1">2. 多样的数据编码格式 <a class="header-anchor" href="#_2-多样的数据编码格式" aria-label="Permalink to &quot;2. 多样的数据编码格式&quot;">&ZeroWidthSpace;</a></h3>
<ul>
<li><strong>DEC</strong>：标准十进制编码</li>
<li><strong>BCD</strong>：二进制编码十进制（每个半字节0~9）</li>
<li><strong>HEX</strong>：十六进制直接转换</li>
<li><strong>ASCII</strong>：字符串编码</li>
<li>还有各种自定义格式...</li>
</ul>
<h3 id="_3-字节序的迷宫" tabindex="-1">3. 字节序的迷宫 <a class="header-anchor" href="#_3-字节序的迷宫" aria-label="Permalink to &quot;3. 字节序的迷宫&quot;">&ZeroWidthSpace;</a></h3>
<ul>
<li><strong>ABCD</strong>（大端）：网络字节序</li>
<li><strong>DCBA</strong>（小端）：Intel x86常见</li>
<li><strong>CDAB</strong>：中间字节交换</li>
<li><strong>BADC</strong>：另一种交换方式</li>
</ul>
<h3 id="_4-数据类型的复杂映射" tabindex="-1">4. 数据类型的复杂映射 <a class="header-anchor" href="#_4-数据类型的复杂映射" aria-label="Permalink to &quot;4. 数据类型的复杂映射&quot;">&ZeroWidthSpace;</a></h3>
<p>同样的原始数据，可能是：</p>
<ul>
<li><code>bool</code>、<code>byte</code>、<code>sbyte</code></li>
<li><code>short</code>、<code>ushort</code>、<code>int</code>、<code>uint</code></li>
<li><code>long</code>、<code>ulong</code>、<code>float</code>、<code>double</code></li>
<li>甚至是字符串或时间戳</li>
</ul>
<h2 id="灵感时刻-暴力美学的解决思路" tabindex="-1">灵感时刻：暴力美学的解决思路 <a class="header-anchor" href="#灵感时刻-暴力美学的解决思路" aria-label="Permalink to &quot;灵感时刻：暴力美学的解决思路&quot;">&ZeroWidthSpace;</a></h2>
<p>在又一次被数据格式折磨后，我突然想到：</p>
<blockquote>
<p>&quot;转换方式不知道？没关系，我让程序全算一遍，我只用看哪个是对的就好了！&quot;</p>
</blockquote>
<p>这就是典型的<strong>暴力美学</strong>思维：</p>
<ul>
<li>与其猜测，不如穷举</li>
<li>与其试错，不如全试</li>
<li>与其查手册，不如让计算机帮我们计算所有可能的组合</li>
</ul>
<h3 id="核心思路" tabindex="-1">核心思路 <a class="header-anchor" href="#核心思路" aria-label="Permalink to &quot;核心思路&quot;">&ZeroWidthSpace;</a></h3>
<ol>
<li><strong>输入原始数据</strong>：支持各种格式（byte[]、ushort[]、hex等）</li>
<li><strong>自动排列组合</strong>：字节序 × 编码格式 × 数据类型 = 所有可能结果</li>
<li><strong>一次性输出</strong>：让用户一眼看到哪个结果是合理的</li>
<li><strong>详细解释</strong>：告诉用户每种转换是怎么计算的</li>
</ol>
<h2 id="需求分析-这个工具应该为谁服务" tabindex="-1">需求分析：这个工具应该为谁服务？ <a class="header-anchor" href="#需求分析-这个工具应该为谁服务" aria-label="Permalink to &quot;需求分析：这个工具应该为谁服务？&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="目标用户群体" tabindex="-1">目标用户群体 <a class="header-anchor" href="#目标用户群体" aria-label="Permalink to &quot;目标用户群体&quot;">&ZeroWidthSpace;</a></h3>
<ol>
<li>
<p><strong>自动化工程师</strong></p>
<ul>
<li>需要对接各种品牌PLC</li>
<li>经常遇到数据格式不明的情况</li>
<li>希望快速验证数据解析结果</li>
</ul>
</li>
<li>
<p><strong>嵌入式开发者</strong></p>
<ul>
<li>处理Modbus、CAN、串口等协议数据</li>
<li>需要在不同字节序间转换</li>
<li>调试通信协议时需要数据格式验证</li>
</ul>
</li>
<li>
<p><strong>系统集成商</strong></p>
<ul>
<li>对接多种设备和协议</li>
<li>需要快速理解设备数据格式</li>
<li>项目时间紧，不想深入研究每种设备的文档</li>
</ul>
</li>
<li>
<p><strong>学习者和研究人员</strong></p>
<ul>
<li>学习PLC通信协议</li>
<li>了解不同数据编码方式</li>
<li>需要直观的工具来理解概念</li>
</ul>
</li>
</ol>
<h3 id="用户场景" tabindex="-1">用户场景 <a class="header-anchor" href="#用户场景" aria-label="Permalink to &quot;用户场景&quot;">&ZeroWidthSpace;</a></h3>
<p><strong>场景1：新项目对接</strong></p>
<div class="language- vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>工程师接到任务，需要对接一台新的PLC设备</span></span>
<span class="line"><span>拿到一串数据：[0x34, 0x00, 0x3F, 0x00, 0x34, 0x00]</span></span>
<span class="line"><span>不确定是什么格式，使用工具一键获得所有可能的解析结果</span></span></code></pre>
</div><p><strong>场景2：调试通信协议</strong></p>
<div class="language- vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>Modbus通信中收到异常数据，怀疑是字节序问题</span></span>
<span class="line"><span>将数据输入工具，对比各种字节序的结果</span></span>
<span class="line"><span>快速定位问题所在</span></span></code></pre>
</div><p><strong>场景3：学习和验证</strong></p>
<div class="language- vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>学习BCD编码的原理</span></span>
<span class="line"><span>输入测试数据，查看详细的转换过程</span></span>
<span class="line"><span>理解每一步计算的逻辑</span></span></code></pre>
</div><h2 id="设计理念-简单而强大" tabindex="-1">设计理念：简单而强大 <a class="header-anchor" href="#设计理念-简单而强大" aria-label="Permalink to &quot;设计理念：简单而强大&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="_1-纯前端解决方案" tabindex="-1">1. 纯前端解决方案 <a class="header-anchor" href="#_1-纯前端解决方案" aria-label="Permalink to &quot;1. 纯前端解决方案&quot;">&ZeroWidthSpace;</a></h3>
<p><strong>为什么选择纯前端？</strong></p>
<ul>
<li><strong>无依赖</strong>：打开浏览器就能用，不需要安装任何软件</li>
<li><strong>隐私安全</strong>：数据不会上传到服务器，完全本地处理</li>
<li><strong>跨平台</strong>：Windows、Mac、Linux都能用</li>
<li><strong>便携性</strong>：可以保存到本地，随时随地使用</li>
</ul>
<h3 id="_2-暴力穷举策略" tabindex="-1">2. 暴力穷举策略 <a class="header-anchor" href="#_2-暴力穷举策略" aria-label="Permalink to &quot;2. 暴力穷举策略&quot;">&ZeroWidthSpace;</a></h3>
<p><strong>核心算法思路：</strong></p>
<div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (每种字节序) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (每种编码格式) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (每种数据类型) {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            计算结果并展示</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div><p>这种&quot;笨办法&quot;看起来低效，但实际上：</p>
<ul>
<li>计算量并不大（现代浏览器完全能处理）</li>
<li>用户体验极佳（一次查看所有可能）</li>
<li>避免了用户的试错成本</li>
</ul>
<h3 id="_3-教育式交互" tabindex="-1">3. 教育式交互 <a class="header-anchor" href="#_3-教育式交互" aria-label="Permalink to &quot;3. 教育式交互&quot;">&ZeroWidthSpace;</a></h3>
<p>不仅要给出结果，还要告诉用户<strong>为什么</strong>是这个结果：</p>
<div class="language- vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>详细计算过程：</span></span>
<span class="line"><span>1. 原始数据：[13312, 16128]（ushort[]）</span></span>
<span class="line"><span>2. 转换为字节：[00, 34, 00, 3F]</span></span>
<span class="line"><span>3. 应用CDAB字节序：[34, 00, 3F, 00]</span></span>
<span class="line"><span>4. 按int32解析：0x003F0034 = 4128820</span></span>
<span class="line"><span>5. 结果：4128820</span></span></code></pre>
</div><h2 id="功能设计-覆盖所有可能的场景" tabindex="-1">功能设计：覆盖所有可能的场景 <a class="header-anchor" href="#功能设计-覆盖所有可能的场景" aria-label="Permalink to &quot;功能设计：覆盖所有可能的场景&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="核心功能模块" tabindex="-1">核心功能模块 <a class="header-anchor" href="#核心功能模块" aria-label="Permalink to &quot;核心功能模块&quot;">&ZeroWidthSpace;</a></h3>
<h4 id="_1-数据输入模块" tabindex="-1">1. 数据输入模块 <a class="header-anchor" href="#_1-数据输入模块" aria-label="Permalink to &quot;1. 数据输入模块&quot;">&ZeroWidthSpace;</a></h4>
<div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 支持多种输入格式</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> byte[]: [</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0x01</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0x00</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0x00</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0x00</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ushort[]: [</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">256</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">512</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> 十六进制</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">01</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 00</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 00</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 00</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> 十进制数组</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: [</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]</span></span></code></pre>
</div><h4 id="_2-转换引擎" tabindex="-1">2. 转换引擎 <a class="header-anchor" href="#_2-转换引擎" aria-label="Permalink to &quot;2. 转换引擎&quot;">&ZeroWidthSpace;</a></h4>
<div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 字节序处理</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> byteOrders</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'ABCD'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">bytes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> bytes,                    </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 大端</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'DCBA'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">bytes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> bytes.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">reverse</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(),          </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 小端</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'CDAB'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">bytes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> swapWords</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(bytes),         </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 西门子</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'BADC'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">bytes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> swapWordBytes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(bytes)      </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 欧姆龙</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 编码处理</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> encodings</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'DEC'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">value</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> value,                     </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 普通十进制</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'BCD'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">value</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> decodeBCD</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(value),          </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// BCD解码</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    'HEX'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">value</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> value.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">toString</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">16</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)         </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 十六进制</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">};</span></span></code></pre>
</div><h4 id="_3-结果展示模块" tabindex="-1">3. 结果展示模块 <a class="header-anchor" href="#_3-结果展示模块" aria-label="Permalink to &quot;3. 结果展示模块&quot;">&ZeroWidthSpace;</a></h4>
<ul>
<li>表格形式展示所有组合结果</li>
<li>智能高亮异常值</li>
<li>支持按类型、字节序、编码分组</li>
<li>一键复制功能</li>
</ul>
<h4 id="_4-详细解释模块" tabindex="-1">4. 详细解释模块 <a class="header-anchor" href="#_4-详细解释模块" aria-label="Permalink to &quot;4. 详细解释模块&quot;">&ZeroWidthSpace;</a></h4>
<ul>
<li>步骤化展示计算过程</li>
<li>二进制、十六进制、十进制多重显示</li>
<li>字节操作可视化</li>
</ul>
<h3 id="高级功能" tabindex="-1">高级功能 <a class="header-anchor" href="#高级功能" aria-label="Permalink to &quot;高级功能&quot;">&ZeroWidthSpace;</a></h3>
<h4 id="_1-智能验证" tabindex="-1">1. 智能验证 <a class="header-anchor" href="#_1-智能验证" aria-label="Permalink to &quot;1. 智能验证&quot;">&ZeroWidthSpace;</a></h4>
<div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// BCD格式验证</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">function</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> isValidBCD</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">value</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> value.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">toString</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">16</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">split</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">''</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">every</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">digit</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        digit </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">>=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> '0'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> &#x26;&#x26;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> digit </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> '9'</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    );</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 浮点数合理性检查</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">function</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> isReasonableFloat</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">value</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> !</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">isNaN</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(value) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;&#x26;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> isFinite</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(value) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;&#x26;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">           Math.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">abs</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(value) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1e10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div><h4 id="_2-品牌预设" tabindex="-1">2. 品牌预设 <a class="header-anchor" href="#_2-品牌预设" aria-label="Permalink to &quot;2. 品牌预设&quot;">&ZeroWidthSpace;</a></h4>
<div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> plcPresets</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    '西门子S7'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: { byteOrder: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'CDAB'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, encoding: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'DEC'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> },</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    '欧姆龙CP1E'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: { byteOrder: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'BADC'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, encoding: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'DEC'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> },</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    '三菱FX'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: { byteOrder: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'ABCD'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, encoding: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'BCD'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> },</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // ...更多品牌预设</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">};</span></span></code></pre>
</div><h2 id="技术实现-简洁而高效" tabindex="-1">技术实现：简洁而高效 <a class="header-anchor" href="#技术实现-简洁而高效" aria-label="Permalink to &quot;技术实现：简洁而高效&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="技术栈选择" tabindex="-1">技术栈选择 <a class="header-anchor" href="#技术栈选择" aria-label="Permalink to &quot;技术栈选择&quot;">&ZeroWidthSpace;</a></h3>
<p><strong>HTML5 + Vanilla JavaScript + CSS3</strong></p>
<p><strong>为什么不用框架？</strong></p>
<ul>
<li><strong>轻量级</strong>：整个工具就一个HTML文件，易于分发</li>
<li><strong>兼容性好</strong>：不依赖特定版本的框架</li>
<li><strong>学习成本低</strong>：任何前端开发者都能理解和修改</li>
<li><strong>性能优异</strong>：没有框架开销，原生JS性能最佳</li>
</ul>
<h3 id="核心算法" tabindex="-1">核心算法 <a class="header-anchor" href="#核心算法" aria-label="Permalink to &quot;核心算法&quot;">&ZeroWidthSpace;</a></h3>
<h4 id="_1-字节序转换算法" tabindex="-1">1. 字节序转换算法 <a class="header-anchor" href="#_1-字节序转换算法" aria-label="Permalink to &quot;1. 字节序转换算法&quot;">&ZeroWidthSpace;</a></h4>
<div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">function</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> reorderBytes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">bytes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">order</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> result</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Uint8Array</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(bytes.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">length</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> wordSize</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 16位为一个字</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> bytes.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">length</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> wordSize </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> word1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> bytes.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">slice</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(i, i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> wordSize);</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> word2</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> bytes.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">slice</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> wordSize, i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> wordSize </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        switch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(order) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            case</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'ABCD'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 不变</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                result.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(word1, i);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                result.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(word2, i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> wordSize);</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                break</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            case</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'CDAB'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 字交换</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                result.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(word2, i);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                result.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(word1, i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> wordSize);</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                break</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">            // ... 其他情况</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> result;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div><h4 id="_2-bcd解码算法" tabindex="-1">2. BCD解码算法 <a class="header-anchor" href="#_2-bcd解码算法" aria-label="Permalink to &quot;2. BCD解码算法&quot;">&ZeroWidthSpace;</a></h4>
<div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">function</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> decodeBCD</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">value</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> result </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> multiplier </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    while</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (value </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">></span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> digit</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> value </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0xF</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 取低4位</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (digit </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">></span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 9</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> NaN</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 非法BCD</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        result </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> digit </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> multiplier;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        multiplier </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        value </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">>>=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 右移4位</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> result;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div><h3 id="性能优化" tabindex="-1">性能优化 <a class="header-anchor" href="#性能优化" aria-label="Permalink to &quot;性能优化&quot;">&ZeroWidthSpace;</a></h3>
<h4 id="_1-web-worker支持" tabindex="-1">1. Web Worker支持 <a class="header-anchor" href="#_1-web-worker支持" aria-label="Permalink to &quot;1. Web Worker支持&quot;">&ZeroWidthSpace;</a></h4>
<p>对于大数据量的处理，使用Web Worker避免阻塞UI：</p>
<div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 主线程</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> worker</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Worker</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'converter-worker.js'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">worker.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">postMessage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">({ data: largeDataArray });</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">worker.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">onmessage</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">e</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    displayResults</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(e.data.results);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// Worker线程</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">self.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">onmessage</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> function</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">e</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> results</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> processAllCombinations</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(e.data.data);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    self.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">postMessage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">({ results });</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">};</span></span></code></pre>
</div><h4 id="_2-结果缓存" tabindex="-1">2. 结果缓存 <a class="header-anchor" href="#_2-结果缓存" aria-label="Permalink to &quot;2. 结果缓存&quot;">&ZeroWidthSpace;</a></h4>
<div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> resultCache</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Map</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">function</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> getCachedResult</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">data</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">config</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> key</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> `${</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">JSON</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">stringify</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">data</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}-${</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">JSON</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">stringify</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">(</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">config</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">)</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (resultCache.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">has</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(key)) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> resultCache.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(key);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> result</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> calculateResult</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(data, config);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    resultCache.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">set</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(key, result);</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> result;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div><h2 id="用户体验设计-让复杂变简单" tabindex="-1">用户体验设计：让复杂变简单 <a class="header-anchor" href="#用户体验设计-让复杂变简单" aria-label="Permalink to &quot;用户体验设计：让复杂变简单&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="交互流程设计" tabindex="-1">交互流程设计 <a class="header-anchor" href="#交互流程设计" aria-label="Permalink to &quot;交互流程设计&quot;">&ZeroWidthSpace;</a></h3>
<div class="language- vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>1. 用户输入原始数据</span></span>
<span class="line"><span>   ↓</span></span>
<span class="line"><span>2. 选择输入数据类型</span></span>
<span class="line"><span>   ↓</span></span>
<span class="line"><span>3. 点击"分析所有可能"</span></span>
<span class="line"><span>   ↓</span></span>
<span class="line"><span>4. 查看结果表格，找到合理的结果</span></span>
<span class="line"><span>   ↓</span></span>
<span class="line"><span>5. 点击"详细说明"了解计算过程</span></span>
<span class="line"><span>   ↓</span></span>
<span class="line"><span>6. 复制正确的结果用于实际项目</span></span></code></pre>
</div><h3 id="ui布局设计" tabindex="-1">UI布局设计 <a class="header-anchor" href="#ui布局设计" aria-label="Permalink to &quot;UI布局设计&quot;">&ZeroWidthSpace;</a></h3>
<div class="language- vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>┌─────────────────────────────────────┐</span></span>
<span class="line"><span>│              数据输入区              │</span></span>
<span class="line"><span>│  [                               ]  │</span></span>
<span class="line"><span>│  输入格式: [byte[] ▼] [分析所有可能]  │</span></span>
<span class="line"><span>└─────────────────────────────────────┘</span></span>
<span class="line"><span>┌─────────────────────────────────────┐</span></span>
<span class="line"><span>│              控制选项区              │</span></span>
<span class="line"><span>│  字节序: [全部▼]  编码: [全部▼]     │</span></span>
<span class="line"><span>│  数据类型: [全部▼]                  │</span></span>
<span class="line"><span>└─────────────────────────────────────┘</span></span>
<span class="line"><span>┌─────────────────────────────────────┐</span></span>
<span class="line"><span>│              结果展示区              │</span></span>
<span class="line"><span>│  │字节序│编码│类型│结果  │操作│     │</span></span>
<span class="line"><span>│  │ABCD │DEC │int │xxxxx │详情│复制│ │</span></span>
<span class="line"><span>│  │CDAB │DEC │int │yyyyy │详情│复制│ │</span></span>
<span class="line"><span>│  │...  │... │... │...   │... │... │ │</span></span>
<span class="line"><span>└─────────────────────────────────────┘</span></span></code></pre>
</div><h3 id="错误处理和用户引导" tabindex="-1">错误处理和用户引导 <a class="header-anchor" href="#错误处理和用户引导" aria-label="Permalink to &quot;错误处理和用户引导&quot;">&ZeroWidthSpace;</a></h3>
<div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 输入验证</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">function</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> validateInput</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">input</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">type</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (type </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">===</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'byte[]'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // 检查是否为有效的字节数组</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> input.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">every</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">val</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> val </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">>=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> &#x26;&#x26;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> val </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 255</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">else</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (type </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">===</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'ushort[]'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // 检查是否为有效的无符号短整型数组</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> input.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">every</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">val</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> val </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">>=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> &#x26;&#x26;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> val </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 65535</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 友好的错误提示</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">function</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> showUserFriendlyError</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">errorType</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> messages</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">        'invalid_byte'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'输入的字节值必须在0-255之间'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">        'invalid_ushort'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'输入的ushort值必须在0-65535之间'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">        'empty_input'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'请输入要转换的数据'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">        'invalid_format'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'数据格式不正确，请检查输入'</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    };</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    showToast</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(messages[errorType] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">||</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> '未知错误'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div><h2 id="实际应用案例" tabindex="-1">实际应用案例 <a class="header-anchor" href="#实际应用案例" aria-label="Permalink to &quot;实际应用案例&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="案例1-西门子s7-1200数据解析" tabindex="-1">案例1：西门子S7-1200数据解析 <a class="header-anchor" href="#案例1-西门子s7-1200数据解析" aria-label="Permalink to &quot;案例1：西门子S7-1200数据解析&quot;">&ZeroWidthSpace;</a></h3>
<p><strong>背景</strong>：某工厂的温度监控系统，从西门子PLC读取到数据：<code>[0x41, 0xA0, 0x00, 0x00]</code></p>
<p><strong>使用工具分析</strong>：</p>
<ol>
<li>输入数据：<code>[65, 160, 0, 0]</code>（转换为byte[]）</li>
<li>选择&quot;分析所有可能&quot;</li>
<li>查看结果表格：</li>
</ol>
<table>
<thead>
<tr>
<th>字节序</th>
<th>编码</th>
<th>类型</th>
<th>结果</th>
</tr>
</thead>
<tbody>
<tr>
<td>ABCD</td>
<td>DEC</td>
<td>float</td>
<td>20.0</td>
</tr>
<tr>
<td>CDAB</td>
<td>DEC</td>
<td>float</td>
<td>5.960464e-8</td>
</tr>
<tr>
<td>DCBA</td>
<td>DEC</td>
<td>float</td>
<td>2.350989e-38</td>
</tr>
<tr>
<td>BADC</td>
<td>DEC</td>
<td>float</td>
<td>1.401298e-45</td>
</tr>
</tbody>
</table>
<p><strong>结论</strong>：ABCD字节序的float结果（20.0）最合理，符合温度值的预期。</p>
<h3 id="案例2-欧姆龙cp1e的bcd编码" tabindex="-1">案例2：欧姆龙CP1E的BCD编码 <a class="header-anchor" href="#案例2-欧姆龙cp1e的bcd编码" aria-label="Permalink to &quot;案例2：欧姆龙CP1E的BCD编码&quot;">&ZeroWidthSpace;</a></h3>
<p><strong>背景</strong>：生产计数器数据：<code>[0x12, 0x34]</code></p>
<p><strong>分析过程</strong>：</p>
<ol>
<li>输入：<code>[18, 52]</code></li>
<li>查看BCD编码结果：</li>
</ol>
<table>
<thead>
<tr>
<th>字节序</th>
<th>编码</th>
<th>类型</th>
<th>结果</th>
</tr>
</thead>
<tbody>
<tr>
<td>ABCD</td>
<td>BCD</td>
<td>int</td>
<td>1234</td>
</tr>
<tr>
<td>ABCD</td>
<td>DEC</td>
<td>int</td>
<td>4660</td>
</tr>
</tbody>
</table>
<p><strong>结论</strong>：BCD编码的结果（1234）是正确的生产计数。</p>
<h3 id="案例3-modbus通信调试" tabindex="-1">案例3：Modbus通信调试 <a class="header-anchor" href="#案例3-modbus通信调试" aria-label="Permalink to &quot;案例3：Modbus通信调试&quot;">&ZeroWidthSpace;</a></h3>
<p><strong>背景</strong>：Modbus RTU读取的寄存器数据异常：<code>[0x00, 0x64, 0x00, 0xC8]</code></p>
<p><strong>调试过程</strong>：</p>
<ol>
<li>怀疑字节序问题，输入数据进行分析</li>
<li>对比不同字节序的结果：</li>
</ol>
<table>
<thead>
<tr>
<th>字节序</th>
<th>编码</th>
<th>类型</th>
<th>结果</th>
</tr>
</thead>
<tbody>
<tr>
<td>ABCD</td>
<td>DEC</td>
<td>int</td>
<td>6553800</td>
</tr>
<tr>
<td>DCBA</td>
<td>DEC</td>
<td>int</td>
<td>-939524096</td>
</tr>
<tr>
<td>CDAB</td>
<td>DEC</td>
<td>int</td>
<td>13107300</td>
</tr>
<tr>
<td>BADC</td>
<td>DEC</td>
<td>int</td>
<td>1677824</td>
</tr>
</tbody>
</table>
<p><strong>发现</strong>：设备使用了BADC字节序，实际值应该是<code>100</code>和<code>200</code>（两个ushort值）。</p>
<h2 id="开发过程中的思考和权衡" tabindex="-1">开发过程中的思考和权衡 <a class="header-anchor" href="#开发过程中的思考和权衡" aria-label="Permalink to &quot;开发过程中的思考和权衡&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="_1-功能范围的权衡" tabindex="-1">1. 功能范围的权衡 <a class="header-anchor" href="#_1-功能范围的权衡" aria-label="Permalink to &quot;1. 功能范围的权衡&quot;">&ZeroWidthSpace;</a></h3>
<p><strong>最初的想法</strong>：做一个包含所有可能功能的&quot;瑞士军刀&quot;
<strong>实际选择</strong>：专注于数据格式转换，不涉及通信功能</p>
<p><strong>原因</strong>：</p>
<ul>
<li>保持工具的专业性和易用性</li>
<li>避免功能臃肿导致的维护困难</li>
<li>让工具在一个领域做到极致</li>
</ul>
<h3 id="_2-性能和准确性的平衡" tabindex="-1">2. 性能和准确性的平衡 <a class="header-anchor" href="#_2-性能和准确性的平衡" aria-label="Permalink to &quot;2. 性能和准确性的平衡&quot;">&ZeroWidthSpace;</a></h3>
<p><strong>挑战</strong>：如何在穷举所有组合的同时保证性能？</p>
<p><strong>解决方案</strong>：</p>
<ul>
<li>使用高效的算法实现</li>
<li>添加数据量限制（避免内存溢出）</li>
<li>提供Web Worker选项处理大数据</li>
</ul>
<h3 id="_3-用户体验的细节考虑" tabindex="-1">3. 用户体验的细节考虑 <a class="header-anchor" href="#_3-用户体验的细节考虑" aria-label="Permalink to &quot;3. 用户体验的细节考虑&quot;">&ZeroWidthSpace;</a></h3>
<p><strong>问题</strong>：如何让新手用户快速上手？</p>
<p><strong>解决方案</strong>：</p>
<ul>
<li>提供丰富的输入示例</li>
<li>添加品牌预设选项</li>
<li>详细的计算过程说明</li>
<li>智能的结果高亮</li>
</ul>
<h2 id="未来展望-持续进化的工具" tabindex="-1">未来展望：持续进化的工具 <a class="header-anchor" href="#未来展望-持续进化的工具" aria-label="Permalink to &quot;未来展望：持续进化的工具&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="短期计划" tabindex="-1">短期计划 <a class="header-anchor" href="#短期计划" aria-label="Permalink to &quot;短期计划&quot;">&ZeroWidthSpace;</a></h3>
<ol>
<li>
<p><strong>增加更多编码格式支持</strong></p>
<ul>
<li>IEEE-754浮点详细分析</li>
<li>自定义编码格式</li>
<li>时间戳格式转换</li>
</ul>
</li>
<li>
<p><strong>改进用户体验</strong></p>
<ul>
<li>移动端适配</li>
<li>深色模式支持</li>
<li>快捷键操作</li>
</ul>
</li>
<li>
<p><strong>增强调试功能</strong></p>
<ul>
<li>数据对比功能</li>
<li>历史记录保存</li>
<li>批量数据处理</li>
</ul>
</li>
</ol>
<h3 id="长期愿景" tabindex="-1">长期愿景 <a class="header-anchor" href="#长期愿景" aria-label="Permalink to &quot;长期愿景&quot;">&ZeroWidthSpace;</a></h3>
<ol>
<li>
<p><strong>协议扩展</strong></p>
<ul>
<li>Modbus CRC校验</li>
<li>CAN总线数据解析</li>
<li>Profinet协议支持</li>
</ul>
</li>
<li>
<p><strong>智能化功能</strong></p>
<ul>
<li>基于机器学习的格式推测</li>
<li>自动识别设备类型</li>
<li>智能错误诊断</li>
</ul>
</li>
<li>
<p><strong>生态建设</strong></p>
<ul>
<li>插件系统</li>
<li>社区贡献的预设</li>
<li>API接口开放</li>
</ul>
</li>
</ol>
<h2 id="结语-开源的力量" tabindex="-1">结语：开源的力量 <a class="header-anchor" href="#结语-开源的力量" aria-label="Permalink to &quot;结语：开源的力量&quot;">&ZeroWidthSpace;</a></h2>
<p>这个工具从个人痛点出发，希望能解决更多工程师的实际问题。选择开源，是因为相信：</p>
<ol>
<li><strong>集体智慧</strong>：更多人的参与能让工具更完善</li>
<li><strong>知识共享</strong>：让更多人受益于这个解决方案</li>
<li><strong>持续进化</strong>：开源项目有更强的生命力</li>
</ol>
<p>如果你也曾被PLC数据格式折磨过，如果你觉得这个工具有价值，欢迎：</p>
<ul>
<li>⭐ 给项目点个Star</li>
<li>🐛 提交Bug报告和功能建议</li>
<li>🔧 参与代码贡献</li>
<li>📢 推荐给有需要的朋友</li>
</ul>
<p>让我们一起，让PLC数据转换不再是工程师的噩梦，而是可以被优雅解决的技术问题。</p>
<hr>
<p><strong>项目地址</strong>：[<a href="https://github.com/duyl328/PLC-Data-Lab" target="_blank" rel="noreferrer">https://github.com/duyl328/PLC-Data-Lab</a>]<br>
<strong>在线体验</strong>：[<a href="https://duyl328.github.io/PLC-Data-Lab/" target="_blank" rel="noreferrer">https://duyl328.github.io/PLC-Data-Lab/</a>]</p>
<p><em>愿这个小工具，能为每一个与数据格斗的工程师，节省一点时间，减少一点烦恼。</em></p>
]]></content>
        <author>
            <name>duyl328</name>
            <uri>https://seyl.me/about</uri>
        </author>
        <category label="工具"/>
        <category label="PLC"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[如何成为黑客]]></title>
        <id>https://seyl.me/posts/2025/04/hacker-howto</id>
        <link href="https://seyl.me/posts/2025/04/hacker-howto"/>
        <updated>2025-04-11T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[<h1 id="frontmatter-title-转载" tabindex="-1">{{ $frontmatter.title }}(转载) <a class="header-anchor" href="#frontmatter-title-转载" aria-label="Permalink to &quot;{{ $frontmatter.title }}(转载)&quot;">&ZeroWidthSpace;</a></h1>
<div class="warning custom-block github-alert"><p class="custom-block-title">版权声明</p>
<p>How To Become A Hacker</p>
<p>Eric Steven Raymond, Thyrsus Enterprises, &lt; <a href="mailto:esr@thyrsus.com" target="_blank" rel="noreferrer">esr@thyrsus.com</a> &gt;</p>
<p>Copyright © 2001 Eric S. Raymond</p>
<p>翻译：柯非, &lt; <a href="mailto:zer4tul@gmail.com" target="_blank" rel="noreferrer">zer4tul@gmail.com</a> &gt;</p>
</div>
<blockquote>
<p>✒️ 文章摘要</p>
</blockquote>
<!-- DESC SEP -->
<p>在这篇文章中，笔者从《How To Become A Hacker》一文出发，系统地梳理了黑客文化的核心精神、态度与必备技能。我深入探讨了“黑客”与“破坏者（Cracker）”的根本区别，强调黑客并非违法分子，而是一群追求自由、分享与优雅解决问题的人。</p>
<p>为了成为真正的黑客，笔者总结了几条明确的路径：学习编程语言（如Python、C、LISP等），掌握操作系统（尤其是Linux和Unix）、了解互联网的底层原理、熟练使用英语，以及参与自由软件项目。过程中还特别强调了要具备“懒惰、急躁、傲慢”这三种略带反讽却本质积极的黑客美德。</p>
<p>这不仅是一篇技能指南，更是一种价值观的宣言。正如文中所说：“黑客精神，是在智识与创造力之上，对世界不断重构的冲动。”成为黑客，从模仿与学习开始，更重要的是不断探索、思考与分享。</p>
<!-- DESC SEP -->
<h2 id="什么是黑客" tabindex="-1">什么是黑客 <a class="header-anchor" href="#什么是黑客" aria-label="Permalink to &quot;什么是黑客&quot;">&ZeroWidthSpace;</a></h2>
<p><a href="#">新黑客词典（Jargon File）</a>中有数个“黑客”的定义，主要形容&quot;技术专才&quot;或&quot;有志解决问题及超越极限之人&quot;。要成为黑客，有两个要点。</p>
<p>这可以追溯到几十年前第一台分时小型电脑诞生, ARPAnet 实验也刚展开的年代，那时有一个由程序设计专家和网络名人所组成的, 具有分享特点的文化社群。 这种文化的成员创造了 “hacker” 这个词。他们建立了互联网，他们发明了现在使用的Unix操作系统。他们管理Usenet讨论组。他们令WWW运作。因此，若你有上述的特性及参与同类的社区，亦有对以上种种作出贡献，同时社区的人知你是谁又称你为“hacker”，你便是黑客。</p>
<p>然而，黑客的理念并非只局限于软件社区。有很多人将黑客的态度应用于其他事物，如电子或音乐上——实际上，黑客的理念存在于任何科学及文学。由于了解黑客的理念及精神，软件社区的黑客亦会称后者为黑客。有些人亦认为黑客的理念是独立于黑客所从事的媒体。然而，我们将在这篇文章专注讨论软件黑客的技巧，态度及传统。</p>
<p>另外，有一群人亦称自已为“黑客”，他们（多数是年青人）用电脑侵入其他电脑的系统作出破坏。黑客们称这群人为“Cracker（破坏者）”，亦不认同他们为黑客。多数黑客会认为Cracker是懒惰, 不负责任，不杰出的人。有能力侵入安全系统并不能使你成为黑客，正如可以用铁丝来偷车并不能使你成为汽车工程师一样。不幸的是很多作家及报道均称这群人为“黑客”。这一直使黑客们非常恼火。</p>
<p>黑客与Cracker的主要区别在于，前者搞建设，后者搞破坏。</p>
<p>如果你想成为一个黑客，请继续读下去。如果你只想做一个Cracker，请到 alt.2600 讨论组，并做好当你发现自己不如想象中聪颖的时候进5到10次监狱的准备。关于Cracker我就说这么多。</p>
<h2 id="黑客精神" tabindex="-1">黑客精神 <a class="header-anchor" href="#黑客精神" aria-label="Permalink to &quot;黑客精神&quot;">&ZeroWidthSpace;</a></h2>
<p>黑客们解决问题，建设事物，他们崇尚自由和无私的双向帮助。要被他人承认是一名黑客，你必须表现得你具备了这样的态度。而要表现得你具备了这种态度，你必须彻彻底底的坚持它。</p>
<p>如果你认为培养黑客的态度只是一条在这个文化圈中得到认同的路子，那就错了。成为具备这种素质的人对 <strong>你</strong> ¸非常重要 —— 使你保持学习和成为黑客的自发性。正如所有创造性艺术一样，成为大师的最有效途径就是效仿大师的精神——不仅从理念上，还要从态度上效仿。</p>
<p>或许下面的这首现代禅诗很好的阐述了这个意思：</p>
<blockquote>
<p>To follow the path:<br>
沿着这样一条道路：<br>
look to the master,<br>
关注大师，<br>
follow the master,  z
跟随大师，<br>
walk with the master,<br>
与大师同行，<br>
see through the master,<br>
洞察大师，<br>
become the master.<br>
成为大师。</p>
</blockquote>
<p>如果你想成为一名黑客，反复阅读以下内容直到你相信它们：</p>
<h3 id="世上仍有大量迷人的事情等待解决" tabindex="-1">世上仍有大量迷人的事情等待解决 <a class="header-anchor" href="#世上仍有大量迷人的事情等待解决" aria-label="Permalink to &quot;世上仍有大量迷人的事情等待解决&quot;">&ZeroWidthSpace;</a></h3>
<p>作为一名黑客可以享受很多乐趣，同时需要付出相当多的努力。努力需要动力。成功的运动员从锻炼身体、超越身体极限中获得精神愉悦。类似的，作为一名黑客，你可以从解决问题、磨练技术和锻炼智力中获得乐趣。</p>
<p>如果你天生不是这样的人，那你需要设法变成这样的人以使你能够成为一名黑客。否则你将会发现你的精力会被诸如性、金钱、社会上的虚名之类让人分心的东西所消磨掉。</p>
<p>（你还需要对自己的学习能力树立信心——相信尽管你对某一问题了解得不多，只要你能解决其中一部分，并从中学习，你可以解决其他的部分——直到解决它。）</p>
<h3 id="同样的问题不应被重复处理两次" tabindex="-1">同样的问题不应被重复处理两次 <a class="header-anchor" href="#同样的问题不应被重复处理两次" aria-label="Permalink to &quot;同样的问题不应被重复处理两次&quot;">&ZeroWidthSpace;</a></h3>
<p>创造性的智慧是非常有价值且稀缺的资源。它们不应当被浪费在重复发明轮子上，世上仍有大量迷人的新问题等着解决。</p>
<p>作为一名黑客，你应该坚信其他黑客的时间非常宝贵——所以你有义务共享信息，解决问题之后公布方案，这样其他人可以去解决新的问题，而不是忙于应付旧问题。</p>
<p>注意，“同一个问题不应该被重复处理两次”并不是说你必须认为所有已有方案都是最优的，或每个问题只有唯一的解决方案。通常我们从一个问题的最初解决方案中能够学习到很多东西。这很好，并且对于我们思考如何能做得更好来说，这通常是必要的。我们反对的是人为的技术、法律上的，或者机构性的设置障碍（例如闭源软件），使得一个好的方案不能被重复使用，逼得人们重造轮子。</p>
<p>（你不必认为你必须将 <strong>所有</strong> 你的创造发明都公布出去，虽然这样做的黑客将会赢得大家极度尊重。适当卖一些钱来换取足够的食物、租金和电脑并不违反黑客的价值观。用你的技能来养家糊口甚至致富都可以，只要你在做这些的时候别忘记你是一名黑客。）</p>
<h3 id="拒绝重复和沉闷的事情" tabindex="-1">拒绝重复和沉闷的事情 <a class="header-anchor" href="#拒绝重复和沉闷的事情" aria-label="Permalink to &quot;拒绝重复和沉闷的事情&quot;">&ZeroWidthSpace;</a></h3>
<p>黑客（以及富有创造力的所有人）不应当被愚蠢的重复性劳动所困扰，因为这意味着他们并没有在做只有他们才能做的事情——解决新问题。这样的浪费会伤害所有人。因此，无聊和乏味的工作不仅仅是令人不爽，而是罪恶。</p>
<p>作为一个黑客，你应该坚信这一点并尽可能的将枯燥的工作自动化，这不仅仅是为了你自己，也为了其他人（尤其是其他黑客）。</p>
<p>（这里有一个例外。黑客有时会做一些看起来重复或枯燥的事情以进行脑力休息，或以此来锻炼一种技能，或以此获得某种除此以外无法获取的经验。但这是有选择的——有脑子的人不该被强迫做枯燥的事。）</p>
<h3 id="自由万岁" tabindex="-1">自由万岁 <a class="header-anchor" href="#自由万岁" aria-label="Permalink to &quot;自由万岁&quot;">&ZeroWidthSpace;</a></h3>
<p>黑客是天生的反独裁主义者。 任何能向你发号施令的人能够迫使你停止解决令你着迷的问题。 同时，按照独裁者的一般思路，他通常会给出一些极端愚昧的理由。因此，不论何处，任何独裁主义的作法，只要它压迫你和其他黑客，你就要和它斗到底。</p>
<p>（这并非向所有权威挑战。儿童需要监护，罪犯要被看管起来。如果服从命令得到某种东西比起用其他方式得到它更节约时间，黑客可以同意 接受某种形式的权威。但这是一个有限度的，有意的交易；那种权威想要的个人服从不是你应该同意给予的。）</p>
<p>权威喜欢审查和保密。他们不信任自愿的合作和信息共享——他们只喜欢由他们控制的所谓“合作”。因此，作为一个黑客，你得对审查、保密，以及使用武力或欺骗去压迫有行为能力的人们的做法有一种本能的敌意。 同时你要有为此信念斗争的意愿。</p>
<h3 id="精神不能代替能力" tabindex="-1">精神不能代替能力 <a class="header-anchor" href="#精神不能代替能力" aria-label="Permalink to &quot;精神不能代替能力&quot;">&ZeroWidthSpace;</a></h3>
<p>作为一个黑客，你必须培养起这些精神。但是仅仅有精神并不能使你成为黑客，也不能使你成为运动健将或摇滚明星。成为一名黑客还需要智力，实践，奉献精神和辛勤工作。</p>
<p>因此，你需要学会有怀疑态度和尊重任何能力。黑客不会为装模作样的人浪费时间，但他们尊重能力——尤其是从事黑客工作的能力，不过任何能力都是好的。很少人能具备的高要求能力尤其好，其中涉及脑力，技巧和专注方面的能力最好。</p>
<p>尊重能力，你就会享受到提高自己的能力所带来的乐趣——辛苦的工作和奉献将不再是苦差而是一种高度娱乐。想要成为一名黑客，这一点尤其重要。</p>
<h2 id="基本黑客技能" tabindex="-1">基本黑客技能 <a class="header-anchor" href="#基本黑客技能" aria-label="Permalink to &quot;基本黑客技能&quot;">&ZeroWidthSpace;</a></h2>
<p>黑客的态度很重要，但技能更重要。态度不能替代能力，在被别的黑客称你为黑客之前，你有一些基本技能需要掌握。</p>
<p>这些基本技能随着时间的推移和技术的革新也缓慢的变化着。例如以前的内容中包括了使用机器语言编程，最近包含进了HTML。总的来说当前包括以下内容：</p>
<h3 id="学习编程" tabindex="-1">学习编程 <a class="header-anchor" href="#学习编程" aria-label="Permalink to &quot;学习编程&quot;">&ZeroWidthSpace;</a></h3>
<p>理所当然，这是最基本的黑客技能。如果你一门计算机语言都不懂，我建议你从Python学起。它设计良好，文档详尽，并且对新人十分友好。尽管它是一门很好的入门语言，但它不只是玩具水平。它非常强大灵活，并且适用于大型项目。我写过一篇详细的<a href="http://www.linuxjournal.com/article/3882" target="_blank" rel="noreferrer">对Python的评价</a>。在<a href="http://docs.python.org/tutorial/index.html" target="_blank" rel="noreferrer">Python的网站</a>可以找到很好的<a href="http://docs.python.org/tutorial/index.html" target="_blank" rel="noreferrer">教程</a>。在<a href="http://cscircles.cemc.uwaterloo.ca/" target="_blank" rel="noreferrer">Computer Science Circles</a>也有一篇不错的第三方教程。</p>
<p>我早前曾经建议使用Java作为入门语言，但<a href="http://www.crosstalkonline.org/storage/issue-archives/2008/200801/200801-Dewar.pdf" target="_blank" rel="noreferrer">这篇评价</a>改变了我的看法（请在文档中搜索“The Pitfalls of Java as a First Programming Language”）。如同文中尖锐指出的一样，一个黑客不能“像五金店中的管道工一样处理问题”。你需要知道所有的组件事实上都 <strong>干了什么</strong>。现在，我认为最好先学C和Lisp，然后再学Java。</p>
<p>比Java更好的选择是学习Go。这种相对较新的语言很容易从Python上手，而且学习它可以使你在可能的下一步（学习C语言）中得到很大的帮助。此外，未来几年的一个未知数是Go将在多大程度上取代C语言成为真正的系统编程语言。在未来，这种情况可能会在C语言的大部分传统领域内发生。</p>
<p>另外有一点需要注意。如果一门语言帮你做了太多工作，它会同时是一个好的生产工具和一个不好的初学对象。不仅语言有这个问题，Web框架比如RubyOnRails，CakePHP，Django也很容易让你流于表面，面对困难问题的时候束手无策，甚至无法对一个简单问题进行追查并给出解决方案。</p>
<p>如果你需要做一些重要的编程工作，你需要学习C语言，它是Unix的核心语言。C++跟C关系密切。如果你了解其中一种，学习另外一种应该不难。但是这两种语言都不适合作为入门学习。此外，如果你越避免用C编程，你的工作效率会越高。</p>
<p>C的执行效率非常高，并且非常节省机器资源。不幸的是C的高效是通过让你手动进行许多底层资源（例如内存）管理来获得的。底层代码复杂并且容易出bug，你需要花费很多时间来进行调试。鉴于当今的机器性能如此之高，这样的做法通常很不划算——通常更好的做法是使用一种稍微慢一些，不那么高效，但是能够 <strong>大幅</strong> 节省你的时间的语言。那便是Python。</p>
<p>其他对黑客而言比较重要的语言包括Perl和LISP。Perl很实用，它广泛应用于动态网页和系统管理方面，因此即使你从不写Perl代码，至少也得能看懂。许多人使用Perl的理由和我建议你使用Python的理由一样，都是为了避免用C完成那些执行效率需求不那么高的工作。你需要能够看懂他们的代码。</p>
<p>LISP之所以值得一学是基于另外的理由——当你最终掌握了它的时候，你将会获得巨大的启迪。它将使你在今后成为一个更好的程序员，即使你实际上很少使用LISP本身。（你可以通过为Emacs文本编辑器或者GIMP的Script-Fu编写插件或修改现有插件来很容易的学习LISP。）</p>
<p>当然，你最好五种语言都会（Python，C/C++，Java，Perl和LISP）。除了是重要的黑客语言之外，它们也代表了截然不同的编程思路和方法，每一种都能让你受益匪浅。</p>
<p>但是单纯的堆砌语言是不可能成为一个黑客，甚至程序员的。你需要学会如何独立于任何具体的语言之外来思考编程问题。作为一名真正的黑客，你需要通过手册和你已有的知识掌握到在几天之内学会一门语言的要点。这意味着你需要学习许许多多不同的语言。</p>
<p>这里我无法给你完完全全的指导教会你如何编程——这是个复杂的技能。但我可以告诉你，书本和课程也不能做到（最好的黑客中，有许多，也许 <strong>几乎</strong> 都是自学成才的）。 你可以从书本上学到语言的特点——这只是皮毛，但要使书面知识成为自身技能只能通过实践和虚心向他人学习。因此要做到</p>
<pre><code>（1）**读** 代码
（2）**写** 代码。
</code></pre>
<p>Peter Norvig，Google最顶级的黑客之一，也是世界上最受欢迎的AI教材（译注：指“人工智能：一种现代方法”和“人工智能程序设计范例：通用Lisp语言的案例研究”等）的共同作者。他写了一篇名为<a href="http://www.norvig.com/21-days.html" target="_blank" rel="noreferrer">Teach Yourself Programming in Ten Years</a>的短文。他在文中提到的“编程成功的诀窍（recipe for programming success）”特别值得留意。</p>
<p>学习编程就像学习用优美的自然语言书写一样。最好的办法就是阅读大师的名著，试着自己写点东西，再读一些，再写一点，再读一些，再写一点……如此往复，直到你的作品达到如你在范文中所见的简洁和健壮。</p>
<p>我必须再提一下<a href="#">How To Learn Hacking</a>，这是一些简单的说明，但是学起来并不容易。</p>
<p>以前很难找到适合阅读的好代码，因为几乎没有大型程序的代码能够供新人阅读和练手。这种情况已经发生戏剧性的变化。开源软件，编程工具和操作系统（都是由黑客创造的）现在随处可见。这刚好带我们到下一个话题……</p>
<h3 id="获取一个开源的unix并学习运行和使用它" tabindex="-1">获取一个开源的Unix并学习运行和使用它 <a class="header-anchor" href="#获取一个开源的unix并学习运行和使用它" aria-label="Permalink to &quot;获取一个开源的Unix并学习运行和使用它&quot;">&ZeroWidthSpace;</a></h3>
<p>我假定你拥有或者能使用一台个人电脑（现在的孩子真幸福。黑客文化建立之初电脑贵得要死，没人买得起）。新手们向黑客技能迈出的最重要一步就是获取一份Linux或BSD-Unix的拷贝，将其安装在个人电脑上，并运行它。</p>
<p>没错，世上除了Unix还有其他操作系统。但它们都是以二进制形式发布的——你读不到源码，你也不能修改代码。在类似Microsoft Windows那样的闭源操作系统上学习黑客技术就像戴着脚镣学跳舞。</p>
<p>在Mac OS X上倒是可以，不过它只有一部分是开源的——你可能会撞墙，也必须很小心的避免养成依赖Apple专有代码的坏习惯。如果你专注于底层的Unix，你可以学到一些有用的东西。</p>
<p>Unix是互联网上的操作系统。虽然你不懂Unix仍然可以学会使用互联网，但若你不懂Unix，你将不能在互联网上从事黑客活动。因此，现今的黑客文化是严重以Unix为中心的。（曾经不是这样，并且有一些老派的黑客对此仍然感到不太高兴。但是现今Unix和互联网的羁绊如此之强，连Microsoft也无法撼动分毫。）</p>
<p>所以，请安装一套Unix - 我个人喜爱Linux但还有其他种类的（并且，你 <strong>可以</strong> 在同一台电脑上运行Linux和Windows）。学习它，使用它，调教它。用它在互联网上冲浪。阅读它的代码，修改它的代码。你将获得比Windows操作系统上更好的编程工具（包括C，LISP，Python和Perl）。你会觉得其乐无穷，学到比你想像更多更好的知识。</p>
<p>想要获取更多和学习Unix相关的信息，请参考<a href="http://catb.org/~esr/faqs/loginataka.html" target="_blank" rel="noreferrer">Loginataka</a>。你或许还想看看<a href="http://catb.org/~esr/writings/taoup/" target="_blank" rel="noreferrer">Unix编程艺术</a>（译注：这里给出的是原文链接。国内有翻译版出售）。</p>
<p>我认为博客<a href="https://letsgolarval.wordpress.com/" target="_blank" rel="noreferrer">Let's Go Larval!</a>对于处在学习Linux阶段中的用户是非常易懂和有用的。 这篇文章<a href="https://letsgolarval.wordpress.com/2015/06/23/how-i-learned-linux" target="_blank" rel="noreferrer">How I Learned Linux</a> 就是一个很好的起点。</p>
<p>想开始Linux之旅，请参考<a href="http://www.linux.org/" target="_blank" rel="noreferrer">Linux Online!</a>。你可以从那里下载Linux或者（更好的主意是）找到一个当地的Linux用户群为你的安装过程提供帮助。</p>
<p>在本文最初的10年间，我认为从一个初学者的角度来说，所有Linux发行版都差不多。不过在2006~2007年间，一个事实上最好的选择出现了：<a href="http://www.ubuntu.com/" target="_blank" rel="noreferrer">Ubuntu</a>。其他发行版各有所长，而Ubuntu对初学者最友好。注意，相比Ubuntu默认那个丑陋的几乎不可用的“Unity”桌面，Xubuntu和Kubuntu更好用一点。</p>
<p>你可以在<a href="http://www.bsd.org/" target="_blank" rel="noreferrer">www.bsd.org</a>找到BSD相关的帮助和资源。</p>
<p>一个试水的好办法是试试被Linux爱好者称为“Live CD”的东西，那是一个完全在光盘或者U盘上运行，而不修改你硬盘的发行版。它运行起来比较慢，因为光盘很慢，但是这是一个在做出任何不可挽救的改变前看看可行性的办法。</p>
<p>我写过一篇关于<a href="http://en.tldp.org/HOWTO/Unix-and-Internet-Fundamentals-HOWTO/index.html" target="_blank" rel="noreferrer">Unix和互联网基础</a>的入门文章。</p>
<p>我曾经不建议新手独自安装Linux或者BSD。现在它们的安装程序已经做得足够好，你作为新人也完全搞得定。尽管如此，我仍然建议和你当地的Linux用户群取得联系并寻求帮助。这没坏处，并且可以让整个过程更顺利。</p>
<h3 id="学习使用万维网-world-wide-web-www-和html-超文本标记语言" tabindex="-1">学习使用万维网（World Wide Web，WWW）和HTML（超文本标记语言） <a class="header-anchor" href="#学习使用万维网-world-wide-web-www-和html-超文本标记语言" aria-label="Permalink to &quot;学习使用万维网（World Wide Web，WWW）和HTML（超文本标记语言）&quot;">&ZeroWidthSpace;</a></h3>
<p>大多数的黑客造物在你所不知的地方发挥着作用，帮助工厂、办公室和学校运转，这看上去跟普通人没太大关系。Web是一个大大的例外，即便 <strong>政客</strong> 也承认这个巨大耀眼的黑客玩具正在改变着世界。单就这一个原因（当然还有其他理由）你就需要学习掌握Web。</p>
<p>这并不仅仅意味着如何使用浏览器（谁都会），而是要学会如何写HTML，Web的标记语言。如果你不会编程，写HTML会教你一些有助于学习的思考习惯。因此，先完成一个主页。尝试坚持使用XHTML，一种比标准HTML更清晰的语言。（Web上有很多很好的初学者指南，例如<a href="http://htmldog.com/" target="_blank" rel="noreferrer">这个</a>）。</p>
<p>但仅仅拥有一个主页不能使你成为一名黑客。Web里充满了各种网页。大多数是毫无意义的，零信息量的垃圾——界面时髦，能夺人眼球的垃圾还是垃圾（更多信息访问<a href="http://catb.org/~esr/html-hell.html" target="_blank" rel="noreferrer">The HTML Hell Page</a>）。</p>
<p>所以，你的页面必须有内容——得是有趣并且/或者对其他黑客来说有用的内容。这是我们下一个议题要说的……</p>
<h3 id="学习实用英语" tabindex="-1">学习实用英语 <a class="header-anchor" href="#学习实用英语" aria-label="Permalink to &quot;学习实用英语&quot;">&ZeroWidthSpace;</a></h3>
<p>作为一个美国人和一个以英语为母语的人，我以前很不情愿提到这点，免得成为一种文化上的帝国主义。但相当多以其他语言为母语的人一直劝我指出这一点，那就是英语是黑客文化和Internet的工作语言，你需要懂得以便在黑客社区顺利工作。</p>
<p>大概1991年的时候我了解到许多黑客在技术讨论中使用英语，即使在他们的母语都相同，英语对他们而言只是第二语言的时候也常如此。据我所知，当前英语有着比其他语言丰富得多的技术词汇，因此是一个对于工作来说相当好的工具。基于同样的理由，英文技术书籍的翻译（如果有的话）通常都不能令读者满意。</p>
<p>芬兰人Linus Torvalds用英语注释他的代码（很明显这不是凑巧）。他流利的英语成为他能够管理全球范围的Linux开发人员社区的重要因素。这是一个值得学习的例子。</p>
<p>即使作为一个以英语为母语的人也不代表你就具备了成为黑客所需的语言技能。一般而言，如果你写得像个半文盲似的，文中充斥着各种语法、拼写错误，多半得不到理睬。虽然不严谨的文笔并不总是意味着不严谨的思维，但我们发现这两者之间的关联还是挺紧密的。而我们不需要这种思维不严谨的人。如果你现在还没有具备这样的书写能力，赶紧培养。</p>
<h2 id="在黑客社区中立足" tabindex="-1">在黑客社区中立足 <a class="header-anchor" href="#在黑客社区中立足" aria-label="Permalink to &quot;在黑客社区中立足&quot;">&ZeroWidthSpace;</a></h2>
<p>像大部分非盈利社区一样，黑客社区靠声誉运转。你设法解决有趣的问题，但问题是否有趣及解决方法是否有效，需要由那些和你具有同样甚至更高技术水平的人去评判。</p>
<p>因此，要玩黑客这个游戏，你需要以其他黑客对你技能的评判作为对自己的评价（所以我说，在其他黑客称你为黑客之前，你不是一个真正的黑客）。这个事实常被人误解（从1990年代后有所好转，但还是很严重），人们认为黑客都是不在乎别人的评价，孤僻的人。这实际上是一个黑客文化的禁忌。</p>
<p>特别地，黑客被人类学家们称为 <strong>奉献社区</strong>。在这里你不是凭借你对别人的统治来建立地位和名望，也不是靠美貌，或拥有其他人想要的东西，而是靠你的奉献。尤其是奉献你的时间，你的创造力和你的技术成果。</p>
<p>要想获得黑客的尊重，你基本上有5件事情可干：</p>
<h3 id="编写开源软件" tabindex="-1">编写开源软件 <a class="header-anchor" href="#编写开源软件" aria-label="Permalink to &quot;编写开源软件&quot;">&ZeroWidthSpace;</a></h3>
<p>首先（也是最传统和最重要的）是写一些其他黑客觉得有趣或有用的程序，并且开放源代码。</p>
<p>（我们曾经把这些程序称为“自由软件（free software）”，但是太多人不能确定这里的“free”是什么意思。现在我们通常使用“<a href="http://www.opensource.org/" target="_blank" rel="noreferrer">开源</a>”软件这个词。</p>
<p>黑客间最受尊敬的圣人是那些编写了大型的，功能强劲且满足了广泛需求的开源软件供他人使用的人。</p>
<p>但是这里有段有趣的历史。虽然黑客一直敬重开源软件开发者，并且他们是我们社区的核心，但是直到1990年代中期，绝大部分黑客绝大多数时间是在闭源软件上工作的。在我1996年写本文的第一版的时候仍然如此。到1997年之后开源软件逐渐成为主流并改变了这一点。现在，“黑客社区”和“开源软件开发者”本质上是对同一文化和同一人群的两种表述——但值得记住的是，曾经不是如此。（想了解更多，请看“<a href="https://github.com/zer4tul/hacker-howto?tab=readme-ov-file#%E5%8E%86%E5%8F%B2%E8%AE%B0%E5%BD%95%EF%BC%9A%E9%BB%91%E5%AE%A2%E6%B4%BB%E5%8A%A8%EF%BC%8C%E5%BC%80%E6%BA%90%EF%BC%8C%E5%92%8C%E8%87%AA%E7%94%B1%E8%BD%AF%E4%BB%B6" target="_blank" rel="noreferrer">历史记录：黑客活动，开源，和自由软件</a>”。）</p>
<h3 id="帮助测试和调试开源软件" tabindex="-1">帮助测试和调试开源软件 <a class="header-anchor" href="#帮助测试和调试开源软件" aria-label="Permalink to &quot;帮助测试和调试开源软件&quot;">&ZeroWidthSpace;</a></h3>
<p>黑客也尊敬那些为开源软件进行测试和除错的人。在这个并非完美的世界上，我们不可避免地要花大多数的开发时间在调试阶段。 这就是为什么许多开源软件作者都会高度评价那些好的beta测试员 （知道如何清楚描述出错症状，很好地定位错误，能忍受快速发布中的bug，并且愿意使用一些简单的诊断工具），认为他们像红宝石一样珍贵。一个好的测试员可以使如恶梦的测试及除错工作变为一件值得经历的小烦恼。</p>
<p>如果你是个新手，试着找一个你感兴趣的正在开发的程序，尝试做一个好的beta测试员。 你会自然地从帮着测试，进步到帮着抓bug，到最后帮着改程序。你会从中学到很多，并且与未来会帮到你的人结下友谊。</p>
<h3 id="发布有用的信息" tabindex="-1">发布有用的信息 <a class="header-anchor" href="#发布有用的信息" aria-label="Permalink to &quot;发布有用的信息&quot;">&ZeroWidthSpace;</a></h3>
<p>另一个好事是收集整理有用有趣的信息做成网页或文档如FAQ（常见问题）列表，且让他们容易获得。</p>
<p>技术性FAQ的维护者往往如同开源软件作者一样很受人尊重。</p>
<h3 id="帮助维护基础设施运转" tabindex="-1">帮助维护基础设施运转 <a class="header-anchor" href="#帮助维护基础设施运转" aria-label="Permalink to &quot;帮助维护基础设施运转&quot;">&ZeroWidthSpace;</a></h3>
<p>黑客社区（也包括互联网发展）是靠自愿者组成的。有大量重要但平淡的事情需要处理——管理邮件列表，新闻组，维护大型软件归档库，开发RFC和其他技术标准等。</p>
<p>做以上事情的人会得到很多人的尊敬，因为大家都知道这些事情需要大量的时间并且不如编写软件那么有趣。这类工作需要使命感。</p>
<h3 id="为黑客社区服务" tabindex="-1">为黑客社区服务 <a class="header-anchor" href="#为黑客社区服务" aria-label="Permalink to &quot;为黑客社区服务&quot;">&ZeroWidthSpace;</a></h3>
<p>最后，你还可以为黑客社区做服务和宣扬（比如写一篇“如何成为黑客”的文章 😃）。通常你不会做这些工作，直到你已经做了以上四种中的一样，并且取得了相当的知名度。</p>
<p>黑客社区没有既定的领导者，但是有被人们尊重的英雄，长老级人物，史学家和发言人。当你在这个圈里足够久，你可能会成为他们中的一员。但请谨记，黑客对于自我夸耀的长老并不认同，因此不要尝试大举追求这种名誉。与其奋力追求，不如先摆正自己的位置，等它自己到你手中，那时需要做到谦虚和优雅。</p>
<h2 id="黑客与书呆子-nerd-的关系" tabindex="-1">黑客与书呆子（Nerd）的关系 <a class="header-anchor" href="#黑客与书呆子-nerd-的关系" aria-label="Permalink to &quot;黑客与书呆子（Nerd）的关系&quot;">&ZeroWidthSpace;</a></h2>
<p>与流行的传说不同，黑客并不是书呆子。但这确实对你成为黑客有帮助，并且很多黑客确实是书呆子。做一个深居简出的人有助于使你更能集中精力做一些重要的事，例如思考和从事黑客活动。</p>
<p>因此，许多黑客甚至以“极客（geek）”（译注：这个词原本在美国俚语中指“反常的人”）为名——这是一种宣布他们独立于普通社会的方式（此外，黑客也通常沉迷于其他一些事情例如科幻和战略游戏）。“书呆子”这个词通常在1990年代也被如此使用，那时候“书呆子”这个词略含贬义，而“极客”贬义更重。2000年以后这两个词的关系发生了转变，至少在美国流行文化上是如此，现在甚至在非技术专家中也出现了以标榜为极客为豪的情况。</p>
<p>如果你能集中足够的精力做好黑客工作同时还能有正常的生活，这很好。现在做到这一点比我在1970年代还是新手的时候要容易的多；如今主流文化对技术怪人要友善的多。甚至有越来越多的人意识到黑客通常是很好的恋人和配偶侯选。</p>
<p>如果你因为生活上的不如意而成为黑客，那也不错——至少你不用分神了。或许今后你能有一个不错的生活。</p>
<h2 id="风格" tabindex="-1">风格 <a class="header-anchor" href="#风格" aria-label="Permalink to &quot;风格&quot;">&ZeroWidthSpace;</a></h2>
<p>重申一下，作为一名黑客，你必须进入黑客式思维模式。当你不在电脑边的时候你仍然有很多有益的事情可做。它们不能替代真正的黑客活动（没有什么可以），但是很多黑客都这么干，并且感到它们与黑客精神存在某些根本的联系。</p>
<ul>
<li>学会流畅的使用母语写作。虽然认为程序员写不好文章的误解仍然很普遍，但是有数量令人惊讶的黑客（包括我所知造诣最高的那些）都是不错的写手。</li>
<li>阅读科幻小说。参加科幻聚会（一个接触黑客和可能成为黑客的人的好方法）。</li>
<li>加入黑客空间（hackerspace）并做一些东西出来（另外一个接触黑客和可能成为黑客的人的好方法）。</li>
<li>习武。武术的精神修炼与黑客之道惊人的相似。黑客中比较常见的当然是亚洲的空手格斗技巧，例如跆拳道、空手道及其变种、中国功夫、合气道、柔术（译注：这里指的是日本传统武术，而不是柔身术或软功）。西方击剑和亚洲剑术也有相当的追随者。在持枪合法的地区，射击从1990年代起也越来越受欢迎。与黑客之道最契合的武术是那些强调精神修炼、放松意识，强调控制而不是单纯的蛮力的类型。</li>
<li>学习一种冥想修炼。黑客中一直以来最受欢迎的是禅（很重要的是学禅并不要求你有特定的宗教信仰）（译注：这里指的是日本禅宗，而不是汉地佛教禅宗）。其他方式也可以，但是请注意一定选择那些不会要求你相信很疯狂东西的方式。</li>
<li>修习音乐。学会鉴赏特别的音乐。学会玩某种乐器，或唱歌。</li>
<li>提高对双关语、文字游戏的鉴赏能力。</li>
</ul>
<p>这些事情，你已经在做的越多，你就越是天生做黑客的料。至于为什么偏偏是这些事情，原因并不完全清楚，但它们都涉及用到左右脑混合使用，这似乎是关键所在。黑客们既需要清晰的逻辑思维，有时又需要偏离逻辑跳出问题的表象。</p>
<p>工作即娱乐，娱乐即工作。对于真正的黑客来说，“玩”，“工作”，“科学”和“艺术”之间没有界线，或者说，它们在一个高层面的创造性趣味里融合在一起。另外，不要对一点点技能就感到满足。虽然大多数黑客自称是程序员，他们实际上在其他相关的方面也很可能相当强悍——常见的是系统管理、页面设计和PC硬件故障处理。一个黑客，如果他是一名系统管理员，他很可能对脚本编程和页面设计也相当在行。黑客不会半途而废，如果他们要学习一门技能，他们会将其学好。</p>
<p>最后，一些你 <strong>不应</strong> 做的事。</p>
<p>不要使用愚蠢，哗众取宠的ID或昵称。</p>
<p>不要卷入Usenet（或其他任何地方）的骂战。</p>
<p>不要自称为“赛博朋克（cyberpunk）”，也不要浪费时间跟他们打交道。</p>
<p>不要发送含有大量拼写和语法错误的email和帖子。</p>
<p>做出以上事情只会招来嘲笑。黑客的记性都很好——你犯下的错误会令你将要经过多年才可以被其他黑客接受。</p>
<p>网名的问题值得深思。将身份隐藏在虚假的名字后是骇客、warez d00dz及其他低等生物幼稚愚蠢的行为特点。黑客不会做这些事；他们对他们所作的感到骄傲，而且乐于人们将作品与他们的 <strong>真名</strong> 相联系。 因此, 若你现在用假名，放弃它。黑客社区里只会将用假名的人视为失败者。</p>
<h2 id="历史记录-黑客活动-开源-和自由软件" tabindex="-1">历史记录：黑客活动，开源，和自由软件 <a class="header-anchor" href="#历史记录-黑客活动-开源-和自由软件" aria-label="Permalink to &quot;历史记录：黑客活动，开源，和自由软件&quot;">&ZeroWidthSpace;</a></h2>
<p>当我在1996年末刚开始写这篇文档的时候，很多情况跟现在是不同的。简单的介绍一下这个变化对于对开放源代码、自由软件和Linux跟黑客社区的关系感到困惑的人们可能会有所帮助。如果你对这些不感兴趣，可以直接跳过这里，前往FAQ和参考资料部分。</p>
<p>我描述的黑客精神和黑客社区远早于1990年出现的Linux。我最初进入这个圈子大概是在1976年，其原因可以追溯到1960年代早期。但是在Linux出现前，多数黑客行为是在专有操作系统，或一些自主研发的实验性系统上，例如MIT的ITS，这个系统从未在实验室以外的地方使用过。虽然在早期（Linux出现之前）有过一些试图改变这种状况的努力，但是它们的影响都非常轻微，仅限于真正怀抱这样理想的人群，即使在当时的黑客社区这也是绝对少数，更不论对于世界范围内的通用软件群体的影响了。</p>
<p>现在被称为“开放源代码”的行为，其历史与黑客社区一样久远，但是直到1985年这都只是一个无名的民间行为，没有相关的理论和宣言。这段史前时代在1985年结束，大黑客Richard Stallman（“RMS”）尝试给了它一个名字——“自由软件（Free Software）”。但是这个命名行为也是一个强制要求行为，他为“自由软件”标签加上了大多数已有的黑客社区从不接受的意识形态的包袱。“自由软件”的标签被黑客社区中的一部分重要人物（尤其是与BSD Unix有关联的社区）明确拒绝，并且其余的大部分人也在严肃并且持保留意见的情况下使用它（包括我本人）。</p>
<p>除此之外，大约在1990年代中期以前，RMS想要在“自由软件”口号下定义和引领黑客社区。在Linux崛起之后，这受到了极大挑战。Linux为开放源代码开发活动提供了一个天然的环境。许多在现今被称为“开放源代码”条款下发布的项目纷纷从专有Unix向Linux迁移。围绕Linux的社区呈现爆炸式的增长，比在Linux出现前的黑客文化规模更大且更多样化。RMS想要将这些活动与他的“自由软件”运动关联起来，但是由于Linux社区爆炸式的多样性和该社区的创始人，Linus Torvalds的公开怀疑所阻碍。Torvalds仍然使用“自由软件”这一词汇，因为找不到更好的替代品，但他公开拒绝了RMS的意识形态观念。许多年轻黑客纷纷效仿。</p>
<p>在1996年，当我第一次发布本文的时候，黑客社区正在围绕Linux和一些其他开放源代码的操作系统（尤其是BSD Unix的继承者）进行重组。我们中的许多人曾经在封闭源代码的操作系统上花费大量时间开发封闭源代码软件的集体记忆并没有因此褪色，但是这看起来已经是过去。黑客们将自己作为黑客的定义与开发源代码项目例如Linux和Apache越来越紧密的结合在一起。</p>
<p>然而“开放源代码”这个词直到1998年初才出现。当它出现之后，多数黑客社区在6个月之内采用了它，除了与“自由软件”在意识形态层面绑定的极少数例外。自1998年起，尤其是2003年之后，“黑客”和“开放源代码（和自由软件）开发”越来越紧密相连。今天，几乎已经无法也没必要将它们区分开，并且这一点看起来在将来也不会改变。</p>
<p>然而，曾经并不是这样，这一点值得我们记住。</p>
<h2 id="其他资源" tabindex="-1">其他资源 <a class="header-anchor" href="#其他资源" aria-label="Permalink to &quot;其他资源&quot;">&ZeroWidthSpace;</a></h2>
<p>Paul Graham写了一篇名为“<a href="http://www.paulgraham.com/gh.html" target="_blank" rel="noreferrer">Great Hackers</a>”和一篇名为“<a href="http://www.paulgraham.com/college.html" target="_blank" rel="noreferrer">Undergraduation</a>”的文章，有很多精妙的见解。</p>
<p>年轻的黑客可能会发现<a href="http://catb.org/~esr/faqs/things-every-hacker-once-knew" target="_blank" rel="noreferrer">Things Every Hacker Once Knew</a>有趣并且有用。</p>
<p>有一篇名为<a href="http://samizdat.mines.edu/howto/HowToBeAProgrammer.html" target="_blank" rel="noreferrer">How To Be A Programmer</a>的文章，对如何成为程序员做了详尽的说明。它的价值不仅限于代码及其相关能力上，对于如何在一个程序员团队中工作也有建设性价值。</p>
<p>我写过一篇<a href="http://catb.org/~esr/writings/hacker-history/hacker-history.html" target="_blank" rel="noreferrer">A Brief History Of Hackerdom</a>。</p>
<p>我写过一篇名为“<a href="http://catb.org/~esr/writings/cathedral-bazaar/index.html" target="_blank" rel="noreferrer">大教堂与市集（The Cathedral and the Bazaar）</a>”的文章，在文中解释了Linux和开源社区是如何运作的。在它的续集“<a href="http://catb.org/~esr/writings/homesteading/" target="_blank" rel="noreferrer">开拓智域（Homesteading the Noosphere）</a>”中，我进一步深入探讨了这个问题。</p>
<p>Rick Moen写了一篇很棒的关于<a href="http://linuxmafia.com/faq/Linux_PR/newlug.html" target="_blank" rel="noreferrer">如何运营一个Linux用户组</a>的文章。</p>
<p>Rick Moen和我共著了一篇关于<a href="https://gist.github.com/zer4tul/95ffaa741c836dc6ab3b" target="_blank" rel="noreferrer">提问的智慧</a>的文章。它将使你更容易获取到帮助。</p>
<p>如果需要个人电脑、Unix 和互联网如何工作的基础知识，参阅<a href="http://en.tldp.org/HOWTO/Unix-and-Internet-Fundamentals-HOWTO/" target="_blank" rel="noreferrer">Unix 和互联网工作的基本原理</a>。</p>
<p>当你发布软件或补丁时，试着按<a href="http://en.tldp.org/HOWTO/Software-Release-Practice-HOWTO/index.html" target="_blank" rel="noreferrer">软件发布实践</a>操作。</p>
<p>如果你对禅诗感兴趣，你可能会喜欢<a href="http://catb.org/~esr//writings/unix-koans" target="_blank" rel="noreferrer">Rootless Root: The Unix Koans of Master Foo</a>。</p>
<h2 id="常见问题" tabindex="-1">常见问题 <a class="header-anchor" href="#常见问题" aria-label="Permalink to &quot;常见问题&quot;">&ZeroWidthSpace;</a></h2>
<p>Q: <a href="#hack1">如何证明我已经是一名黑客了？</a><br/>
Q: <a href="#hack2">你能教我做黑客吗？</a><br/>
Q: <a href="#hack3">我该如何开始？</a><br/>
Q: <a href="#hack4">我该什么时候开始学？现在会不会太迟了？</a><br/>
Q: <a href="#hack5">学会黑客之道要多长时间？</a><br/>
Q: <a href="#hack6">Visual Basic是一门好的入门语言吗？</a><br/>
Q: <a href="#hack7">你能教我“黑”掉一个网站，或者教我怎么黑它吗？</a><br/>
Q: <a href="#hack8">我怎么样才能得到别人帐号的密码？</a><br/>
Q: <a href="#hack9">我如何入侵/查看/监视别人的email？</a><br/>
Q: <a href="#hack10">我如何才能盗取IRC的频道管理员权限？</a><br/>
Q: <a href="#hack11">我被人入侵了。你能帮我避免以后再被攻击吗？</a><br/>
Q: <a href="#hack12">我的Windows软件出现问题了。你能帮我吗？</a><br/>
Q: <a href="#hack13">我在哪里可以找到能与之交流的真正的黑客？</a><br/>
Q: <a href="#hack14">你能推荐一些有关黑客的好书吗？</a><br/>
Q: <a href="#hack15">成为一名黑客我需要擅长数学吗？</a><br/>
Q: <a href="#hack16">我该从哪种语言开始学？</a><br/>
Q: <a href="#hack17">我需要什么样的机器配置？</a><br/>
Q: <a href="#hack18">我想做贡献。你能帮我挑选一个问题来处理吗？</a><br/>
Q: <a href="#hack19">我得因此憎恨和反对Microsoft吗？</a><br/>
Q: <a href="#hack20">但开放源代码软件不会使程序员丢饭碗吗？</a><br/>
Q: <a href="#hack21">哪里有免费的Unix？</a><br/></p>
]]></summary>
        <content type="html"><![CDATA[<h1 id="frontmatter-title-转载" tabindex="-1">{{ $frontmatter.title }}(转载) <a class="header-anchor" href="#frontmatter-title-转载" aria-label="Permalink to &quot;{{ $frontmatter.title }}(转载)&quot;">&ZeroWidthSpace;</a></h1>
<div class="warning custom-block github-alert"><p class="custom-block-title">版权声明</p>
<p>How To Become A Hacker</p>
<p>Eric Steven Raymond, Thyrsus Enterprises, &lt; <a href="mailto:esr@thyrsus.com" target="_blank" rel="noreferrer">esr@thyrsus.com</a> &gt;</p>
<p>Copyright © 2001 Eric S. Raymond</p>
<p>翻译：柯非, &lt; <a href="mailto:zer4tul@gmail.com" target="_blank" rel="noreferrer">zer4tul@gmail.com</a> &gt;</p>
</div>
<blockquote>
<p>✒️ 文章摘要</p>
</blockquote>
<!-- DESC SEP -->
<p>在这篇文章中，笔者从《How To Become A Hacker》一文出发，系统地梳理了黑客文化的核心精神、态度与必备技能。我深入探讨了“黑客”与“破坏者（Cracker）”的根本区别，强调黑客并非违法分子，而是一群追求自由、分享与优雅解决问题的人。</p>
<p>为了成为真正的黑客，笔者总结了几条明确的路径：学习编程语言（如Python、C、LISP等），掌握操作系统（尤其是Linux和Unix）、了解互联网的底层原理、熟练使用英语，以及参与自由软件项目。过程中还特别强调了要具备“懒惰、急躁、傲慢”这三种略带反讽却本质积极的黑客美德。</p>
<p>这不仅是一篇技能指南，更是一种价值观的宣言。正如文中所说：“黑客精神，是在智识与创造力之上，对世界不断重构的冲动。”成为黑客，从模仿与学习开始，更重要的是不断探索、思考与分享。</p>
<!-- DESC SEP -->
<h2 id="什么是黑客" tabindex="-1">什么是黑客 <a class="header-anchor" href="#什么是黑客" aria-label="Permalink to &quot;什么是黑客&quot;">&ZeroWidthSpace;</a></h2>
<p><a href="#">新黑客词典（Jargon File）</a>中有数个“黑客”的定义，主要形容&quot;技术专才&quot;或&quot;有志解决问题及超越极限之人&quot;。要成为黑客，有两个要点。</p>
<p>这可以追溯到几十年前第一台分时小型电脑诞生, ARPAnet 实验也刚展开的年代，那时有一个由程序设计专家和网络名人所组成的, 具有分享特点的文化社群。 这种文化的成员创造了 “hacker” 这个词。他们建立了互联网，他们发明了现在使用的Unix操作系统。他们管理Usenet讨论组。他们令WWW运作。因此，若你有上述的特性及参与同类的社区，亦有对以上种种作出贡献，同时社区的人知你是谁又称你为“hacker”，你便是黑客。</p>
<p>然而，黑客的理念并非只局限于软件社区。有很多人将黑客的态度应用于其他事物，如电子或音乐上——实际上，黑客的理念存在于任何科学及文学。由于了解黑客的理念及精神，软件社区的黑客亦会称后者为黑客。有些人亦认为黑客的理念是独立于黑客所从事的媒体。然而，我们将在这篇文章专注讨论软件黑客的技巧，态度及传统。</p>
<p>另外，有一群人亦称自已为“黑客”，他们（多数是年青人）用电脑侵入其他电脑的系统作出破坏。黑客们称这群人为“Cracker（破坏者）”，亦不认同他们为黑客。多数黑客会认为Cracker是懒惰, 不负责任，不杰出的人。有能力侵入安全系统并不能使你成为黑客，正如可以用铁丝来偷车并不能使你成为汽车工程师一样。不幸的是很多作家及报道均称这群人为“黑客”。这一直使黑客们非常恼火。</p>
<p>黑客与Cracker的主要区别在于，前者搞建设，后者搞破坏。</p>
<p>如果你想成为一个黑客，请继续读下去。如果你只想做一个Cracker，请到 alt.2600 讨论组，并做好当你发现自己不如想象中聪颖的时候进5到10次监狱的准备。关于Cracker我就说这么多。</p>
<h2 id="黑客精神" tabindex="-1">黑客精神 <a class="header-anchor" href="#黑客精神" aria-label="Permalink to &quot;黑客精神&quot;">&ZeroWidthSpace;</a></h2>
<p>黑客们解决问题，建设事物，他们崇尚自由和无私的双向帮助。要被他人承认是一名黑客，你必须表现得你具备了这样的态度。而要表现得你具备了这种态度，你必须彻彻底底的坚持它。</p>
<p>如果你认为培养黑客的态度只是一条在这个文化圈中得到认同的路子，那就错了。成为具备这种素质的人对 <strong>你</strong> ¸非常重要 —— 使你保持学习和成为黑客的自发性。正如所有创造性艺术一样，成为大师的最有效途径就是效仿大师的精神——不仅从理念上，还要从态度上效仿。</p>
<p>或许下面的这首现代禅诗很好的阐述了这个意思：</p>
<blockquote>
<p>To follow the path:<br>
沿着这样一条道路：<br>
look to the master,<br>
关注大师，<br>
follow the master,  z
跟随大师，<br>
walk with the master,<br>
与大师同行，<br>
see through the master,<br>
洞察大师，<br>
become the master.<br>
成为大师。</p>
</blockquote>
<p>如果你想成为一名黑客，反复阅读以下内容直到你相信它们：</p>
<h3 id="世上仍有大量迷人的事情等待解决" tabindex="-1">世上仍有大量迷人的事情等待解决 <a class="header-anchor" href="#世上仍有大量迷人的事情等待解决" aria-label="Permalink to &quot;世上仍有大量迷人的事情等待解决&quot;">&ZeroWidthSpace;</a></h3>
<p>作为一名黑客可以享受很多乐趣，同时需要付出相当多的努力。努力需要动力。成功的运动员从锻炼身体、超越身体极限中获得精神愉悦。类似的，作为一名黑客，你可以从解决问题、磨练技术和锻炼智力中获得乐趣。</p>
<p>如果你天生不是这样的人，那你需要设法变成这样的人以使你能够成为一名黑客。否则你将会发现你的精力会被诸如性、金钱、社会上的虚名之类让人分心的东西所消磨掉。</p>
<p>（你还需要对自己的学习能力树立信心——相信尽管你对某一问题了解得不多，只要你能解决其中一部分，并从中学习，你可以解决其他的部分——直到解决它。）</p>
<h3 id="同样的问题不应被重复处理两次" tabindex="-1">同样的问题不应被重复处理两次 <a class="header-anchor" href="#同样的问题不应被重复处理两次" aria-label="Permalink to &quot;同样的问题不应被重复处理两次&quot;">&ZeroWidthSpace;</a></h3>
<p>创造性的智慧是非常有价值且稀缺的资源。它们不应当被浪费在重复发明轮子上，世上仍有大量迷人的新问题等着解决。</p>
<p>作为一名黑客，你应该坚信其他黑客的时间非常宝贵——所以你有义务共享信息，解决问题之后公布方案，这样其他人可以去解决新的问题，而不是忙于应付旧问题。</p>
<p>注意，“同一个问题不应该被重复处理两次”并不是说你必须认为所有已有方案都是最优的，或每个问题只有唯一的解决方案。通常我们从一个问题的最初解决方案中能够学习到很多东西。这很好，并且对于我们思考如何能做得更好来说，这通常是必要的。我们反对的是人为的技术、法律上的，或者机构性的设置障碍（例如闭源软件），使得一个好的方案不能被重复使用，逼得人们重造轮子。</p>
<p>（你不必认为你必须将 <strong>所有</strong> 你的创造发明都公布出去，虽然这样做的黑客将会赢得大家极度尊重。适当卖一些钱来换取足够的食物、租金和电脑并不违反黑客的价值观。用你的技能来养家糊口甚至致富都可以，只要你在做这些的时候别忘记你是一名黑客。）</p>
<h3 id="拒绝重复和沉闷的事情" tabindex="-1">拒绝重复和沉闷的事情 <a class="header-anchor" href="#拒绝重复和沉闷的事情" aria-label="Permalink to &quot;拒绝重复和沉闷的事情&quot;">&ZeroWidthSpace;</a></h3>
<p>黑客（以及富有创造力的所有人）不应当被愚蠢的重复性劳动所困扰，因为这意味着他们并没有在做只有他们才能做的事情——解决新问题。这样的浪费会伤害所有人。因此，无聊和乏味的工作不仅仅是令人不爽，而是罪恶。</p>
<p>作为一个黑客，你应该坚信这一点并尽可能的将枯燥的工作自动化，这不仅仅是为了你自己，也为了其他人（尤其是其他黑客）。</p>
<p>（这里有一个例外。黑客有时会做一些看起来重复或枯燥的事情以进行脑力休息，或以此来锻炼一种技能，或以此获得某种除此以外无法获取的经验。但这是有选择的——有脑子的人不该被强迫做枯燥的事。）</p>
<h3 id="自由万岁" tabindex="-1">自由万岁 <a class="header-anchor" href="#自由万岁" aria-label="Permalink to &quot;自由万岁&quot;">&ZeroWidthSpace;</a></h3>
<p>黑客是天生的反独裁主义者。 任何能向你发号施令的人能够迫使你停止解决令你着迷的问题。 同时，按照独裁者的一般思路，他通常会给出一些极端愚昧的理由。因此，不论何处，任何独裁主义的作法，只要它压迫你和其他黑客，你就要和它斗到底。</p>
<p>（这并非向所有权威挑战。儿童需要监护，罪犯要被看管起来。如果服从命令得到某种东西比起用其他方式得到它更节约时间，黑客可以同意 接受某种形式的权威。但这是一个有限度的，有意的交易；那种权威想要的个人服从不是你应该同意给予的。）</p>
<p>权威喜欢审查和保密。他们不信任自愿的合作和信息共享——他们只喜欢由他们控制的所谓“合作”。因此，作为一个黑客，你得对审查、保密，以及使用武力或欺骗去压迫有行为能力的人们的做法有一种本能的敌意。 同时你要有为此信念斗争的意愿。</p>
<h3 id="精神不能代替能力" tabindex="-1">精神不能代替能力 <a class="header-anchor" href="#精神不能代替能力" aria-label="Permalink to &quot;精神不能代替能力&quot;">&ZeroWidthSpace;</a></h3>
<p>作为一个黑客，你必须培养起这些精神。但是仅仅有精神并不能使你成为黑客，也不能使你成为运动健将或摇滚明星。成为一名黑客还需要智力，实践，奉献精神和辛勤工作。</p>
<p>因此，你需要学会有怀疑态度和尊重任何能力。黑客不会为装模作样的人浪费时间，但他们尊重能力——尤其是从事黑客工作的能力，不过任何能力都是好的。很少人能具备的高要求能力尤其好，其中涉及脑力，技巧和专注方面的能力最好。</p>
<p>尊重能力，你就会享受到提高自己的能力所带来的乐趣——辛苦的工作和奉献将不再是苦差而是一种高度娱乐。想要成为一名黑客，这一点尤其重要。</p>
<h2 id="基本黑客技能" tabindex="-1">基本黑客技能 <a class="header-anchor" href="#基本黑客技能" aria-label="Permalink to &quot;基本黑客技能&quot;">&ZeroWidthSpace;</a></h2>
<p>黑客的态度很重要，但技能更重要。态度不能替代能力，在被别的黑客称你为黑客之前，你有一些基本技能需要掌握。</p>
<p>这些基本技能随着时间的推移和技术的革新也缓慢的变化着。例如以前的内容中包括了使用机器语言编程，最近包含进了HTML。总的来说当前包括以下内容：</p>
<h3 id="学习编程" tabindex="-1">学习编程 <a class="header-anchor" href="#学习编程" aria-label="Permalink to &quot;学习编程&quot;">&ZeroWidthSpace;</a></h3>
<p>理所当然，这是最基本的黑客技能。如果你一门计算机语言都不懂，我建议你从Python学起。它设计良好，文档详尽，并且对新人十分友好。尽管它是一门很好的入门语言，但它不只是玩具水平。它非常强大灵活，并且适用于大型项目。我写过一篇详细的<a href="http://www.linuxjournal.com/article/3882" target="_blank" rel="noreferrer">对Python的评价</a>。在<a href="http://docs.python.org/tutorial/index.html" target="_blank" rel="noreferrer">Python的网站</a>可以找到很好的<a href="http://docs.python.org/tutorial/index.html" target="_blank" rel="noreferrer">教程</a>。在<a href="http://cscircles.cemc.uwaterloo.ca/" target="_blank" rel="noreferrer">Computer Science Circles</a>也有一篇不错的第三方教程。</p>
<p>我早前曾经建议使用Java作为入门语言，但<a href="http://www.crosstalkonline.org/storage/issue-archives/2008/200801/200801-Dewar.pdf" target="_blank" rel="noreferrer">这篇评价</a>改变了我的看法（请在文档中搜索“The Pitfalls of Java as a First Programming Language”）。如同文中尖锐指出的一样，一个黑客不能“像五金店中的管道工一样处理问题”。你需要知道所有的组件事实上都 <strong>干了什么</strong>。现在，我认为最好先学C和Lisp，然后再学Java。</p>
<p>比Java更好的选择是学习Go。这种相对较新的语言很容易从Python上手，而且学习它可以使你在可能的下一步（学习C语言）中得到很大的帮助。此外，未来几年的一个未知数是Go将在多大程度上取代C语言成为真正的系统编程语言。在未来，这种情况可能会在C语言的大部分传统领域内发生。</p>
<p>另外有一点需要注意。如果一门语言帮你做了太多工作，它会同时是一个好的生产工具和一个不好的初学对象。不仅语言有这个问题，Web框架比如RubyOnRails，CakePHP，Django也很容易让你流于表面，面对困难问题的时候束手无策，甚至无法对一个简单问题进行追查并给出解决方案。</p>
<p>如果你需要做一些重要的编程工作，你需要学习C语言，它是Unix的核心语言。C++跟C关系密切。如果你了解其中一种，学习另外一种应该不难。但是这两种语言都不适合作为入门学习。此外，如果你越避免用C编程，你的工作效率会越高。</p>
<p>C的执行效率非常高，并且非常节省机器资源。不幸的是C的高效是通过让你手动进行许多底层资源（例如内存）管理来获得的。底层代码复杂并且容易出bug，你需要花费很多时间来进行调试。鉴于当今的机器性能如此之高，这样的做法通常很不划算——通常更好的做法是使用一种稍微慢一些，不那么高效，但是能够 <strong>大幅</strong> 节省你的时间的语言。那便是Python。</p>
<p>其他对黑客而言比较重要的语言包括Perl和LISP。Perl很实用，它广泛应用于动态网页和系统管理方面，因此即使你从不写Perl代码，至少也得能看懂。许多人使用Perl的理由和我建议你使用Python的理由一样，都是为了避免用C完成那些执行效率需求不那么高的工作。你需要能够看懂他们的代码。</p>
<p>LISP之所以值得一学是基于另外的理由——当你最终掌握了它的时候，你将会获得巨大的启迪。它将使你在今后成为一个更好的程序员，即使你实际上很少使用LISP本身。（你可以通过为Emacs文本编辑器或者GIMP的Script-Fu编写插件或修改现有插件来很容易的学习LISP。）</p>
<p>当然，你最好五种语言都会（Python，C/C++，Java，Perl和LISP）。除了是重要的黑客语言之外，它们也代表了截然不同的编程思路和方法，每一种都能让你受益匪浅。</p>
<p>但是单纯的堆砌语言是不可能成为一个黑客，甚至程序员的。你需要学会如何独立于任何具体的语言之外来思考编程问题。作为一名真正的黑客，你需要通过手册和你已有的知识掌握到在几天之内学会一门语言的要点。这意味着你需要学习许许多多不同的语言。</p>
<p>这里我无法给你完完全全的指导教会你如何编程——这是个复杂的技能。但我可以告诉你，书本和课程也不能做到（最好的黑客中，有许多，也许 <strong>几乎</strong> 都是自学成才的）。 你可以从书本上学到语言的特点——这只是皮毛，但要使书面知识成为自身技能只能通过实践和虚心向他人学习。因此要做到</p>
<pre><code>（1）**读** 代码
（2）**写** 代码。
</code></pre>
<p>Peter Norvig，Google最顶级的黑客之一，也是世界上最受欢迎的AI教材（译注：指“人工智能：一种现代方法”和“人工智能程序设计范例：通用Lisp语言的案例研究”等）的共同作者。他写了一篇名为<a href="http://www.norvig.com/21-days.html" target="_blank" rel="noreferrer">Teach Yourself Programming in Ten Years</a>的短文。他在文中提到的“编程成功的诀窍（recipe for programming success）”特别值得留意。</p>
<p>学习编程就像学习用优美的自然语言书写一样。最好的办法就是阅读大师的名著，试着自己写点东西，再读一些，再写一点，再读一些，再写一点……如此往复，直到你的作品达到如你在范文中所见的简洁和健壮。</p>
<p>我必须再提一下<a href="#">How To Learn Hacking</a>，这是一些简单的说明，但是学起来并不容易。</p>
<p>以前很难找到适合阅读的好代码，因为几乎没有大型程序的代码能够供新人阅读和练手。这种情况已经发生戏剧性的变化。开源软件，编程工具和操作系统（都是由黑客创造的）现在随处可见。这刚好带我们到下一个话题……</p>
<h3 id="获取一个开源的unix并学习运行和使用它" tabindex="-1">获取一个开源的Unix并学习运行和使用它 <a class="header-anchor" href="#获取一个开源的unix并学习运行和使用它" aria-label="Permalink to &quot;获取一个开源的Unix并学习运行和使用它&quot;">&ZeroWidthSpace;</a></h3>
<p>我假定你拥有或者能使用一台个人电脑（现在的孩子真幸福。黑客文化建立之初电脑贵得要死，没人买得起）。新手们向黑客技能迈出的最重要一步就是获取一份Linux或BSD-Unix的拷贝，将其安装在个人电脑上，并运行它。</p>
<p>没错，世上除了Unix还有其他操作系统。但它们都是以二进制形式发布的——你读不到源码，你也不能修改代码。在类似Microsoft Windows那样的闭源操作系统上学习黑客技术就像戴着脚镣学跳舞。</p>
<p>在Mac OS X上倒是可以，不过它只有一部分是开源的——你可能会撞墙，也必须很小心的避免养成依赖Apple专有代码的坏习惯。如果你专注于底层的Unix，你可以学到一些有用的东西。</p>
<p>Unix是互联网上的操作系统。虽然你不懂Unix仍然可以学会使用互联网，但若你不懂Unix，你将不能在互联网上从事黑客活动。因此，现今的黑客文化是严重以Unix为中心的。（曾经不是这样，并且有一些老派的黑客对此仍然感到不太高兴。但是现今Unix和互联网的羁绊如此之强，连Microsoft也无法撼动分毫。）</p>
<p>所以，请安装一套Unix - 我个人喜爱Linux但还有其他种类的（并且，你 <strong>可以</strong> 在同一台电脑上运行Linux和Windows）。学习它，使用它，调教它。用它在互联网上冲浪。阅读它的代码，修改它的代码。你将获得比Windows操作系统上更好的编程工具（包括C，LISP，Python和Perl）。你会觉得其乐无穷，学到比你想像更多更好的知识。</p>
<p>想要获取更多和学习Unix相关的信息，请参考<a href="http://catb.org/~esr/faqs/loginataka.html" target="_blank" rel="noreferrer">Loginataka</a>。你或许还想看看<a href="http://catb.org/~esr/writings/taoup/" target="_blank" rel="noreferrer">Unix编程艺术</a>（译注：这里给出的是原文链接。国内有翻译版出售）。</p>
<p>我认为博客<a href="https://letsgolarval.wordpress.com/" target="_blank" rel="noreferrer">Let's Go Larval!</a>对于处在学习Linux阶段中的用户是非常易懂和有用的。 这篇文章<a href="https://letsgolarval.wordpress.com/2015/06/23/how-i-learned-linux" target="_blank" rel="noreferrer">How I Learned Linux</a> 就是一个很好的起点。</p>
<p>想开始Linux之旅，请参考<a href="http://www.linux.org/" target="_blank" rel="noreferrer">Linux Online!</a>。你可以从那里下载Linux或者（更好的主意是）找到一个当地的Linux用户群为你的安装过程提供帮助。</p>
<p>在本文最初的10年间，我认为从一个初学者的角度来说，所有Linux发行版都差不多。不过在2006~2007年间，一个事实上最好的选择出现了：<a href="http://www.ubuntu.com/" target="_blank" rel="noreferrer">Ubuntu</a>。其他发行版各有所长，而Ubuntu对初学者最友好。注意，相比Ubuntu默认那个丑陋的几乎不可用的“Unity”桌面，Xubuntu和Kubuntu更好用一点。</p>
<p>你可以在<a href="http://www.bsd.org/" target="_blank" rel="noreferrer">www.bsd.org</a>找到BSD相关的帮助和资源。</p>
<p>一个试水的好办法是试试被Linux爱好者称为“Live CD”的东西，那是一个完全在光盘或者U盘上运行，而不修改你硬盘的发行版。它运行起来比较慢，因为光盘很慢，但是这是一个在做出任何不可挽救的改变前看看可行性的办法。</p>
<p>我写过一篇关于<a href="http://en.tldp.org/HOWTO/Unix-and-Internet-Fundamentals-HOWTO/index.html" target="_blank" rel="noreferrer">Unix和互联网基础</a>的入门文章。</p>
<p>我曾经不建议新手独自安装Linux或者BSD。现在它们的安装程序已经做得足够好，你作为新人也完全搞得定。尽管如此，我仍然建议和你当地的Linux用户群取得联系并寻求帮助。这没坏处，并且可以让整个过程更顺利。</p>
<h3 id="学习使用万维网-world-wide-web-www-和html-超文本标记语言" tabindex="-1">学习使用万维网（World Wide Web，WWW）和HTML（超文本标记语言） <a class="header-anchor" href="#学习使用万维网-world-wide-web-www-和html-超文本标记语言" aria-label="Permalink to &quot;学习使用万维网（World Wide Web，WWW）和HTML（超文本标记语言）&quot;">&ZeroWidthSpace;</a></h3>
<p>大多数的黑客造物在你所不知的地方发挥着作用，帮助工厂、办公室和学校运转，这看上去跟普通人没太大关系。Web是一个大大的例外，即便 <strong>政客</strong> 也承认这个巨大耀眼的黑客玩具正在改变着世界。单就这一个原因（当然还有其他理由）你就需要学习掌握Web。</p>
<p>这并不仅仅意味着如何使用浏览器（谁都会），而是要学会如何写HTML，Web的标记语言。如果你不会编程，写HTML会教你一些有助于学习的思考习惯。因此，先完成一个主页。尝试坚持使用XHTML，一种比标准HTML更清晰的语言。（Web上有很多很好的初学者指南，例如<a href="http://htmldog.com/" target="_blank" rel="noreferrer">这个</a>）。</p>
<p>但仅仅拥有一个主页不能使你成为一名黑客。Web里充满了各种网页。大多数是毫无意义的，零信息量的垃圾——界面时髦，能夺人眼球的垃圾还是垃圾（更多信息访问<a href="http://catb.org/~esr/html-hell.html" target="_blank" rel="noreferrer">The HTML Hell Page</a>）。</p>
<p>所以，你的页面必须有内容——得是有趣并且/或者对其他黑客来说有用的内容。这是我们下一个议题要说的……</p>
<h3 id="学习实用英语" tabindex="-1">学习实用英语 <a class="header-anchor" href="#学习实用英语" aria-label="Permalink to &quot;学习实用英语&quot;">&ZeroWidthSpace;</a></h3>
<p>作为一个美国人和一个以英语为母语的人，我以前很不情愿提到这点，免得成为一种文化上的帝国主义。但相当多以其他语言为母语的人一直劝我指出这一点，那就是英语是黑客文化和Internet的工作语言，你需要懂得以便在黑客社区顺利工作。</p>
<p>大概1991年的时候我了解到许多黑客在技术讨论中使用英语，即使在他们的母语都相同，英语对他们而言只是第二语言的时候也常如此。据我所知，当前英语有着比其他语言丰富得多的技术词汇，因此是一个对于工作来说相当好的工具。基于同样的理由，英文技术书籍的翻译（如果有的话）通常都不能令读者满意。</p>
<p>芬兰人Linus Torvalds用英语注释他的代码（很明显这不是凑巧）。他流利的英语成为他能够管理全球范围的Linux开发人员社区的重要因素。这是一个值得学习的例子。</p>
<p>即使作为一个以英语为母语的人也不代表你就具备了成为黑客所需的语言技能。一般而言，如果你写得像个半文盲似的，文中充斥着各种语法、拼写错误，多半得不到理睬。虽然不严谨的文笔并不总是意味着不严谨的思维，但我们发现这两者之间的关联还是挺紧密的。而我们不需要这种思维不严谨的人。如果你现在还没有具备这样的书写能力，赶紧培养。</p>
<h2 id="在黑客社区中立足" tabindex="-1">在黑客社区中立足 <a class="header-anchor" href="#在黑客社区中立足" aria-label="Permalink to &quot;在黑客社区中立足&quot;">&ZeroWidthSpace;</a></h2>
<p>像大部分非盈利社区一样，黑客社区靠声誉运转。你设法解决有趣的问题，但问题是否有趣及解决方法是否有效，需要由那些和你具有同样甚至更高技术水平的人去评判。</p>
<p>因此，要玩黑客这个游戏，你需要以其他黑客对你技能的评判作为对自己的评价（所以我说，在其他黑客称你为黑客之前，你不是一个真正的黑客）。这个事实常被人误解（从1990年代后有所好转，但还是很严重），人们认为黑客都是不在乎别人的评价，孤僻的人。这实际上是一个黑客文化的禁忌。</p>
<p>特别地，黑客被人类学家们称为 <strong>奉献社区</strong>。在这里你不是凭借你对别人的统治来建立地位和名望，也不是靠美貌，或拥有其他人想要的东西，而是靠你的奉献。尤其是奉献你的时间，你的创造力和你的技术成果。</p>
<p>要想获得黑客的尊重，你基本上有5件事情可干：</p>
<h3 id="编写开源软件" tabindex="-1">编写开源软件 <a class="header-anchor" href="#编写开源软件" aria-label="Permalink to &quot;编写开源软件&quot;">&ZeroWidthSpace;</a></h3>
<p>首先（也是最传统和最重要的）是写一些其他黑客觉得有趣或有用的程序，并且开放源代码。</p>
<p>（我们曾经把这些程序称为“自由软件（free software）”，但是太多人不能确定这里的“free”是什么意思。现在我们通常使用“<a href="http://www.opensource.org/" target="_blank" rel="noreferrer">开源</a>”软件这个词。</p>
<p>黑客间最受尊敬的圣人是那些编写了大型的，功能强劲且满足了广泛需求的开源软件供他人使用的人。</p>
<p>但是这里有段有趣的历史。虽然黑客一直敬重开源软件开发者，并且他们是我们社区的核心，但是直到1990年代中期，绝大部分黑客绝大多数时间是在闭源软件上工作的。在我1996年写本文的第一版的时候仍然如此。到1997年之后开源软件逐渐成为主流并改变了这一点。现在，“黑客社区”和“开源软件开发者”本质上是对同一文化和同一人群的两种表述——但值得记住的是，曾经不是如此。（想了解更多，请看“<a href="https://github.com/zer4tul/hacker-howto?tab=readme-ov-file#%E5%8E%86%E5%8F%B2%E8%AE%B0%E5%BD%95%EF%BC%9A%E9%BB%91%E5%AE%A2%E6%B4%BB%E5%8A%A8%EF%BC%8C%E5%BC%80%E6%BA%90%EF%BC%8C%E5%92%8C%E8%87%AA%E7%94%B1%E8%BD%AF%E4%BB%B6" target="_blank" rel="noreferrer">历史记录：黑客活动，开源，和自由软件</a>”。）</p>
<h3 id="帮助测试和调试开源软件" tabindex="-1">帮助测试和调试开源软件 <a class="header-anchor" href="#帮助测试和调试开源软件" aria-label="Permalink to &quot;帮助测试和调试开源软件&quot;">&ZeroWidthSpace;</a></h3>
<p>黑客也尊敬那些为开源软件进行测试和除错的人。在这个并非完美的世界上，我们不可避免地要花大多数的开发时间在调试阶段。 这就是为什么许多开源软件作者都会高度评价那些好的beta测试员 （知道如何清楚描述出错症状，很好地定位错误，能忍受快速发布中的bug，并且愿意使用一些简单的诊断工具），认为他们像红宝石一样珍贵。一个好的测试员可以使如恶梦的测试及除错工作变为一件值得经历的小烦恼。</p>
<p>如果你是个新手，试着找一个你感兴趣的正在开发的程序，尝试做一个好的beta测试员。 你会自然地从帮着测试，进步到帮着抓bug，到最后帮着改程序。你会从中学到很多，并且与未来会帮到你的人结下友谊。</p>
<h3 id="发布有用的信息" tabindex="-1">发布有用的信息 <a class="header-anchor" href="#发布有用的信息" aria-label="Permalink to &quot;发布有用的信息&quot;">&ZeroWidthSpace;</a></h3>
<p>另一个好事是收集整理有用有趣的信息做成网页或文档如FAQ（常见问题）列表，且让他们容易获得。</p>
<p>技术性FAQ的维护者往往如同开源软件作者一样很受人尊重。</p>
<h3 id="帮助维护基础设施运转" tabindex="-1">帮助维护基础设施运转 <a class="header-anchor" href="#帮助维护基础设施运转" aria-label="Permalink to &quot;帮助维护基础设施运转&quot;">&ZeroWidthSpace;</a></h3>
<p>黑客社区（也包括互联网发展）是靠自愿者组成的。有大量重要但平淡的事情需要处理——管理邮件列表，新闻组，维护大型软件归档库，开发RFC和其他技术标准等。</p>
<p>做以上事情的人会得到很多人的尊敬，因为大家都知道这些事情需要大量的时间并且不如编写软件那么有趣。这类工作需要使命感。</p>
<h3 id="为黑客社区服务" tabindex="-1">为黑客社区服务 <a class="header-anchor" href="#为黑客社区服务" aria-label="Permalink to &quot;为黑客社区服务&quot;">&ZeroWidthSpace;</a></h3>
<p>最后，你还可以为黑客社区做服务和宣扬（比如写一篇“如何成为黑客”的文章 😃）。通常你不会做这些工作，直到你已经做了以上四种中的一样，并且取得了相当的知名度。</p>
<p>黑客社区没有既定的领导者，但是有被人们尊重的英雄，长老级人物，史学家和发言人。当你在这个圈里足够久，你可能会成为他们中的一员。但请谨记，黑客对于自我夸耀的长老并不认同，因此不要尝试大举追求这种名誉。与其奋力追求，不如先摆正自己的位置，等它自己到你手中，那时需要做到谦虚和优雅。</p>
<h2 id="黑客与书呆子-nerd-的关系" tabindex="-1">黑客与书呆子（Nerd）的关系 <a class="header-anchor" href="#黑客与书呆子-nerd-的关系" aria-label="Permalink to &quot;黑客与书呆子（Nerd）的关系&quot;">&ZeroWidthSpace;</a></h2>
<p>与流行的传说不同，黑客并不是书呆子。但这确实对你成为黑客有帮助，并且很多黑客确实是书呆子。做一个深居简出的人有助于使你更能集中精力做一些重要的事，例如思考和从事黑客活动。</p>
<p>因此，许多黑客甚至以“极客（geek）”（译注：这个词原本在美国俚语中指“反常的人”）为名——这是一种宣布他们独立于普通社会的方式（此外，黑客也通常沉迷于其他一些事情例如科幻和战略游戏）。“书呆子”这个词通常在1990年代也被如此使用，那时候“书呆子”这个词略含贬义，而“极客”贬义更重。2000年以后这两个词的关系发生了转变，至少在美国流行文化上是如此，现在甚至在非技术专家中也出现了以标榜为极客为豪的情况。</p>
<p>如果你能集中足够的精力做好黑客工作同时还能有正常的生活，这很好。现在做到这一点比我在1970年代还是新手的时候要容易的多；如今主流文化对技术怪人要友善的多。甚至有越来越多的人意识到黑客通常是很好的恋人和配偶侯选。</p>
<p>如果你因为生活上的不如意而成为黑客，那也不错——至少你不用分神了。或许今后你能有一个不错的生活。</p>
<h2 id="风格" tabindex="-1">风格 <a class="header-anchor" href="#风格" aria-label="Permalink to &quot;风格&quot;">&ZeroWidthSpace;</a></h2>
<p>重申一下，作为一名黑客，你必须进入黑客式思维模式。当你不在电脑边的时候你仍然有很多有益的事情可做。它们不能替代真正的黑客活动（没有什么可以），但是很多黑客都这么干，并且感到它们与黑客精神存在某些根本的联系。</p>
<ul>
<li>学会流畅的使用母语写作。虽然认为程序员写不好文章的误解仍然很普遍，但是有数量令人惊讶的黑客（包括我所知造诣最高的那些）都是不错的写手。</li>
<li>阅读科幻小说。参加科幻聚会（一个接触黑客和可能成为黑客的人的好方法）。</li>
<li>加入黑客空间（hackerspace）并做一些东西出来（另外一个接触黑客和可能成为黑客的人的好方法）。</li>
<li>习武。武术的精神修炼与黑客之道惊人的相似。黑客中比较常见的当然是亚洲的空手格斗技巧，例如跆拳道、空手道及其变种、中国功夫、合气道、柔术（译注：这里指的是日本传统武术，而不是柔身术或软功）。西方击剑和亚洲剑术也有相当的追随者。在持枪合法的地区，射击从1990年代起也越来越受欢迎。与黑客之道最契合的武术是那些强调精神修炼、放松意识，强调控制而不是单纯的蛮力的类型。</li>
<li>学习一种冥想修炼。黑客中一直以来最受欢迎的是禅（很重要的是学禅并不要求你有特定的宗教信仰）（译注：这里指的是日本禅宗，而不是汉地佛教禅宗）。其他方式也可以，但是请注意一定选择那些不会要求你相信很疯狂东西的方式。</li>
<li>修习音乐。学会鉴赏特别的音乐。学会玩某种乐器，或唱歌。</li>
<li>提高对双关语、文字游戏的鉴赏能力。</li>
</ul>
<p>这些事情，你已经在做的越多，你就越是天生做黑客的料。至于为什么偏偏是这些事情，原因并不完全清楚，但它们都涉及用到左右脑混合使用，这似乎是关键所在。黑客们既需要清晰的逻辑思维，有时又需要偏离逻辑跳出问题的表象。</p>
<p>工作即娱乐，娱乐即工作。对于真正的黑客来说，“玩”，“工作”，“科学”和“艺术”之间没有界线，或者说，它们在一个高层面的创造性趣味里融合在一起。另外，不要对一点点技能就感到满足。虽然大多数黑客自称是程序员，他们实际上在其他相关的方面也很可能相当强悍——常见的是系统管理、页面设计和PC硬件故障处理。一个黑客，如果他是一名系统管理员，他很可能对脚本编程和页面设计也相当在行。黑客不会半途而废，如果他们要学习一门技能，他们会将其学好。</p>
<p>最后，一些你 <strong>不应</strong> 做的事。</p>
<p>不要使用愚蠢，哗众取宠的ID或昵称。</p>
<p>不要卷入Usenet（或其他任何地方）的骂战。</p>
<p>不要自称为“赛博朋克（cyberpunk）”，也不要浪费时间跟他们打交道。</p>
<p>不要发送含有大量拼写和语法错误的email和帖子。</p>
<p>做出以上事情只会招来嘲笑。黑客的记性都很好——你犯下的错误会令你将要经过多年才可以被其他黑客接受。</p>
<p>网名的问题值得深思。将身份隐藏在虚假的名字后是骇客、warez d00dz及其他低等生物幼稚愚蠢的行为特点。黑客不会做这些事；他们对他们所作的感到骄傲，而且乐于人们将作品与他们的 <strong>真名</strong> 相联系。 因此, 若你现在用假名，放弃它。黑客社区里只会将用假名的人视为失败者。</p>
<h2 id="历史记录-黑客活动-开源-和自由软件" tabindex="-1">历史记录：黑客活动，开源，和自由软件 <a class="header-anchor" href="#历史记录-黑客活动-开源-和自由软件" aria-label="Permalink to &quot;历史记录：黑客活动，开源，和自由软件&quot;">&ZeroWidthSpace;</a></h2>
<p>当我在1996年末刚开始写这篇文档的时候，很多情况跟现在是不同的。简单的介绍一下这个变化对于对开放源代码、自由软件和Linux跟黑客社区的关系感到困惑的人们可能会有所帮助。如果你对这些不感兴趣，可以直接跳过这里，前往FAQ和参考资料部分。</p>
<p>我描述的黑客精神和黑客社区远早于1990年出现的Linux。我最初进入这个圈子大概是在1976年，其原因可以追溯到1960年代早期。但是在Linux出现前，多数黑客行为是在专有操作系统，或一些自主研发的实验性系统上，例如MIT的ITS，这个系统从未在实验室以外的地方使用过。虽然在早期（Linux出现之前）有过一些试图改变这种状况的努力，但是它们的影响都非常轻微，仅限于真正怀抱这样理想的人群，即使在当时的黑客社区这也是绝对少数，更不论对于世界范围内的通用软件群体的影响了。</p>
<p>现在被称为“开放源代码”的行为，其历史与黑客社区一样久远，但是直到1985年这都只是一个无名的民间行为，没有相关的理论和宣言。这段史前时代在1985年结束，大黑客Richard Stallman（“RMS”）尝试给了它一个名字——“自由软件（Free Software）”。但是这个命名行为也是一个强制要求行为，他为“自由软件”标签加上了大多数已有的黑客社区从不接受的意识形态的包袱。“自由软件”的标签被黑客社区中的一部分重要人物（尤其是与BSD Unix有关联的社区）明确拒绝，并且其余的大部分人也在严肃并且持保留意见的情况下使用它（包括我本人）。</p>
<p>除此之外，大约在1990年代中期以前，RMS想要在“自由软件”口号下定义和引领黑客社区。在Linux崛起之后，这受到了极大挑战。Linux为开放源代码开发活动提供了一个天然的环境。许多在现今被称为“开放源代码”条款下发布的项目纷纷从专有Unix向Linux迁移。围绕Linux的社区呈现爆炸式的增长，比在Linux出现前的黑客文化规模更大且更多样化。RMS想要将这些活动与他的“自由软件”运动关联起来，但是由于Linux社区爆炸式的多样性和该社区的创始人，Linus Torvalds的公开怀疑所阻碍。Torvalds仍然使用“自由软件”这一词汇，因为找不到更好的替代品，但他公开拒绝了RMS的意识形态观念。许多年轻黑客纷纷效仿。</p>
<p>在1996年，当我第一次发布本文的时候，黑客社区正在围绕Linux和一些其他开放源代码的操作系统（尤其是BSD Unix的继承者）进行重组。我们中的许多人曾经在封闭源代码的操作系统上花费大量时间开发封闭源代码软件的集体记忆并没有因此褪色，但是这看起来已经是过去。黑客们将自己作为黑客的定义与开发源代码项目例如Linux和Apache越来越紧密的结合在一起。</p>
<p>然而“开放源代码”这个词直到1998年初才出现。当它出现之后，多数黑客社区在6个月之内采用了它，除了与“自由软件”在意识形态层面绑定的极少数例外。自1998年起，尤其是2003年之后，“黑客”和“开放源代码（和自由软件）开发”越来越紧密相连。今天，几乎已经无法也没必要将它们区分开，并且这一点看起来在将来也不会改变。</p>
<p>然而，曾经并不是这样，这一点值得我们记住。</p>
<h2 id="其他资源" tabindex="-1">其他资源 <a class="header-anchor" href="#其他资源" aria-label="Permalink to &quot;其他资源&quot;">&ZeroWidthSpace;</a></h2>
<p>Paul Graham写了一篇名为“<a href="http://www.paulgraham.com/gh.html" target="_blank" rel="noreferrer">Great Hackers</a>”和一篇名为“<a href="http://www.paulgraham.com/college.html" target="_blank" rel="noreferrer">Undergraduation</a>”的文章，有很多精妙的见解。</p>
<p>年轻的黑客可能会发现<a href="http://catb.org/~esr/faqs/things-every-hacker-once-knew" target="_blank" rel="noreferrer">Things Every Hacker Once Knew</a>有趣并且有用。</p>
<p>有一篇名为<a href="http://samizdat.mines.edu/howto/HowToBeAProgrammer.html" target="_blank" rel="noreferrer">How To Be A Programmer</a>的文章，对如何成为程序员做了详尽的说明。它的价值不仅限于代码及其相关能力上，对于如何在一个程序员团队中工作也有建设性价值。</p>
<p>我写过一篇<a href="http://catb.org/~esr/writings/hacker-history/hacker-history.html" target="_blank" rel="noreferrer">A Brief History Of Hackerdom</a>。</p>
<p>我写过一篇名为“<a href="http://catb.org/~esr/writings/cathedral-bazaar/index.html" target="_blank" rel="noreferrer">大教堂与市集（The Cathedral and the Bazaar）</a>”的文章，在文中解释了Linux和开源社区是如何运作的。在它的续集“<a href="http://catb.org/~esr/writings/homesteading/" target="_blank" rel="noreferrer">开拓智域（Homesteading the Noosphere）</a>”中，我进一步深入探讨了这个问题。</p>
<p>Rick Moen写了一篇很棒的关于<a href="http://linuxmafia.com/faq/Linux_PR/newlug.html" target="_blank" rel="noreferrer">如何运营一个Linux用户组</a>的文章。</p>
<p>Rick Moen和我共著了一篇关于<a href="https://gist.github.com/zer4tul/95ffaa741c836dc6ab3b" target="_blank" rel="noreferrer">提问的智慧</a>的文章。它将使你更容易获取到帮助。</p>
<p>如果需要个人电脑、Unix 和互联网如何工作的基础知识，参阅<a href="http://en.tldp.org/HOWTO/Unix-and-Internet-Fundamentals-HOWTO/" target="_blank" rel="noreferrer">Unix 和互联网工作的基本原理</a>。</p>
<p>当你发布软件或补丁时，试着按<a href="http://en.tldp.org/HOWTO/Software-Release-Practice-HOWTO/index.html" target="_blank" rel="noreferrer">软件发布实践</a>操作。</p>
<p>如果你对禅诗感兴趣，你可能会喜欢<a href="http://catb.org/~esr//writings/unix-koans" target="_blank" rel="noreferrer">Rootless Root: The Unix Koans of Master Foo</a>。</p>
<h2 id="常见问题" tabindex="-1">常见问题 <a class="header-anchor" href="#常见问题" aria-label="Permalink to &quot;常见问题&quot;">&ZeroWidthSpace;</a></h2>
<p>Q: <a href="#hack1">如何证明我已经是一名黑客了？</a><br/>
Q: <a href="#hack2">你能教我做黑客吗？</a><br/>
Q: <a href="#hack3">我该如何开始？</a><br/>
Q: <a href="#hack4">我该什么时候开始学？现在会不会太迟了？</a><br/>
Q: <a href="#hack5">学会黑客之道要多长时间？</a><br/>
Q: <a href="#hack6">Visual Basic是一门好的入门语言吗？</a><br/>
Q: <a href="#hack7">你能教我“黑”掉一个网站，或者教我怎么黑它吗？</a><br/>
Q: <a href="#hack8">我怎么样才能得到别人帐号的密码？</a><br/>
Q: <a href="#hack9">我如何入侵/查看/监视别人的email？</a><br/>
Q: <a href="#hack10">我如何才能盗取IRC的频道管理员权限？</a><br/>
Q: <a href="#hack11">我被人入侵了。你能帮我避免以后再被攻击吗？</a><br/>
Q: <a href="#hack12">我的Windows软件出现问题了。你能帮我吗？</a><br/>
Q: <a href="#hack13">我在哪里可以找到能与之交流的真正的黑客？</a><br/>
Q: <a href="#hack14">你能推荐一些有关黑客的好书吗？</a><br/>
Q: <a href="#hack15">成为一名黑客我需要擅长数学吗？</a><br/>
Q: <a href="#hack16">我该从哪种语言开始学？</a><br/>
Q: <a href="#hack17">我需要什么样的机器配置？</a><br/>
Q: <a href="#hack18">我想做贡献。你能帮我挑选一个问题来处理吗？</a><br/>
Q: <a href="#hack19">我得因此憎恨和反对Microsoft吗？</a><br/>
Q: <a href="#hack20">但开放源代码软件不会使程序员丢饭碗吗？</a><br/>
Q: <a href="#hack21">哪里有免费的Unix？</a><br/></p>
<hr>
<div id="hack1"><b>Q: 如何证明我已经是一名黑客了？</b></div>
<p>A: 问自己以下三个问题：</p>
<p>* 你能够流畅的编写代码吗？<br>
 * 你是否与黑客社区的目标和价值观产生共鸣？<br>
 * 是否有知名黑客称你为黑客？</p>
<p>如果你对三个问题的回答都是肯定的，你就已经是一名黑客。哪怕只有一个回答是否定的也不行。</p>
<p>第一个问题是关于技能的。如果你具备了前文提到的基本技能，就应该没问题。如果你已经有相当数量的代码被开源项目所接受，可以跳过这个问题。</p>
<p>第二个问题是关于精神的。如果前面的<a href="#黑客精神">五条黑客的精神</a>明显比其他地方的描述更贴近你的真实生活，你就已经通过了一半。这是内在的一半，外在的一半是你对黑客社区长期项目的贡献程度。</p>
<p>这里有一个不完整但具有指示性的项目列表：Linux的改进和发展是否有你的贡献？你是否对软件自由充满激情？你是否反对垄断？你是否为了让计算机成为这个世界更丰富多彩、更人性化的工具而努力？</p>
<p>请注意。黑客社区有一些特定的，主要是防御性的政治倾向——其中两条是维护言论自由和抵御可能使开放源代码非法的“知识产权”。有一些长期项目是公民自由组织，例如电子前哨基金会（EFF），外在的态度包括支持他们。除此之外，大多数企图将黑客精神系统化为一个具体的政治程序的黑客都值得怀疑。我们曾经为此付出过代价，并了解到这些想法通常会导致分裂并且令人心烦意乱。如果有人想要以黑客精神的名义来招揽你，那是他们搞错了重点。最好的回应恐怕是“闭嘴，给他们看代码（Shut up and show them the code）。”</p>
<p>第三个问题是递归的。我在“<a href="#什么是黑客">什么是黑客</a>”中提到过，成为一名黑客，就是成为一个具有分享特点的文化社群的一员。很久之前，黑客相比现在是一个松散的，不自知的群体。但是近30年来，由于互联网使得黑客文化的核心更易发展和维护，人际网络方面取得了长足进步。这种改变最简单的代表就是，在这个世纪，我们有了自己的T恤。</p>
<p>社会学家在研究类似黑客社区这样的被统称为“无形学院（invisible colleges）”的人际网络时注意到，这类网络通常都有门卫——具有社区授权的核心成员会审核新人的进入申请。由于黑客社区是“无形学院”中比较松散和非正式的一种，门卫的身份也是非正式的。但是所有黑客天生就知道并非每个黑客都是门卫。在取得门卫的头衔前需要具备特定的资历和成就。这很难度量，但是每个黑客在看到它的时候就能知道。</p>
<hr>
<div id="hack2"><b>Q: 你能教我做黑客吗？</b></div>
<p>A: 自从第一次发布这份文档，我每周都会收到一些请求，（通常一天几封）要我“教会他们做黑客”。遗憾的是，我没有时间和精力来做这个；我自己的黑客项目，及我作为一个开放源代码倡导者 的四处奔波已经占用了我110%的时间。</p>
<p>即便我想教你，黑客也依然基本上是一项自行修炼的的态度和技术。当真正的黑客想帮助你的时候，如果你乞求他们一汤匙一汤匙“喂”你的话，你会发现他们不会尊重你。</p>
<p>先去学一些东西。显示你在尝试，你能靠自己去学习。然后再去向你遇到的黑客请教特殊的问题。</p>
<p>如果你发E-mail给一位黑客寻求他的帮助，有两件首要记住的事情。第一，写出来的文字显得懒且粗心的人通常非常懒于思考且非常马大哈，不能成为好黑客——因此注意拼写正确，使用正确的语法及发音，否则你可能会无人理睬。 第二，不要试图要求回复到与你的发信地址不同的另一个帐号。这样做的人一般是使用盗用帐号，不会有人有兴趣为虎作伥帮助窃贼的。</p>
<hr>
<div id="hack3"><b>Q: 我该如何开始           </b></div>
<p>A: 对你而言最佳的入门方式也许是去参加LUG（Linux用户组）的聚会。 你可以在 <a href="http://www.tldp.org/links/index.html" target="_blank" rel="noreferrer">LDP的综合Linux信息页面</a>上找到类似的组织；也许有一个在你附近的，而且非常有可能与一所大学或学校挂钩。如果你提出要求，LUG 成员兴许会给你一套 Linux，当然此后会帮你安装并带你入门。</p>
<p>下一步（如果你在附近找不到LUG的话，这是第一步）找一个你感兴趣的开放源代码项目。读它的代码，并且检查它的bug。学着做贡献，并从此入门。</p>
<p>入门的唯一方式是提升你的技能。如果你还想问我关于如何开始的私人建议，我还是会给你相同的答案，因为没有捷径。我还会在心里认为你可能是个失败者——因为你没有耐性读完这个 FAQ，并且也没有足够的智商从文中理解到入门的唯一途径就是提升你的技能。你没救了。</p>
<hr>
<div id="hack4"><b>Q: 我该什么时候开始学？现在会不会太迟了？</b></div>
<p>A: 你有动力学的时候就可以。多数人是在15到20岁之间开始感兴趣的，但据我所知也有在这个年龄区间之外的例外。</p>
<hr>
<div id="hack5"><b>Q: 学会黑客之道要多长时间？</b></div>
<p>A: 这取决于你的聪明程度和努力程度。多数人如果足够专注的话，能在18个月到2年之间学会一套令人尊敬的技能。但是，不要以为这就结束了。在黑客领域（在其他很多领域也一样），需要10年时间精湛技艺。如果你是一个真正的黑客，你要用你的余生来学习和完善你的技术。</p>
<hr>
<div id="hack6"><b>Q: Visual Basic是一门好的入门语言吗？</b></div>
<p>A: 你问这个问题，那通常意味着你想在Microsoft Windows下从事黑客活动。这本身就不是个好主意。我将在Windows下学习黑客技巧比喻为戴着脚镣学跳舞，这不是开玩笑。别这么做。Windows很糟糕，而且它从来没有变好一点。</p>
<p>Visual Basic有一个很重要的问题，主要是源于它不可移植。虽然已经有Visual Basic的开源实现，但ECMA的可执行标准只覆盖了其编程接口的很小一部分。在Windows中，大多数函数库是由单一供应商（Microsoft）专有的。如果你不能非常小心的选择你所使用的特性（比任何新手所能做到的都更小心），你最终很可能被束缚在Microsoft决定支持的那些平台上。如果你从Unix系统开始，有更好的编程语言和更好的函数库可用。例如Python。</p>
<p>此外，如同其他 Basic 语言一样，Visual Basic是一种设计糟糕的语言，它会教给你坏的编程习惯。别让我详细列举和解释它们，这够写一本书了。找一门设计优良的编程语言来学。</p>
<p>坏习惯之一就是依赖单一厂商提供的函数库、控件和开发工具。通常，一门不能支持至少Linux或一种BSD，或其他第三方操作系统的语言，都不适合应付黑客工作。</p>
<hr>
<div id="hack7"><b>Q: 你能帮我“黑”掉一个网站，或者教我怎么黑它吗？</b></div>
<p>A: No。任何读完这份FAQ后还问这个问题的人都是无药可救的蠢材，即使有时间我也不会理睬。任何发给我的此类e-mail都会被忽略掉或被痛骂一顿。</p>
<hr>
<div id="hack8"><b>Q: 我怎么样才能得到别人帐号的密码？</b></div>
<p>A: 这是破坏行为。滚开，白痴。</p>
<hr>
<div id="hack9"><b>Q: 我如何入侵/查看/监视别人的email？</b></div>
<p>A: 这是破坏行为。从我面前消失，混蛋。</p>
<hr>
<div id="hack10"><b>Q: 我如何才能盗取IRC的频道管理员权限？</b></div>
<p>A: 这是破坏行为。去死，蠢货。</p>
<hr>
<div id="hack11"><b>Q: 我被人入侵了。你能帮我避免以后再被攻击吗？</b></div>
<p>A: 不能。每次问我这个问题的都是些运行Microsoft Windows的菜鸟。不可能有效保护Windows系统免受破坏行为攻击。代码和架构上的大量缺陷使保护Windows的努力犹如隔靴搔痒。唯一可靠的预防是换到Linux或者其他设计得至少足够安全的系统上。</p>
<hr>
<div id="hack12"><b>Q: 我的Windows软件出现问题了。你能帮我吗？</b></div>
<p>A: 是的。进入DOS模式，然后输入“format c:”。你遇到的问题将在几分钟内消失。</p>
<hr>
<div id="hack13"><b>Q: 我在哪里可以找到能与之交流的真正的黑客？</b></div>
<p>A: 最佳办法是在你附近找一个Unix或Linux的用户组，参加他们的聚会（你可以在ibiblio的<a href="#">LDP</a>站点找到一些指向用户组的链接）。</p>
<p>我过去曾说过在IRC上找不到真正的黑客，但我发觉现在情况有所改变。显然一些真正的黑客的社区像GIMP及Perl，也有IRC频道了。）</p>
<hr>
<div id="hack14"><b>Q: 你能推荐一些有关黑客的好书吗？</b></div>
<p>A: 我维护着一份<a href="http://en.tldp.org/HOWTO/Reading-List-HOWTO/index.html" target="_blank" rel="noreferrer">Linux Reading List HOWTO</a>，也许会对你有用。<a href="http://catb.org/~esr/faqs/loginataka.html" target="_blank" rel="noreferrer">Loginataka</a>也很有意思。</p>
<p>关于Python的介绍，请访问Python官方站点上的<a href="http://docs.python.org/tutorial/index.html" target="_blank" rel="noreferrer">入门资料</a></p>
<hr>
<div id="hack15"><b>Q: 成为一名黑客我需要擅长数学吗？</b></div>
<p>A: 不。黑客倒很少使用常规的数学或算术。 尤其是你不会用到三角学、微积分或数学分析（在特定领域，这些学科很有用，例如3D电脑图像）。一些有限数学（包括布尔代数，集合论，组合数学，图论）的背景知识会有帮助。了解一些系统的逻辑和布尔代数是有好处的。一些基础的离散数学（包括有限集合论、组合数学和图论）会有帮助。</p>
<p>更重要的是：你需要能够像数学家一样进行逻辑性地思考和进行缜密的推理。在这一点上绝大部分数学理论帮不了你，你需要有能够应付数学的修养和智力。如果你不够聪明，你成为黑客的希望很渺茫。如果你的修养不够，最好培养起来。</p>
<p>我认为一个好的了解你当前状况的办法是，找一本Rymond Smullyan的书 <em>What Is The Name Of This Book?</em>。Smullyan那些有趣的逻辑题很符合黑客精神。如果你能解答它们，这是个很好的信号。如果你能享受解题的过程那就更好了。</p>
<hr>
<div id="hack16"><b>Q: 我该从哪种语言开始学？</b></div>
<p>A: XHTML（最新的HTML方言）——如果你还不懂的话。市面上有一大堆的封面精美，宣传得天花乱坠的 糟糕的HTML书籍，不幸的是很少有好的。我最喜欢的是<a href="http://www.oreilly.com/catalog/html5/" target="_blank" rel="noreferrer">HTML: The Definitive Guide</a>。</p>
<p>但HTML不完全是一种编程语言。当你准备开始编程时，我推荐从Python起步。 你会听到一大群人推荐Perl，并且Perl依然比Python流行得多，但是难学得多且（以我之见）设计得不是很好。</p>
<p>C确实重要，但它要比Python或Perl难多了。不要尝试先学C。</p>
<p>Windows用户不要满足于Visual Basic。它会教给你坏习惯，而且它不可以移植，只能在Windows下运行。避免它。</p>
<hr>
<div id="hack17"><b>Q: 我需要什么样的机器配置？</b></div>
<p>A: 过去个人电脑计算能力相当不够且内存小，给黑客的学习过程设置了人为的障碍。不过从1990年代以后就不是这样了，任何配置比一台Intel 486DX50好的机器都有足够的能力进行开发工作，跑Xorg，及进行Internet通讯，同时现在能买到的最小的磁盘都已经绰绰有余。</p>
<p>选择用来学习的机器时重要的一点是注意配件是否是Linux兼容的（或BSD兼容，如果你选择学 BSD）。同刚才提到的一样，大多数现在的机器都是符合的；唯一的值得注意的地方在于 调制解调器和打印机；有些具备为Windows设计的配件的机器不会在Linux下工作。</p>
<p>关于硬件兼容性有一个FAQ；最新版本在<a href="http://en.tldp.org/HOWTO/Hardware-HOWTO/index.html" target="_blank" rel="noreferrer">这里</a>。</p>
<hr>
<div id="hack18"><b>Q: 我想做贡献。你能帮我挑选一个问题来处理吗？</b></div>
<p>A: 不行。因为我不知道你擅长什么，也不知道你对什么感兴趣。你需要做到自我驱动，否则无法进步。这也是为什么让别人帮你挑选方向几乎都不会有用。</p>
<hr>
<div id="hack19"><b>Q: 我得因此憎恨和反对Microsoft吗？</b></div>
<p>A: 不，你不必如此。不是因为Microsoft不令人讨厌，而是因为黑客文化早在Microsoft出现之前就存在了，且将在Microsoft成为历史后依然存在。你耗费在憎恨Microsoft的任何力气不如花在热爱你的技术上。写好的代码——那会相当有效地打击Microsoft又不会让你得到恶报。</p>
<hr>
<div id="hack20"><b>Q: 但开放源代码软件不会使程序员丢饭碗吗？</b></div>
<p>A: 看起来不太可能——目前为止，开放源代码软件产业似乎创造了更多的就业机会而不是减少就业机会。如果写一个程序比起不写来是纯经济收益的话，那么在写完后，程序员应该得到报酬不管程序是否是开放源代码。并且，无论写出多么“免费自由”的软件，都存在更多对新的，定制的软件的需求。我有这方面更多的论述，放在<a href="#">Open Source</a>网站资料中。</p>
<hr>
<div id="hack21"><b>Q: 哪里有免费的Unix？</b></div>
<p>A: 如果你的机器上还没有安装Unix，我在本文的其他地方已经指出了从哪里可以获取到常用的免费Unix。作为一名黑客，你需要自立自强，以及自学能力。现在开始吧……</p>
]]></content>
        <author>
            <name>duyl328</name>
            <uri>https://seyl.me/about</uri>
        </author>
        <category label="转载"/>
        <category label="思考"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[提问的智慧]]></title>
        <id>https://seyl.me/posts/2025/04/how-to-ask-questions-the-smart-way</id>
        <link href="https://seyl.me/posts/2025/04/how-to-ask-questions-the-smart-way"/>
        <updated>2025-04-10T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[<h1 id="frontmatter-title-转载" tabindex="-1">{{ $frontmatter.title }}(转载) <a class="header-anchor" href="#frontmatter-title-转载" aria-label="Permalink to &quot;{{ $frontmatter.title }}(转载)&quot;">&ZeroWidthSpace;</a></h1>
<div class="warning custom-block github-alert"><p class="custom-block-title">版权声明</p>
<p>Copyright © 2001, 2006, 2014 Eric S. Raymond, Rick Moen <br/>
本指南英文版版權為 Eric S. Raymond, Rick Moen 所有。<br/>
原文網址 (Translated from)：<a href="http://www.catb.org/~esr/faqs/smart-questions.html" target="_blank" rel="noreferrer">http://www.catb.org/~esr/faqs/smart-questions.html</a><br/>
Copyleft 2001 by D.H.Grand(nOBODY/Ginux), 2010 by Gasolin, 2015-present by <a href="https://github.com/ryanhanwu" target="_blank" rel="noreferrer">Ryan Wu</a></p>
</div>
<blockquote>
<p>✒️ 文章摘要</p>
</blockquote>
<!-- DESC SEP -->
<p>本文章旨在教读者如何有效、聪明地提出技术问题，以提高获得有用答案的概率。文章强调在提问前应尽可能自行搜索、阅读文档和尝试解决问题，并在提问时表达清晰、尊重他人、避免含糊和懒惰。作者还指出应在合适的论坛提问、使用明确的标题、准确描述问题经过和现象，并在问题解决后分享经验。<br/>
本文不仅适用于技术社区，也为所有希望提高提问效率的人提供了实用的建议。</p>
<!-- DESC SEP -->
<h2 id="简介" tabindex="-1">简介 <a class="header-anchor" href="#简介" aria-label="Permalink to &quot;简介&quot;">&ZeroWidthSpace;</a></h2>
<p>在<a href="http://www.catb.org/~esr/faqs/hacker-howto.html" target="_blank" rel="noreferrer">黑客</a>的世界里，你所提技术问题的解答的好坏, 很大程度上取决于你提问的方式与此问题的难度。本指南将教你如何正确地提问以获得你满意的答案。</p>
<p>现在开源（Open Source）软件已经相当盛行，您通常可以从其他更有经验的用户那里获得与黑客一样好的答案，这是件<strong>好事</strong>；和黑客相比，用户们往往对那些新手常遇到的问题更宽容一些。尽管如此，以我们在此推荐的方式对待这些有经验的用户通常也是从他们那里获得有用答案的最有效方式。</p>
<p>首先你应该明白，黑客们喜爱有挑战性的问题，或者能激发他们思维的好问题。如果我们并非如此，那我们也不会成为你想询问的对象。如果你给了我们一个值得反复咀嚼玩味的好问题，我们自会对你感激不尽。好问题是激励，是厚礼。好问题可以提高我们的理解力，而且通常会暴露我们以前从没意识到或者思考过的问题。对黑客而言，“好问题！”是诚挚的大力称赞。</p>
<p>尽管如此，黑客们有着蔑视或傲慢面对简单问题的坏名声，这有时让我们看起来对新手、无知者似乎较有敌意，但其实不是那样的。</p>
<p>我们不讳言我们对那些不愿思考、或者在发问前不做他们该做的事的人的蔑视。那些人是时间杀手 —— 他们只想索取，从不付出，消耗我们可用在更有趣的问题或更值得回答的人身上的时间。我们称这样的人为 <code>失败者（loser）</code> （由于历史原因，我们有时把它拼作 <code>lusers</code>）。</p>
<p>我们意识到许多人只是想使用我们写的软件，他们对学习技术细节没有兴趣。对大多数人而言，电脑只是种工具，是种达到目的的手段而已。他们有自己的生活并且有更要紧的事要做。我们认可这点，也从不指望每个人都对这些让我们着迷的技术问题感兴趣。尽管如此，我们只为那些真正有兴趣并愿意积极参与问题解决的人调整回答问题的风格。这点不会变，也不该变：否则，我们就是在最擅长的事情上降低效率。</p>
<p>我们（在很大程度上）是自愿的，从繁忙的生活中抽出时间来解答疑惑，而且时常被提问淹没。所以我们无情地滤掉一些话题，特别是拋弃那些看起来像失败者的家伙，以便更高效地利用时间来回答<code>赢家（winner）</code>的问题。</p>
<p>如果你厌恶我们的态度，高高在上，或过于傲慢，不妨也设身处地想想。我们并没有要求你向我们屈服 —— 事实上，我们大多数人非常乐意与你平等地交流，只要你付出小小努力来满足基本要求，我们就会欢迎你加入我们的文化。但让我们帮助那些不愿意帮助自己的人是没有效率的。无知没有关系，但装白痴就是不行。</p>
<p>所以，你不必在技术上很在行才能吸引我们的注意，但你必须表现出能引导你变得在行的特质 —— 机敏、有想法、善于观察、乐于主动参与解决问题。如果你做不到这些使你与众不同的事情，我们建议你花点钱找家商业公司签个技术支持服务合同，而不是要求黑客个人无偿地帮助你。</p>
<p>如果你决定向我们求助，当然你也不希望被视为失败者，更不愿成为失败者中的一员。能立刻得到快速并有效答案的最好方法，就是像赢家那样提问 —— 聪明、自信、有解决问题的思路，只是偶尔在特定的问题上需要获得一点帮助。</p>
<h2 id="在提问之前" tabindex="-1">在提问之前 <a class="header-anchor" href="#在提问之前" aria-label="Permalink to &quot;在提问之前&quot;">&ZeroWidthSpace;</a></h2>
<p>在你准备要通过电子邮件、新闻群组或者聊天室提出技术问题前，请先做到以下事情：</p>
<ol>
<li>尝试在你准备提问的论坛的旧文章中搜索答案。</li>
<li>尝试上网搜索以找到答案。</li>
<li>尝试阅读手册以找到答案。</li>
<li>尝试阅读常见问题文件（FAQ）以找到答案。</li>
<li>尝试自己检查或试验以找到答案。</li>
<li>向你身边的强者朋友打听以找到答案。</li>
<li>如果你是程序开发者，请尝试阅读源代码以找到答案。</li>
</ol>
<p>当你提出问题的时候，请先表明你已经做了上述的努力；这将有助于树立你并不是一个不劳而获且浪费别人的时间的提问者。如果你能一并表达在做了上述努力的过程中所<strong>学到</strong>的东西会更好，因为我们更乐于回答那些表现出能从答案中学习的人的问题。</p>
<p>运用某些策略，比如先用 Google 搜索你所遇到的各种错误信息（搜索 <a href="http://groups.google.com/" target="_blank" rel="noreferrer">Google 论坛</a>和网页），这样很可能直接就找到了能解决问题的文件或邮件列表线索。即使没有结果，在邮件列表或新闻组寻求帮助时加上一句 <code>我在 Google 中搜过下列句子但没有找到什么有用的东西</code> 也是件好事，即使它只是表明了搜索引擎不能提供哪些帮助。这么做（加上搜索过的字串）也让遇到相似问题的其他人能被搜索引擎引导到你的提问来。</p>
<p>别着急，不要指望几秒钟的 Google 搜索就能解决一个复杂的问题。在向专家求助之前，再阅读一下常见问题文件（FAQ）、放轻松、坐得舒服一些，再花点时间思考一下这个问题。相信我们，他们能从你的提问看出你做了多少阅读与思考，如果你是有备而来，将更有可能得到解答。不要将所有问题一股脑拋出，只因你的第一次搜索没有找到答案（或者找到太多答案）。</p>
<p>准备好你的问题，再将问题仔细地思考过一遍，因为草率的发问只能得到草率的回答，或者根本得不到任何答案。越是能表现出在寻求帮助前你为解决问题所付出的努力，你越有可能得到实质性的帮助。</p>
<p>小心别问错了问题。如果你的问题基于错误的假设，某个普通黑客（J. Random Hacker）多半会一边在心里想着<code>蠢问题…</code>，一边用无意义的字面解释来答复你，希望着你会从问题的回答（而非你想得到的答案）中汲取教训。</p>
<p>绝不要自以为<strong>够格</strong>得到答案，你没有；你并没有。毕竟你没有为这种服务支付任何报酬。你将会是自己去<strong>挣到</strong>一个答案，靠提出有内涵的、有趣的、有思维激励作用的问题 —— 一个有潜力能贡献社区经验的问题，而不仅仅是被动地从他人处索取知识。</p>
<p>另一方面，表明你愿意在找答案的过程中做点什么是一个非常好的开端。<code>谁能给点提示？</code>、<code>我的这个例子里缺了什么？</code>以及<code>我应该检查什么地方</code>比<code>请把我需要的确切的过程贴出来</code>更容易得到答复。因为你表现出只要有人能指个正确方向，你就有完成它的能力和决心。</p>
<h2 id="当你提问时" tabindex="-1">当你提问时 <a class="header-anchor" href="#当你提问时" aria-label="Permalink to &quot;当你提问时&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="慎选提问的论坛" tabindex="-1">慎选提问的论坛 <a class="header-anchor" href="#慎选提问的论坛" aria-label="Permalink to &quot;慎选提问的论坛&quot;">&ZeroWidthSpace;</a></h3>
<p>小心选择你要提问的场合。如果你做了下述的事情，你很可能被忽略掉或者被看作失败者：</p>
<ul>
<li>在与主题不合的论坛上贴出你的问题。</li>
<li>在探讨进阶技术问题的论坛张贴非常初级的问题；反之亦然。</li>
<li>在太多的不同新闻群组上重复转贴同样的问题（cross-post）。</li>
<li>向既非熟人也没有义务解决你问题的人发送私人电邮。</li>
</ul>
<p>黑客会剔除掉那些搞错场合的问题，以保护他们沟通的渠道不被无关的东西淹没。你不会想让这种事发生在自己身上的。</p>
<p>因此，第一步是找到对的论坛。再说一次，Google 和其它搜索引擎还是你的朋友，用它们来找到与你遭遇到困难的软硬件问题最相关的网站。通常那儿都有常见问题（FAQ）、邮件列表及相关说明文件的链接。如果你的努力（包括<strong>阅读</strong> FAQ）都没有结果，网站上也许还有报告 Bug（Bug-reporting）的流程或链接，如果是这样，链过去看看。</p>
<p>向陌生的人或论坛发送邮件最可能是风险最大的事情。举例来说，别假设一个提供丰富内容的网页的作者会想充当你的免费顾问。不要对你的问题是否会受到欢迎做太乐观的估计 —— 如果你不确定，那就向别处发送，或者压根别发。</p>
<p>在选择论坛、新闻群组或邮件列表时，别太相信它的名字，先看看 FAQ 或者许可书以弄清楚你的问题是否切题。发文前先翻翻已有的话题，这样可以让你感受一下那里的文化。事实上，事先在新闻组或邮件列表的历史记录中搜索与你问题相关的关键词是个极好的主意，也许这样就找到答案了。即使没有，也能帮助你归纳出更好的问题。</p>
<p>别像机关枪似的一次“扫射”所有的帮助渠道，这就像大喊大叫一样会使人不快。要一个一个地来。</p>
<p>搞清楚你的主题！最典型的错误之一是在某种致力于跨平台可移植的语言、套件或工具的论坛中提关于 Unix 或 Windows 操作系统程序界面的问题。如果你不明白为什么这是大错，最好在搞清楚这之间差异之前什么也别问。</p>
<p>一般来说，在仔细挑选的公共论坛中提问，会比在私有论坛中提同样的问题更容易得到有用的回答。有几个理由可以支持这点，一是看潜在的回复者有多少，二是看观众有多少。黑客较愿意回答那些能帮助到许多人的问题。</p>
<p>可以理解的是，老练的黑客和一些热门软件的作者正在接受过多的错发信息。就像那根最后压垮骆驼背的稻草一样，你的加入也有可能使情况走向极端 —— 已经好几次了，一些热门软件的作者由于涌入其私人邮箱的大量不堪忍受的无用邮件而不再提供支持。</p>
<h3 id="stack-overflow" tabindex="-1">Stack Overflow <a class="header-anchor" href="#stack-overflow" aria-label="Permalink to &quot;Stack Overflow&quot;">&ZeroWidthSpace;</a></h3>
<p>搜索，_然后_在 Stack Exchange 问。</p>
<p>近年来，Stack Exchange 社区已经成为回答技术及其他问题的主要渠道，尤其是那些开放源码的项目。</p>
<p>因为 Google 索引是即时的，在看 Stack Exchange 之前先在 Google 搜索。有很高的几率某人已经问了一个类似的问题，而且 Stack Exchange 网站们往往会是搜索结果中最前面几个。如果你在 Google 上没有找到任何答案，你再到特定相关主题的网站去找。用标签（Tag）搜索能让你更缩小你的搜索结果。</p>
<p>如果你还是找不到任何对你的问题有用的内容，请把你的问题发在与它最相关的网站上。提问的时候请善用格式化工具，尤其注意为代码添加格式，并且添加相关的标签（特别是编程语言、操作系统或库/包的名称）。当有人要求你提供更多相关信息时，请编辑你的贴子来补充它们[译注：而不是发一个回帖或回答！]。如果你觉得一个答案对你有帮助，点击向上的箭头来为它投票；如果一个答案提供了问题的正确解决方案，点击投票按钮下方的对勾来将它标记为正解。</p>
<p>Stack Exchange 已经成长到<a href="https://stackexchange.com/sites" target="_blank" rel="noreferrer">超过一百个网站</a>，以下是最常用的几个站：</p>
<ul>
<li>Super User 是问一些通用的电脑问题，如果你的问题跟代码或是写程序无关，只是一些网络连线之类的，请到这里。</li>
<li>Stack Overflow 是问写程序有关的问题。</li>
<li>Server Fault 是问服务器和网管相关的问题。</li>
</ul>
<h3 id="网站和-irc-论坛" tabindex="-1">网站和 IRC 论坛 <a class="header-anchor" href="#网站和-irc-论坛" aria-label="Permalink to &quot;网站和 IRC 论坛&quot;">&ZeroWidthSpace;</a></h3>
<p>本地的用户群组（user group），或者你所用的 Linux 发行版本也许正在宣传他们的网页论坛或 IRC 频道，并提供新手帮助（在一些非英语国家，新手论坛很可能还是邮件列表），这些都是开始提问的好地方，特别是当你觉得遇到的也许只是相对简单或者很普通的问题时。有广告赞助的 IRC 频道是公开欢迎提问的地方，通常可以即时得到回应。</p>
<p>事实上，如果程序出的问题只发生在特定 Linux 发行版提供的版本（这很常见），最好先去该发行版的论坛或邮件列表中提问，再到程序本身的论坛或邮件列表提问。（否则）该项目的黑客可能仅仅回复“使用<strong>我们的</strong>版本”。</p>
<p>在任何论坛发文以前，先确认一下有没有搜索功能。如果有，就试着搜索一下问题的几个关键词，也许这会有帮助。如果在此之前你已做过通用的网页搜索（你也该这样做），还是再搜索一下论坛，搜索引擎有可能没来得及索引此论坛的全部内容。</p>
<p>通过论坛或 IRC 频道来提供用户支持服务有增长的趋势，电子邮件则大多为项目开发者间的交流而保留。所以最好先在论坛或 IRC 中寻求与该项目相关的协助。</p>
<p>在使用 IRC 的时候，首先最好不要发布很长的问题描述，有些人称之为频道洪水。最好通过一句话的问题描述来开始聊天。</p>
<h3 id="第二步-使用项目邮件列表" tabindex="-1">第二步，使用项目邮件列表 <a class="header-anchor" href="#第二步-使用项目邮件列表" aria-label="Permalink to &quot;第二步，使用项目邮件列表&quot;">&ZeroWidthSpace;</a></h3>
<p>当某个项目提供开发者邮件列表时，要向列表而不是其中的个别成员提问，即使你确信他能最好地回答你的问题。查一查项目的文件和首页，找到项目的邮件列表并使用它。有几个很好的理由支持我们采用这种办法：</p>
<ul>
<li>任何好到需要向个别开发者提出的问题，也将对整个项目群组有益。反之，如果你认为自己的问题对整个项目群组来说太愚蠢，那这也不能成为骚扰个别开发者的理由。</li>
<li>向列表提问可以分散开发者的负担，个别开发者（尤其是项目领导人）也许太忙以至于没法回答你的问题。</li>
<li>大多数邮件列表都会被存档，那些被存档的内容将被搜索引擎索引。如果你向列表提问并得到解答，将来其他人可以通过网页搜索找到你的问题和答案，也就不用再次发问了。</li>
<li>如果某些问题经常被问到，开发者可以利用此信息来改进说明文件或软件本身，以使其更清楚。如果只是私下提问，就没有人能看到最常见问题的完整场景。</li>
</ul>
<p>如果一个项目既有“用户”也有“开发者”（或“黑客”）邮件列表或论坛，而你又不会动到那些源代码，那么就向“用户”列表或论坛提问。不要假设自己会在开发者列表中受到欢迎，那些人多半会将你的提问视为干扰他们开发的噪音。</p>
<p>然而，如果你<strong>确信</strong>你的问题很特别，而且在“用户”列表或论坛中几天都没有回复，可以试试前往“开发者”列表或论坛发问。建议你在张贴前最好先暗地里观察几天以了解那里的行事方式（事实上这是参与任何私有或半私有列表的好主意）</p>
<p>如果你找不到一个项目的邮件列表，而只能查到项目维护者的电子邮件地址，尽管向他发信。即使是在这种情况下，也别假设（项目）邮件列表不存在。在你的电子邮件中，请陈述你已经试过但没有找到合适的邮件列表，也提及你不反对将自己的邮件转发给他人（许多人认为，即使没什么秘密，私人电子邮件也不应该被公开。通过允许将你的电子邮件转发他人，你给了相应人员处置你邮件的选择）。</p>
<h3 id="使用有意义且描述明确的标题" tabindex="-1">使用有意义且描述明确的标题 <a class="header-anchor" href="#使用有意义且描述明确的标题" aria-label="Permalink to &quot;使用有意义且描述明确的标题&quot;">&ZeroWidthSpace;</a></h3>
<p>在邮件列表、新闻群组或论坛中，大约 50 字以内的标题是抓住资深专家注意力的好机会。别用喋喋不休的<code>帮帮忙</code>、<code>跪求</code>、<code>急</code>（更别说<code>救命啊！！！！</code>这样让人反感的话，用这种标题会被条件反射式地忽略）来浪费这个机会。不要妄想用你的痛苦程度来打动我们，而应该是在这点空间中使用极简单扼要的描述方式来提出问题。</p>
<p>一个好标题范例是<code>目标 —— 差异</code>式的描述，许多技术支持组织就是这样做的。在<code>目标</code>部分指出是哪一个或哪一组东西有问题，在<code>差异</code>部分则描述与期望的行为不一致的地方。</p>
<blockquote>
<p>蠢问题：救命啊！我的笔记本电脑不能正常显示了！</p>
</blockquote>
<blockquote>
<p>聪明问题：X.org 6.8.1 的鼠标指针会变形，某牌显卡 MV1005 芯片组。</p>
</blockquote>
<blockquote>
<p>更聪明问题：X.org 6.8.1 的鼠标指针，在某牌显卡 MV1005 芯片组环境下 - 会变形。</p>
</blockquote>
<p>编写<code>目标 —— 差异</code> 式描述的过程有助于你组织对问题的细致思考。是什么被影响了？ 仅仅是鼠标指针或者还有其它图形？只在 X.org 的 X 版中出现？或只是出现在 6.8.1 版中？ 是针对某牌显卡芯片组？或者只是其中的 MV1005 型号？ 一个黑客只需瞄一眼就能够立即明白你的环境<strong>和</strong>你遇到的问题。</p>
<p>总而言之，请想像一下你正在一个只显示标题的存档讨论串（Thread）索引中查寻。让你的标题更好地反映问题，可使下一个搜索类似问题的人能够关注这个讨论串，而不用再次提问相同的问题。</p>
<p>如果你想在回复中提出问题，记得要修改内容标题，以表明你是在问一个问题， 一个看起来像 <code>Re: 测试</code> 或者 <code>Re: 新 bug</code> 的标题很难引起足够重视。另外，在不影响连贯性之下，适当引用并删减前文的内容，能给新来的读者留下线索。</p>
<p>对于讨论串，不要直接点击回复来开始一个全新的讨论串，这将限制你的观众。因为有些邮件阅读程序，比如 mutt ，允许用户按讨论串排序并通过折叠讨论串来隐藏消息，这样做的人永远看不到你发的消息。</p>
<p>仅仅改变标题还不够。mutt 和其它一些邮件阅读程序还会检查邮件标题以外的其它信息，以便为其指定讨论串。所以宁可发一个全新的邮件。</p>
<p>在网页论坛上，好的提问方式稍有不同，因为讨论串与特定的信息紧密结合，并且通常在讨论串外就看不到里面的内容，故通过回复提问，而非改变标题是可接受的。不是所有论坛都允许在回复中出现分离的标题，而且这样做了基本上没有人会去看。不过，通过回复提问，这本身就是暧昧的做法，因为它们只会被正在查看该标题的人读到。所以，除非你<strong>只想</strong>在该讨论串当前活跃的人群中提问，不然还是另起炉灶比较好。</p>
<h3 id="使问题容易回复" tabindex="-1">使问题容易回复 <a class="header-anchor" href="#使问题容易回复" aria-label="Permalink to &quot;使问题容易回复&quot;">&ZeroWidthSpace;</a></h3>
<p>以<code>请将你的回复发送到……</code>来结束你的问题多半会使你得不到回答。如果你觉得花几秒钟在邮件客户端设置一下回复地址都麻烦，我们也觉得花几秒钟思考你的问题更麻烦。如果你的邮件程序不支持这样做，<a href="http://linuxmafia.com/faq/Mail/muas.html" target="_blank" rel="noreferrer">换个好点的</a>；如果是操作系统不支持这种邮件程序，也换个好点的。</p>
<p>在论坛，要求通过电子邮件回复是非常无礼的，除非你认为回复的信息可能比较敏感（有人会为了某些未知的原因，只让你而不是整个论坛知道答案）。如果你只是想在有人回复讨论串时得到电子邮件提醒，可以要求网页论坛发送给你。几乎所有论坛都支持诸如<code>追踪此讨论串</code>、<code>有回复时发送邮件提醒</code>等功能。</p>
<h3 id="使用清晰、正确、精准且合乎语法的语句" tabindex="-1">使用清晰、正确、精准且合乎语法的语句 <a class="header-anchor" href="#使用清晰、正确、精准且合乎语法的语句" aria-label="Permalink to &quot;使用清晰、正确、精准且合乎语法的语句&quot;">&ZeroWidthSpace;</a></h3>
<p>我们从经验中发现，粗心的提问者通常也会粗心地写程序与思考（我敢打包票）。回答粗心大意者的问题很不值得，我们宁愿把时间耗在别处。</p>
<p>正确的拼写、标点符号和大小写是很重要的。一般来说，如果你觉得这样做很麻烦，不想在乎这些，那我们也觉得麻烦，不想在乎你的提问。花点额外的精力斟酌一下字句，用不着太僵硬与正式 —— 事实上，黑客文化很看重能准确地使用非正式、俚语和幽默的语句。但它<strong>必须很</strong>准确，而且有迹象表明你是在思考和关注问题。</p>
<p>正确地拼写、使用标点和大小写，不要将<code>its</code>混淆为<code>it's</code>，<code>loose</code>搞成<code>lose</code>或者将<code>discrete</code>弄成<code>discreet</code>。不要<strong>全部用大写</strong>，这会被视为无礼的大声嚷嚷（全部小写也好不到哪去，因为不易阅读。<a href="http://en.wikipedia.org/wiki/Alan_Cox" target="_blank" rel="noreferrer">Alan Cox</a> 也许可以这样做，但你不行）。</p>
<p>更白话的说，如果你写得像是个半文盲[译注：<a href="http://zh.wikipedia.org/wiki/%E5%B0%8F%E7%99%BD" target="_blank" rel="noreferrer">小白</a>]，那多半得不到理睬。也不要使用即时通信中的简写或<a href="http://zh.wikipedia.org/wiki/%E7%81%AB%E6%98%9F%E6%96%87" target="_blank" rel="noreferrer">火星文</a>，如将<code>的</code>简化为<code>d</code>会使你看起来像一个为了少打几个键而省字的小白。更糟的是，如果像个小孩似地鬼画符那绝对是在找死，可以肯定没人会理你（或者最多是给你一大堆指责与挖苦）。</p>
<p>如果在使用非母语的论坛提问，你可以犯点拼写和语法上的小错，但决不能在思考上马虎（没错，我们通常能弄清两者的分别）。同时，除非你知道回复者使用的语言，否则请使用英语书写。繁忙的黑客一般会直接删除用他们看不懂的语言写的消息。在网络上英语是通用语言，用英语书写可以将你的问题在尚未被阅读就被直接删除的可能性降到最低。</p>
<p>如果英文是你的外语（Second language），提示潜在回复者你有潜在的语言困难是很好的： [译注：以下附上原文以供使用]</p>
<blockquote>
<p>English is not my native language; please excuse typing errors.</p>
</blockquote>
<ul>
<li>英文不是我的母语，请原谅我的错字或语法。</li>
</ul>
<blockquote>
<p>If you speak $LANGUAGE, please email/PM me; I may need assistance translating my question.</p>
</blockquote>
<ul>
<li>如果你说<strong>某语言</strong>，请向我发电邮/私信；</li>
<li>我需要有人协助我翻译我的问题。</li>
</ul>
<blockquote>
<p>I am familiar with the technical terms, but some slang expressions and idioms are difficult for me.</p>
</blockquote>
<ul>
<li>我对技术名词很熟悉，但对于俗语或是特别用法不甚了解。</li>
</ul>
<blockquote>
<p>I've posted my question in $LANGUAGE and English. I'll be glad to translate responses, if you only use one or the other.</p>
</blockquote>
<ul>
<li>我把我的问题用<strong>某语言</strong>和英文写出来。</li>
<li>如果你只用其中的一种语言回答，我会乐意将回复翻译成为你使用的语言。</li>
</ul>
<h3 id="使用易于读取且标准的文件格式发送问题" tabindex="-1">使用易于读取且标准的文件格式发送问题 <a class="header-anchor" href="#使用易于读取且标准的文件格式发送问题" aria-label="Permalink to &quot;使用易于读取且标准的文件格式发送问题&quot;">&ZeroWidthSpace;</a></h3>
<p>如果你人为地将问题搞得难以阅读，它多半会被忽略，人们更愿读易懂的问题，所以：</p>
<ul>
<li>使用纯文字而不是 HTML (<a href="http://archive.birdhouse.org/etc/evilmail.html" target="_blank" rel="noreferrer">关闭 HTML</a> 并不难）。</li>
<li>使用 MIME 附件通常是可以的，前提是真正有内容（譬如附带的源代码或 patch），而不仅仅是邮件程序生成的模板（譬如只是信件内容的拷贝）。</li>
<li>不要发送一段文字只是一行句子但自动换行后会变成多行的邮件（这使得回复部分内容非常困难）。设想你的读者是在 80 个字符宽的终端机上阅读邮件，最好设置你的换行分割点小于 80 字。</li>
<li>但是，对一些特殊的文件<strong>不要</strong>设置固定宽度（譬如日志文件拷贝或会话记录）。数据应该原样包含，让回复者有信心他们看到的是和你看到的一样的东西。</li>
<li>在英语论坛中，不要使用<code>Quoted-Printable</code> MIME 编码发送消息。这种编码对于张贴非 ASCII 语言可能是必须的，但很多邮件程序并不支持这种编码。当它们处理换行时，那些文本中四处散布的<code>=20</code>符号既难看也分散注意力，甚至有可能破坏内容的语意。</li>
<li>绝对，<strong>永远</strong>不要指望黑客们阅读使用封闭格式编写的文档，像微软公司的 Word 或 Excel 文件等。大多数黑客对此的反应就像有人将还在冒热气的猪粪倒在你家门口时你的反应一样。即便他们能够处理，他们也很厌恶这么做。</li>
<li>如果你从使用 Windows 的电脑发送电子邮件，关闭微软愚蠢的<code>智能引号</code>功能 （从[选项] &gt; [校订] &gt; [自动校正选项]，勾选掉<code>智能引号</code>单选框），以免在你的邮件中到处散布垃圾字符。</li>
<li>在论坛，勿滥用<code>表情符号</code>和<code>HTML</code>功能（当它们提供时）。一两个表情符号通常没有问题，但花哨的彩色文本倾向于使人认为你是个无能之辈。过滥地使用表情符号、色彩和字体会使你看来像个傻笑的小姑娘。这通常不是个好主意，除非你只是对性而不是对答案感兴趣。</li>
</ul>
<p>如果你使用图形用户界面的邮件程序（如微软公司的 Outlook 或者其它类似的），注意它们的默认设置不一定满足这些要求。大多数这类程序有基于选单的<code>查看源代码</code>命令，用它来检查发送文件夹中的邮件，以确保发送的是纯文本文件同时没有一些奇怪的字符。</p>
<h3 id="精确地描述问题并言之有物" tabindex="-1">精确地描述问题并言之有物 <a class="header-anchor" href="#精确地描述问题并言之有物" aria-label="Permalink to &quot;精确地描述问题并言之有物&quot;">&ZeroWidthSpace;</a></h3>
<ul>
<li>仔细、清楚地描述你的问题或 Bug 的症状。</li>
<li>描述问题发生的环境（机器配置、操作系统、应用程序、以及相关的信息），提供经销商的发行版和版本号（如：<code>Fedora Core 4</code>、<code>Slackware 9.1</code>等）。</li>
<li>描述在提问前你是怎样去研究和理解这个问题的。</li>
<li>描述在提问前为确定问题而采取的诊断步骤。</li>
<li>描述最近做过什么可能相关的硬件或软件变更。</li>
<li>尽可能地提供一个可以<code>重现这个问题的可控环境</code>的方法。</li>
</ul>
<p>尽量去揣测一个黑客会怎样反问你，在你提问之前预先将黑客们可能提出的问题回答一遍。</p>
<p>以上几点中，当你报告的是你认为可能在代码中的问题时，给黑客一个可以重现你的问题的环境尤其重要。当你这么做时，你得到有效的回答的机会和速度都会大大的提升。</p>
<p><a href="http://www.chiark.greenend.org.uk/~sgtatham/" target="_blank" rel="noreferrer">Simon Tatham</a> 写过一篇名为《<a href="http://www.chiark.greenend.org.uk/~sgtatham/bugs-cn.html" target="_blank" rel="noreferrer">如何有效地报告Bug</a>》的出色文章。强力推荐你也读一读。</p>
<h3 id="话不在多而在精" tabindex="-1">话不在多而在精 <a class="header-anchor" href="#话不在多而在精" aria-label="Permalink to &quot;话不在多而在精&quot;">&ZeroWidthSpace;</a></h3>
<p>你需要提供精确有内容的信息。这并不是要求你简单的把成堆的出错代码或者资料完全转录到你的提问中。如果你有庞大而复杂的测试样例能重现程序挂掉的情境，尽量将它剪裁得越小越好。</p>
<p>这样做的用处至少有三点。 第一，表现出你为简化问题付出了努力，这可以使你得到回答的机会增加； 第二，简化问题使你更有可能得到<strong>有用</strong>的答案； 第三，在精炼你的 bug 报告的过程中，你很可能就自己找到了解决方法或权宜之计。</p>
<h3 id="别动辄声称找到-bug" tabindex="-1">别动辄声称找到 Bug <a class="header-anchor" href="#别动辄声称找到-bug" aria-label="Permalink to &quot;别动辄声称找到 Bug&quot;">&ZeroWidthSpace;</a></h3>
<p>当你在使用软件中遇到问题，除非你非常、<strong>非常</strong>的有根据，不要动辄声称找到了 Bug。提示：除非你能提供解决问题的源代码补丁，或者提供回归测试来表明前一版本中行为不正确，否则你都多半不够完全确信。这同样适用在网页和文件，如果你（声称）发现了文件的<code>Bug</code>，你应该能提供相应位置的修正或替代文件。</p>
<p>请记得，还有其他许多用户没遇到你发现的问题，否则你在阅读文件或搜索网页时就应该发现了（你在抱怨前<a href="https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md#%E5%9C%A8%E6%8F%90%E9%97%AE%E4%B9%8B%E5%89%8D" target="_blank" rel="noreferrer">已经做了这些，是吧</a>？）。这也意味着很有可能是你弄错了而不是软件本身有问题。</p>
<p>编写软件的人总是非常辛苦地使它尽可能完美。如果你声称找到了 Bug，也就是在质疑他们的能力，即使你是对的，也有可能会冒犯到其中某部分人。当你在标题中嚷嚷着有<code>Bug</code>时，这尤其严重。</p>
<p>提问时，即使你私下非常确信已经发现一个真正的 Bug，最好写得像是<strong>你</strong>做错了什么。如果真的有 Bug，你会在回复中看到这点。这样做的话，如果真有 Bug，维护者就会向你道歉，这总比你惹恼别人然后欠别人一个道歉要好一点。</p>
<h3 id="低声下气不能代替你的功课" tabindex="-1">低声下气不能代替你的功课 <a class="header-anchor" href="#低声下气不能代替你的功课" aria-label="Permalink to &quot;低声下气不能代替你的功课&quot;">&ZeroWidthSpace;</a></h3>
<p>有些人明白他们不该粗鲁或傲慢的提问并要求得到答复，但他们选择另一个极端 —— 低声下气：<code>我知道我只是个可悲的新手，一个失败者，但...</code>。这既使人困扰，也没有用，尤其是伴随着与实际问题含糊不清的描述时更令人反感。</p>
<p>别用原始灵长类动物的把戏来浪费你我的时间。取而代之的是，尽可能清楚地描述背景条件和你的问题情况。这比低声下气更好地定位了你的位置。</p>
<p>有时网页论坛会设有专为新手提问的版面，如果你真的认为遇到了初学者的问题，到那去就是了，但一样别那么低声下气。</p>
<h3 id="描述问题症状而非你的猜测" tabindex="-1">描述问题症状而非你的猜测 <a class="header-anchor" href="#描述问题症状而非你的猜测" aria-label="Permalink to &quot;描述问题症状而非你的猜测&quot;">&ZeroWidthSpace;</a></h3>
<p>告诉黑客们你认为问题是怎样造成的并没什么帮助。（如果你的推断如此有效，还用向别人求助吗？），因此要确信你原原本本告诉了他们问题的症状，而不是你的解释和理论；让黑客们来推测和诊断。如果你认为陈述自己的猜测很重要，清楚地说明这只是你的猜测，并描述为什么它们不起作用。</p>
<p><strong>蠢问题</strong></p>
<blockquote>
<p>我在编译内核时接连遇到 SIG11 错误， 我怀疑某条飞线搭在主板的走线上了，这种情况应该怎样检查最好？</p>
</blockquote>
<p><strong>聪明问题</strong></p>
<blockquote>
<p>我的组装电脑是 FIC-PA2007 主机板搭载 AMD K6/233 CPU（威盛 Apollo VP2 芯片组）， 256MB Corsair PC133 SDRAM 内存，在编译内核时，从开机 20 分钟以后就频频产生 SIG11 错误， 但是在头 20 分钟内从没发生过相同的问题。重新启动也没有用，但是关机一晚上就又能工作 20 分钟。 所有内存都换过了，没有效果。相关部分的标准编译记录如下…</p>
</blockquote>
<p>由于以上这点似乎让许多人觉得难以配合，这里有句话可以提醒你：<code>所有的诊断专家都来自密苏里州。</code> 美国国务院的官方座右铭则是：<code>让我看看</code>（出自国会议员 Willard D. Vandiver 在 1899 年时的讲话：<code>我来自一个出产玉米，棉花，牛蒡和民主党人的国家，滔滔雄辩既不能说服我，也不会让我满意。我来自密苏里州，你必须让我看看。</code>） 针对诊断者而言，这并不是一种怀疑，而只是一种真实而有用的需求，以便让他们看到的是与你看到的原始证据尽可能一致的东西，而不是你的猜测与归纳的结论。所以，大方地展示给我们看吧！</p>
<h3 id="按发生时间先后列出问题症状" tabindex="-1">按发生时间先后列出问题症状 <a class="header-anchor" href="#按发生时间先后列出问题症状" aria-label="Permalink to &quot;按发生时间先后列出问题症状&quot;">&ZeroWidthSpace;</a></h3>
<p>问题发生前的一系列操作，往往就是对找出问题最有帮助的线索。因此，你的说明里应该包含你的操作步骤，以及机器和软件的反应，直到问题发生。在命令行处理的情况下，提供一段操作记录（例如运行脚本工具所生成的），并引用相关的若干行（如 20 行）记录会非常有帮助。</p>
<p>如果挂掉的程序有诊断选项（如 -v 的详述开关），试着选择这些能在记录中增加调试信息的选项。记住，<code>多</code>不等于<code>好</code>。试着选取适当的调试级别以便提供有用的信息而不是让读者淹没在垃圾中。</p>
<p>如果你的说明很长（如超过四个段落），在开头简述问题，接下来再按时间顺序详述会有所帮助。这样黑客们在读你的记录时就知道该注意哪些内容了。</p>
<h3 id="描述目标而不是过程" tabindex="-1">描述目标而不是过程 <a class="header-anchor" href="#描述目标而不是过程" aria-label="Permalink to &quot;描述目标而不是过程&quot;">&ZeroWidthSpace;</a></h3>
<p>如果你想弄清楚如何做某事（而不是报告一个 Bug），在开头就描述你的目标，然后才陈述重现你所卡住的特定步骤。</p>
<p>经常寻求技术帮助的人在心中有个更高层次的目标，而他们在自以为能达到目标的特定道路上被卡住了，然后跑来问该怎么走，但没有意识到这条路本身就有问题。结果要费很大的劲才能搞定。</p>
<p><strong>蠢问题</strong></p>
<blockquote>
<p>我怎样才能从某绘图程序的颜色选择器中取得十六进制的 RGB 值？</p>
</blockquote>
<p><strong>聪明问题</strong></p>
<blockquote>
<p>我正试着用替换一幅图片的色码（color table）成自己选定的色码，我现在知道的唯一方法是编辑每个色码区块（table slot）， 但却无法从某绘图程序的颜色选择器取得十六进制的 RGB 值。</p>
</blockquote>
<p>第二种提问法比较聪明，你可能得到像是<code>建议采用另一个更合适的工具</code>的回复。</p>
<h3 id="别要求使用私人电邮回复" tabindex="-1">别要求使用私人电邮回复 <a class="header-anchor" href="#别要求使用私人电邮回复" aria-label="Permalink to &quot;别要求使用私人电邮回复&quot;">&ZeroWidthSpace;</a></h3>
<p>黑客们认为问题的解决过程应该公开、透明，此过程中如果更有经验的人注意到不完整或者不当之处，最初的回复才能够、也应该被纠正。同时，作为提供帮助者可以得到一些奖励，奖励就是他的能力和学识被其他同行看到。</p>
<p>当你要求私下回复时，这个过程和奖励都被中止。别这样做，让<strong>回复者</strong>来决定是否私下回答 —— 如果他真这么做了，通常是因为他认为问题编写太差或者太肤浅，以至于不可能使其他人产生兴趣。</p>
<p>这条规则存在一条有限的例外，如果你确信提问可能会引来大量雷同的回复时，那么这个神奇的提问句会是<code>向我发电邮，我将为论坛归纳这些回复</code>。试着将邮件列表或新闻群组从洪水般的雷同回复中解救出来是非常有礼貌的 —— 但你必须信守诺言。</p>
<h3 id="清楚明确地表达你的问题以及需求" tabindex="-1">清楚明确地表达你的问题以及需求 <a class="header-anchor" href="#清楚明确地表达你的问题以及需求" aria-label="Permalink to &quot;清楚明确地表达你的问题以及需求&quot;">&ZeroWidthSpace;</a></h3>
<p>漫无边际的提问是近乎无休无止的时间黑洞。最有可能给你有用答案的人通常也正是最忙的人（他们忙是因为要亲自完成大部分工作）。这样的人对无节制的时间黑洞相当厌恶，所以他们也倾向于厌恶那些漫无边际的提问。</p>
<p>如果你明确表述需要回答者做什么（如提供指点、发送一段代码、检查你的补丁、或是其他等等），就最有可能得到有用的答案。因为这会定出一个时间和精力的上限，便于回答者能集中精力来帮你。这么做很棒。</p>
<p>要理解专家们所处的世界，请把专业技能想像为充裕的资源，而回复的时间则是稀缺的资源。你要求他们奉献的时间越少，你越有可能从真正专业而且很忙的专家那里得到解答。</p>
<p>所以，界定一下你的问题，使专家花在辨识你的问题和回答所需要付出的时间减到最少，这技巧对你获得有用的答案相当有帮助 —— 但这技巧通常和简化问题有所区别。因此，问<code>我想更好地理解 X，可否指点一下哪有好一点说明？</code>通常比问<code>你能解释一下 X 吗？</code>更好。如果你的代码不能运作，通常请别人看看哪里有问题，比要求别人替你改正要明智得多。</p>
<h3 id="询问有关代码的问题时" tabindex="-1">询问有关代码的问题时 <a class="header-anchor" href="#询问有关代码的问题时" aria-label="Permalink to &quot;询问有关代码的问题时&quot;">&ZeroWidthSpace;</a></h3>
<p>如果没有提示别人应该从何入手，别要求他人帮你调试有问题的代码。张贴几百行的代码，然后说一声：<code>它不能工作</code>会让你完全被忽略。只贴几十行代码，然后说一句：<code>在第七行以后，我期待它显示 &lt;x&gt;，但实际出现的是 &lt;y&gt;</code>比较有可能让你得到回应。</p>
<p>最有效描述程序问题的方法是提供最精简的 Bug 展示测试用例（bug-demonstrating test case）。什么是最精简的测试用例？那是问题的缩影；一小个程序片段能<strong>刚好</strong>展示出程序的异常行为，而不包含其他令人分散注意力的内容。怎么制作最精简的测试用例？如果你知道哪一行或哪一段代码会造成异常的行为，复制下来并加入足够重现这个状况的代码（例如，足以让这段代码能被编译/直译/被应用程序处理）。如果你无法将问题缩减到一个特定区块，就复制一份代码并移除不影响产生问题行为的部分。总之，测试用例越小越好（查看<a href="https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md#%E8%AF%9D%E4%B8%8D%E5%9C%A8%E5%A4%9A%E8%80%8C%E5%9C%A8%E7%B2%BE" target="_blank" rel="noreferrer">话不在多而在精</a>一节）。</p>
<p>一般而言，要得到一段相当精简的测试用例并不太容易，但永远先尝试这样做是一个好习惯。这种方式可以帮助你了解如何自行解决这个问题 —— 而且即使你的尝试不成功，黑客们也会看到你在尝试取得答案的过程中付出了努力，这可以让他们更愿意与你合作。</p>
<p>如果你只是想让别人帮忙审查（Review）一下代码，在信的开头就要说出来，并且一定要提到你认为哪一部分特别需要关注以及为什么。</p>
<h3 id="别把自己家庭作业的问题贴上来" tabindex="-1">别把自己家庭作业的问题贴上来 <a class="header-anchor" href="#别把自己家庭作业的问题贴上来" aria-label="Permalink to &quot;别把自己家庭作业的问题贴上来&quot;">&ZeroWidthSpace;</a></h3>
<p>黑客们很擅长分辨哪些问题是家庭作业式的问题；因为我们中的大多数都曾自己解决这类问题。同样，这些问题得由<strong>你</strong>来搞定，你会从中学到东西。你可以要求给点提示，但别要求得到完整的解决方案。</p>
<p>如果你怀疑自己碰到了一个家庭作业式的问题，但仍然无法解决，试试在用户群组，论坛或（最后一招）在项目的<strong>用户</strong>邮件列表或论坛中提问。尽管黑客们<strong>会</strong>看出来，但一些有经验的用户也许仍会给你一些提示。</p>
<h3 id="去掉无意义的提问句" tabindex="-1">去掉无意义的提问句 <a class="header-anchor" href="#去掉无意义的提问句" aria-label="Permalink to &quot;去掉无意义的提问句&quot;">&ZeroWidthSpace;</a></h3>
<p>避免用无意义的话结束提问，例如<code>有人能帮我吗？</code>或者<code>这有答案吗？</code>。</p>
<p>首先：如果你对问题的描述不是很好，这样问更是画蛇添足。</p>
<p>其次：由于这样问是画蛇添足，黑客们会很厌烦你 —— 而且通常会用逻辑上正确，但毫无意义的回答来表示他们的蔑视， 例如：<code>没错，有人能帮你</code>或者<code>不，没答案</code>。</p>
<p>一般来说，避免用 <code>是或否</code>、<code>对或错</code>、<code>有或没有</code>类型的问句，除非你想得到<a href="https://strcat.de/questions-with-yes-or-no-answers.html" target="_blank" rel="noreferrer">是或否类型的回答</a>。</p>
<h3 id="即使你很急也不要在标题写紧急" tabindex="-1">即使你很急也不要在标题写<code>紧急</code> <a class="header-anchor" href="#即使你很急也不要在标题写紧急" aria-label="Permalink to &quot;即使你很急也不要在标题写`紧急`&quot;">&ZeroWidthSpace;</a></h3>
<p>这是你的问题，不是我们的。宣称<code>紧急</code>极有可能事与愿违：大多数黑客会直接删除无礼和自私地企图即时引起关注的问题。更严重的是，<code>紧急</code>这个字（或是其他企图引起关注的标题）通常会被垃圾信过滤器过滤掉 —— 你希望能看到你问题的人可能永远也看不到。</p>
<p>有半个例外的情况是，如果你是在一些很高调，会使黑客们兴奋的地方，也许值得这样去做。在这种情况下，如果你有时间压力，也很有礼貌地提到这点，人们也许会有兴趣回答快一点。</p>
<p>当然，这风险很大，因为黑客们兴奋的点多半与你的不同。譬如从 NASA 国际空间站（International Space Station）发这样的标题没有问题，但用自我感觉良好的慈善行为或政治原因发肯定不行。事实上，张贴诸如<code>紧急：帮我救救这个毛茸茸的小海豹！</code>肯定让你被黑客忽略或惹恼他们，即使他们认为毛茸茸的小海豹很重要。</p>
<p>如果你觉得这点很不可思议，最好再把这份指南剩下的内容多读几遍，直到你弄懂了再发文。</p>
<h3 id="礼多人不怪-而且有时还很有帮助" tabindex="-1">礼多人不怪，而且有时还很有帮助 <a class="header-anchor" href="#礼多人不怪-而且有时还很有帮助" aria-label="Permalink to &quot;礼多人不怪，而且有时还很有帮助&quot;">&ZeroWidthSpace;</a></h3>
<p>彬彬有礼，多用<code>请</code>和<code>谢谢您的关注</code>，或<code>谢谢你的关照</code>。让大家都知道你对他们花时间免费提供帮助心存感激。</p>
<p>坦白说，这一点并没有比使用清晰、正确、精准且合乎语法和避免使用专用格式重要（也不能取而代之）。黑客们一般宁可读有点唐突但技术上鲜明的 Bug 报告，而不是那种有礼但含糊的报告。（如果这点让你不解，记住我们是按问题能教给我们什么来评价问题的价值的）</p>
<p>然而，如果你有一串的问题待解决，客气一点肯定会增加你得到有用回应的机会。</p>
<p>（我们注意到，自从本指南发布后，从资深黑客那里得到的唯一严重缺陷反馈，就是对预先道谢这一条。一些黑客觉得<code>先谢了</code>意味着事后就不用再感谢任何人的暗示。我们的建议是要么先说<code>先谢了</code>，<strong>然后</strong>事后再对回复者表示感谢，或者换种方式表达感激，譬如用<code>谢谢你的关注</code>或<code>谢谢你的关照</code>。）</p>
<h3 id="问题解决后-加个简短的补充说明" tabindex="-1">问题解决后，加个简短的补充说明 <a class="header-anchor" href="#问题解决后-加个简短的补充说明" aria-label="Permalink to &quot;问题解决后，加个简短的补充说明&quot;">&ZeroWidthSpace;</a></h3>
<p>问题解决后，向所有帮助过你的人发个说明，让他们知道问题是怎样解决的，并再一次向他们表示感谢。如果问题在新闻组或者邮件列表中引起了广泛关注，应该在那里贴一个说明比较恰当。</p>
<p>最理想的方式是向最初提问的话题回复此消息，并在标题中包含<code>已修正</code>，<code>已解决</code>或其它同等含义的明显标记。在人来人往的邮件列表里，一个看见讨论串<code>问题 X</code>和<code>问题 X - 已解决</code>的潜在回复者就明白不用再浪费时间了（除非他个人觉得<code>问题 X</code>有趣），因此可以利用此时间去解决其它问题。</p>
<p>补充说明不必很长或是很深入；简单的一句<code>你好，原来是网线出了问题！谢谢大家 – Bill</code>比什么也不说要来的好。事实上，除非结论真的很有技术含量，否则简短可爱的小结比长篇大论更好。说明问题是怎样解决的，但大可不必将解决问题的过程复述一遍。</p>
<p>对于有深度的问题，张贴调试记录的摘要是有帮助的。描述问题的最终状态，说明是什么解决了问题，在此<strong>之后</strong>才指明可以避免的盲点。避免盲点的部分应放在正确的解决方案和其它总结材料之后，而不要将此信息搞成侦探推理小说。列出那些帮助过你的名字，会让你交到更多朋友。</p>
<p>除了有礼貌和有内涵以外，这种类型的补充也有助于他人在邮件列表/新闻群组/论坛中搜索到真正解决你问题的方案，让他们也从中受益。</p>
<p>至少，这种补充有助于让每位参与协助的人因问题的解决而从中得到满足感。如果你自己不是技术专家或者黑客，那就相信我们，这种感觉对于那些你向他们求助的大师或者专家而言，是非常重要的。问题悬而未决会让人灰心；黑客们渴望看到问题被解决。好人有好报，满足他们的渴望，你会在下次提问时尝到甜头。</p>
<p>思考一下怎样才能避免他人将来也遇到类似的问题，自问写一份文件或加个常见问题（FAQ）会不会有帮助。如果是的话就将它们发给维护者。</p>
<p>在黑客中，这种良好的后继行动实际上比传统的礼节更为重要，也是你如何透过善待他人而赢得声誉的方式，这是非常有价值的资产。</p>
<h2 id="如何解读答案" tabindex="-1">如何解读答案 <a class="header-anchor" href="#如何解读答案" aria-label="Permalink to &quot;如何解读答案&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="rtfm-和-stfw-如何知道你已完全搞砸了" tabindex="-1">RTFM 和 STFW：如何知道你已完全搞砸了 <a class="header-anchor" href="#rtfm-和-stfw-如何知道你已完全搞砸了" aria-label="Permalink to &quot;RTFM 和 STFW：如何知道你已完全搞砸了&quot;">&ZeroWidthSpace;</a></h3>
<p>有一个古老而神圣的传统：如果你收到<code>RTFM（Read The Fucking Manual）</code>的回应，回答者认为你<strong>应该去读他妈的手册</strong>。当然，基本上他是对的，你应该去读一读。</p>
<p>RTFM 有一个年轻的亲戚。如果你收到<code>STFW（Search The Fucking Web）</code>的回应，回答者认为你<strong>应该到他妈的网上搜索</strong>。那人多半也是对的，去搜索一下吧。（更温和一点的说法是 <strong><a href="http://lmgtfy.com/" target="_blank" rel="noreferrer">Google 是你的朋友</a></strong>！）</p>
<p>在论坛，你也可能被要求去爬爬论坛的旧文。事实上，有人甚至可能热心地为你提供以前解决此问题的讨论串。但不要依赖这种关照，提问前应该先搜索一下旧文。</p>
<p>通常，用这两句之一回答你的人会给你一份包含你需要内容的手册或者一个网址，而且他们打这些字的时候也正在读着。这些答复意味着回答者认为：</p>
<ul>
<li><strong>你需要的信息非常容易获得</strong>；</li>
<li><strong>你自己去搜索这些信息比灌给你，能让你学到更多</strong>。</li>
</ul>
<p>你不应该因此不爽；<strong>依照黑客的标准，他已经表示了对你一定程度的关注，而没有对你的要求视而不见</strong>。你应该对他祖母般的慈祥表示感谢。</p>
<h3 id="如果还是搞不懂" tabindex="-1">如果还是搞不懂 <a class="header-anchor" href="#如果还是搞不懂" aria-label="Permalink to &quot;如果还是搞不懂&quot;">&ZeroWidthSpace;</a></h3>
<p>如果你看不懂回应，别立刻要求对方解释。像你以前试着自己解决问题时那样（利用手册，FAQ，网络，身边的高手），先试着去搞懂他的回应。如果你真的需要对方解释，记得表现出你已经从中学到了点什么。</p>
<p>比方说，如果我回答你：<code>看来似乎是 zentry 卡住了；你应该先清除它。</code>，然后，这是一个<strong>很糟的</strong>后续问题回应：<code>zentry 是什么？</code> <strong>好</strong>的问法应该是这样：<code>哦~~~我看过说明了但是只有 -z 和 -p 两个参数中提到了 zentries，而且还都没有清楚的解释如何清除它。你是指这两个中的哪一个吗？还是我看漏了什么？</code></p>
<h3 id="处理无礼的回应" tabindex="-1">处理无礼的回应 <a class="header-anchor" href="#处理无礼的回应" aria-label="Permalink to &quot;处理无礼的回应&quot;">&ZeroWidthSpace;</a></h3>
<p>很多黑客圈子中看似无礼的行为并不是存心冒犯。相反，它是直截了当，一针见血式的交流风格，这种风格更注重解决问题，而不是使人感觉舒服而却模模糊糊。</p>
<p>如果你觉得被冒犯了，试着平静地反应。如果有人真的做了出格的事，邮件列表、新闻群组或论坛中的前辈多半会招呼他。如果这<strong>没有</strong>发生而你却发火了，那么你发火对象的言语可能在黑客社区中看起来是正常的，而<strong>你</strong>将被视为有错的一方，这将伤害到你获取信息或帮助的机会。</p>
<p>另一方面，你偶尔真的会碰到无礼和无聊的言行。与上述相反，对真正的冒犯者狠狠地打击，用犀利的语言将其驳得体无完肤都是可以接受的。然而，在行事之前一定要非常非常的有根据。纠正无礼的言论与开始一场毫无意义的口水战仅一线之隔，黑客们自己莽撞地越线的情况并不鲜见。如果你是新手或外人，避开这种莽撞的机会并不高。如果你想得到的是信息而不是消磨时光，这时最好不要把手放在键盘上以免冒险。</p>
<p>（有些人断言很多黑客都有轻度的自闭症或亚斯伯格综合症，缺少用于润滑人类社会<strong>正常</strong>交往所需的神经。这既可能是真也可能是假的。如果你自己不是黑客，兴许你认为我们脑袋有问题还能帮助你应付我们的古怪行为。只管这么干好了，我们不在乎。我们<strong>喜欢</strong>我们现在这个样子，并且通常对病患标记都有站得住脚的怀疑。）</p>
<p>Jeff Bigler 的观察总结和这个相关也值得一读 (<strong><a href="http://www.mit.edu/~jcb/tact.html" target="_blank" rel="noreferrer">tact filters</a></strong>)。</p>
<p>在下一节，我们会谈到另一个问题，当<strong>你</strong>行为不当时所会受到的<code>冒犯</code>。</p>
<h2 id="如何避免扮演失败者" tabindex="-1">如何避免扮演失败者 <a class="header-anchor" href="#如何避免扮演失败者" aria-label="Permalink to &quot;如何避免扮演失败者&quot;">&ZeroWidthSpace;</a></h2>
<p>在黑客社区的论坛中，你以本指南所描述的或类似的方式，可能会有那么几次搞砸了。而你会在公开场合中被告知你是如何搞砸的，也许攻击的言语中还会带点夹七夹八的颜色。</p>
<p>这种事发生以后，你能做的最糟糕的事莫过于哀嚎你的遭遇、宣称被言语攻击、要求道歉、高声尖叫、憋闷气、威胁诉诸法律、向其雇主报怨、不去关马桶盖等等。相反地，你该这么做：</p>
<p>熬过去，这很正常。事实上，它是有益健康且合理的。</p>
<p>社区的标准不会自行维持，它们是通过参与者积极而<strong>公开地</strong>执行来维持的。不要哭嚎所有的批评都应该通过私下的邮件传送，它不是这样运作的。当有人评论你的一个说法有误或者提出不同看法时，坚持声称受到个人攻击也毫无益处，这些都是失败者的态度。</p>
<p>也有其它的黑客论坛，受过高礼节要求的误导，禁止参与者张贴任何对别人帖子挑毛病的消息，并声称<code>如果你不想帮助用户就闭嘴。</code> 结果造成有想法的参与者纷纷离开，这么做只会使它们沦为毫无意义的唠叨与无用的技术论坛。</p>
<p>夸张的讲法是：你要的是“友善”（以上述方式）还是有用？两个里面挑一个。</p>
<p>记着：当黑客说你搞砸了，并且（无论多么刺耳）告诉你别再这样做时，他正在为关心<strong>你</strong>和<strong>他的社区</strong>而行动。对他而言，不理你并将你从他的生活中滤掉更简单。如果你无法做到感谢，至少要表现得有点尊严，别大声哀嚎，也别因为自己是个有戏剧性超级敏感的灵魂和自以为有资格的新来者，就指望别人像对待脆弱的洋娃娃那样对你。</p>
<p>有时候，即使你没有搞砸（或者只是在他的想像中你搞砸了），有些人也会无缘无故地攻击你本人。在这种情况下，抱怨倒是<strong>真的</strong>会把问题搞砸。</p>
<p>这些来找麻烦的人要么是毫无办法但自以为是专家的不中用家伙，要么就是测试你是否真会搞砸的心理专家。其它读者要么不理睬，要么用自己的方式对付他们。这些来找麻烦的人在给他们自己找麻烦，这点你不用操心。</p>
<p>也别让自己卷入口水战，最好不要理睬大多数的口水战 —— 当然，这是在你检验它们只是口水战，并且未指出你有搞砸的地方，同时也没有巧妙地将问题真正的答案藏于其后（这也是有可能的）。</p>
<h2 id="不该问的问题" tabindex="-1">不该问的问题 <a class="header-anchor" href="#不该问的问题" aria-label="Permalink to &quot;不该问的问题&quot;">&ZeroWidthSpace;</a></h2>
<p>以下是几个经典蠢问题，以及黑客没回答时心中所想的：</p>
<p>问题：<a href="https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md#q1" target="_blank" rel="noreferrer">我能在哪找到 X 程序或 X 资源？</a></p>
<p>问题：<a href="https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md#q2" target="_blank" rel="noreferrer">我怎样用 X 做 Y？</a></p>
<p>问题：<a href="https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md#q3" target="_blank" rel="noreferrer">如何设定我的 shell 提示？</a></p>
<p>问题：<a href="https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md#q4" target="_blank" rel="noreferrer">我可以用 Bass-o-matic 文件转换工具将 AcmeCorp 文件转换为 TeX 格式吗？</a></p>
<p>问题：<a href="https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md#q5" target="_blank" rel="noreferrer">我的程序/设定/SQL 语句没有用</a></p>
<p>问题：<a href="https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md#q6" target="_blank" rel="noreferrer">我的 Windows 电脑有问题，你能帮我吗？</a></p>
<p>问题：<a href="https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md#q7" target="_blank" rel="noreferrer">我的程序不会动了，我认为系统工具 X 有问题</a></p>
<p>问题：<a href="https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md#q8" target="_blank" rel="noreferrer">我在安装 Linux（或者 X ）时有问题，你能帮我吗？</a></p>
<p>问题：<a href="https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md#q9" target="_blank" rel="noreferrer">我怎么才能破解 root 帐号/窃取 OP 特权/读别人的邮件呢？</a></p>
]]></summary>
        <content type="html"><![CDATA[<h1 id="frontmatter-title-转载" tabindex="-1">{{ $frontmatter.title }}(转载) <a class="header-anchor" href="#frontmatter-title-转载" aria-label="Permalink to &quot;{{ $frontmatter.title }}(转载)&quot;">&ZeroWidthSpace;</a></h1>
<div class="warning custom-block github-alert"><p class="custom-block-title">版权声明</p>
<p>Copyright © 2001, 2006, 2014 Eric S. Raymond, Rick Moen <br/>
本指南英文版版權為 Eric S. Raymond, Rick Moen 所有。<br/>
原文網址 (Translated from)：<a href="http://www.catb.org/~esr/faqs/smart-questions.html" target="_blank" rel="noreferrer">http://www.catb.org/~esr/faqs/smart-questions.html</a><br/>
Copyleft 2001 by D.H.Grand(nOBODY/Ginux), 2010 by Gasolin, 2015-present by <a href="https://github.com/ryanhanwu" target="_blank" rel="noreferrer">Ryan Wu</a></p>
</div>
<blockquote>
<p>✒️ 文章摘要</p>
</blockquote>
<!-- DESC SEP -->
<p>本文章旨在教读者如何有效、聪明地提出技术问题，以提高获得有用答案的概率。文章强调在提问前应尽可能自行搜索、阅读文档和尝试解决问题，并在提问时表达清晰、尊重他人、避免含糊和懒惰。作者还指出应在合适的论坛提问、使用明确的标题、准确描述问题经过和现象，并在问题解决后分享经验。<br/>
本文不仅适用于技术社区，也为所有希望提高提问效率的人提供了实用的建议。</p>
<!-- DESC SEP -->
<h2 id="简介" tabindex="-1">简介 <a class="header-anchor" href="#简介" aria-label="Permalink to &quot;简介&quot;">&ZeroWidthSpace;</a></h2>
<p>在<a href="http://www.catb.org/~esr/faqs/hacker-howto.html" target="_blank" rel="noreferrer">黑客</a>的世界里，你所提技术问题的解答的好坏, 很大程度上取决于你提问的方式与此问题的难度。本指南将教你如何正确地提问以获得你满意的答案。</p>
<p>现在开源（Open Source）软件已经相当盛行，您通常可以从其他更有经验的用户那里获得与黑客一样好的答案，这是件<strong>好事</strong>；和黑客相比，用户们往往对那些新手常遇到的问题更宽容一些。尽管如此，以我们在此推荐的方式对待这些有经验的用户通常也是从他们那里获得有用答案的最有效方式。</p>
<p>首先你应该明白，黑客们喜爱有挑战性的问题，或者能激发他们思维的好问题。如果我们并非如此，那我们也不会成为你想询问的对象。如果你给了我们一个值得反复咀嚼玩味的好问题，我们自会对你感激不尽。好问题是激励，是厚礼。好问题可以提高我们的理解力，而且通常会暴露我们以前从没意识到或者思考过的问题。对黑客而言，“好问题！”是诚挚的大力称赞。</p>
<p>尽管如此，黑客们有着蔑视或傲慢面对简单问题的坏名声，这有时让我们看起来对新手、无知者似乎较有敌意，但其实不是那样的。</p>
<p>我们不讳言我们对那些不愿思考、或者在发问前不做他们该做的事的人的蔑视。那些人是时间杀手 —— 他们只想索取，从不付出，消耗我们可用在更有趣的问题或更值得回答的人身上的时间。我们称这样的人为 <code>失败者（loser）</code> （由于历史原因，我们有时把它拼作 <code>lusers</code>）。</p>
<p>我们意识到许多人只是想使用我们写的软件，他们对学习技术细节没有兴趣。对大多数人而言，电脑只是种工具，是种达到目的的手段而已。他们有自己的生活并且有更要紧的事要做。我们认可这点，也从不指望每个人都对这些让我们着迷的技术问题感兴趣。尽管如此，我们只为那些真正有兴趣并愿意积极参与问题解决的人调整回答问题的风格。这点不会变，也不该变：否则，我们就是在最擅长的事情上降低效率。</p>
<p>我们（在很大程度上）是自愿的，从繁忙的生活中抽出时间来解答疑惑，而且时常被提问淹没。所以我们无情地滤掉一些话题，特别是拋弃那些看起来像失败者的家伙，以便更高效地利用时间来回答<code>赢家（winner）</code>的问题。</p>
<p>如果你厌恶我们的态度，高高在上，或过于傲慢，不妨也设身处地想想。我们并没有要求你向我们屈服 —— 事实上，我们大多数人非常乐意与你平等地交流，只要你付出小小努力来满足基本要求，我们就会欢迎你加入我们的文化。但让我们帮助那些不愿意帮助自己的人是没有效率的。无知没有关系，但装白痴就是不行。</p>
<p>所以，你不必在技术上很在行才能吸引我们的注意，但你必须表现出能引导你变得在行的特质 —— 机敏、有想法、善于观察、乐于主动参与解决问题。如果你做不到这些使你与众不同的事情，我们建议你花点钱找家商业公司签个技术支持服务合同，而不是要求黑客个人无偿地帮助你。</p>
<p>如果你决定向我们求助，当然你也不希望被视为失败者，更不愿成为失败者中的一员。能立刻得到快速并有效答案的最好方法，就是像赢家那样提问 —— 聪明、自信、有解决问题的思路，只是偶尔在特定的问题上需要获得一点帮助。</p>
<h2 id="在提问之前" tabindex="-1">在提问之前 <a class="header-anchor" href="#在提问之前" aria-label="Permalink to &quot;在提问之前&quot;">&ZeroWidthSpace;</a></h2>
<p>在你准备要通过电子邮件、新闻群组或者聊天室提出技术问题前，请先做到以下事情：</p>
<ol>
<li>尝试在你准备提问的论坛的旧文章中搜索答案。</li>
<li>尝试上网搜索以找到答案。</li>
<li>尝试阅读手册以找到答案。</li>
<li>尝试阅读常见问题文件（FAQ）以找到答案。</li>
<li>尝试自己检查或试验以找到答案。</li>
<li>向你身边的强者朋友打听以找到答案。</li>
<li>如果你是程序开发者，请尝试阅读源代码以找到答案。</li>
</ol>
<p>当你提出问题的时候，请先表明你已经做了上述的努力；这将有助于树立你并不是一个不劳而获且浪费别人的时间的提问者。如果你能一并表达在做了上述努力的过程中所<strong>学到</strong>的东西会更好，因为我们更乐于回答那些表现出能从答案中学习的人的问题。</p>
<p>运用某些策略，比如先用 Google 搜索你所遇到的各种错误信息（搜索 <a href="http://groups.google.com/" target="_blank" rel="noreferrer">Google 论坛</a>和网页），这样很可能直接就找到了能解决问题的文件或邮件列表线索。即使没有结果，在邮件列表或新闻组寻求帮助时加上一句 <code>我在 Google 中搜过下列句子但没有找到什么有用的东西</code> 也是件好事，即使它只是表明了搜索引擎不能提供哪些帮助。这么做（加上搜索过的字串）也让遇到相似问题的其他人能被搜索引擎引导到你的提问来。</p>
<p>别着急，不要指望几秒钟的 Google 搜索就能解决一个复杂的问题。在向专家求助之前，再阅读一下常见问题文件（FAQ）、放轻松、坐得舒服一些，再花点时间思考一下这个问题。相信我们，他们能从你的提问看出你做了多少阅读与思考，如果你是有备而来，将更有可能得到解答。不要将所有问题一股脑拋出，只因你的第一次搜索没有找到答案（或者找到太多答案）。</p>
<p>准备好你的问题，再将问题仔细地思考过一遍，因为草率的发问只能得到草率的回答，或者根本得不到任何答案。越是能表现出在寻求帮助前你为解决问题所付出的努力，你越有可能得到实质性的帮助。</p>
<p>小心别问错了问题。如果你的问题基于错误的假设，某个普通黑客（J. Random Hacker）多半会一边在心里想着<code>蠢问题…</code>，一边用无意义的字面解释来答复你，希望着你会从问题的回答（而非你想得到的答案）中汲取教训。</p>
<p>绝不要自以为<strong>够格</strong>得到答案，你没有；你并没有。毕竟你没有为这种服务支付任何报酬。你将会是自己去<strong>挣到</strong>一个答案，靠提出有内涵的、有趣的、有思维激励作用的问题 —— 一个有潜力能贡献社区经验的问题，而不仅仅是被动地从他人处索取知识。</p>
<p>另一方面，表明你愿意在找答案的过程中做点什么是一个非常好的开端。<code>谁能给点提示？</code>、<code>我的这个例子里缺了什么？</code>以及<code>我应该检查什么地方</code>比<code>请把我需要的确切的过程贴出来</code>更容易得到答复。因为你表现出只要有人能指个正确方向，你就有完成它的能力和决心。</p>
<h2 id="当你提问时" tabindex="-1">当你提问时 <a class="header-anchor" href="#当你提问时" aria-label="Permalink to &quot;当你提问时&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="慎选提问的论坛" tabindex="-1">慎选提问的论坛 <a class="header-anchor" href="#慎选提问的论坛" aria-label="Permalink to &quot;慎选提问的论坛&quot;">&ZeroWidthSpace;</a></h3>
<p>小心选择你要提问的场合。如果你做了下述的事情，你很可能被忽略掉或者被看作失败者：</p>
<ul>
<li>在与主题不合的论坛上贴出你的问题。</li>
<li>在探讨进阶技术问题的论坛张贴非常初级的问题；反之亦然。</li>
<li>在太多的不同新闻群组上重复转贴同样的问题（cross-post）。</li>
<li>向既非熟人也没有义务解决你问题的人发送私人电邮。</li>
</ul>
<p>黑客会剔除掉那些搞错场合的问题，以保护他们沟通的渠道不被无关的东西淹没。你不会想让这种事发生在自己身上的。</p>
<p>因此，第一步是找到对的论坛。再说一次，Google 和其它搜索引擎还是你的朋友，用它们来找到与你遭遇到困难的软硬件问题最相关的网站。通常那儿都有常见问题（FAQ）、邮件列表及相关说明文件的链接。如果你的努力（包括<strong>阅读</strong> FAQ）都没有结果，网站上也许还有报告 Bug（Bug-reporting）的流程或链接，如果是这样，链过去看看。</p>
<p>向陌生的人或论坛发送邮件最可能是风险最大的事情。举例来说，别假设一个提供丰富内容的网页的作者会想充当你的免费顾问。不要对你的问题是否会受到欢迎做太乐观的估计 —— 如果你不确定，那就向别处发送，或者压根别发。</p>
<p>在选择论坛、新闻群组或邮件列表时，别太相信它的名字，先看看 FAQ 或者许可书以弄清楚你的问题是否切题。发文前先翻翻已有的话题，这样可以让你感受一下那里的文化。事实上，事先在新闻组或邮件列表的历史记录中搜索与你问题相关的关键词是个极好的主意，也许这样就找到答案了。即使没有，也能帮助你归纳出更好的问题。</p>
<p>别像机关枪似的一次“扫射”所有的帮助渠道，这就像大喊大叫一样会使人不快。要一个一个地来。</p>
<p>搞清楚你的主题！最典型的错误之一是在某种致力于跨平台可移植的语言、套件或工具的论坛中提关于 Unix 或 Windows 操作系统程序界面的问题。如果你不明白为什么这是大错，最好在搞清楚这之间差异之前什么也别问。</p>
<p>一般来说，在仔细挑选的公共论坛中提问，会比在私有论坛中提同样的问题更容易得到有用的回答。有几个理由可以支持这点，一是看潜在的回复者有多少，二是看观众有多少。黑客较愿意回答那些能帮助到许多人的问题。</p>
<p>可以理解的是，老练的黑客和一些热门软件的作者正在接受过多的错发信息。就像那根最后压垮骆驼背的稻草一样，你的加入也有可能使情况走向极端 —— 已经好几次了，一些热门软件的作者由于涌入其私人邮箱的大量不堪忍受的无用邮件而不再提供支持。</p>
<h3 id="stack-overflow" tabindex="-1">Stack Overflow <a class="header-anchor" href="#stack-overflow" aria-label="Permalink to &quot;Stack Overflow&quot;">&ZeroWidthSpace;</a></h3>
<p>搜索，_然后_在 Stack Exchange 问。</p>
<p>近年来，Stack Exchange 社区已经成为回答技术及其他问题的主要渠道，尤其是那些开放源码的项目。</p>
<p>因为 Google 索引是即时的，在看 Stack Exchange 之前先在 Google 搜索。有很高的几率某人已经问了一个类似的问题，而且 Stack Exchange 网站们往往会是搜索结果中最前面几个。如果你在 Google 上没有找到任何答案，你再到特定相关主题的网站去找。用标签（Tag）搜索能让你更缩小你的搜索结果。</p>
<p>如果你还是找不到任何对你的问题有用的内容，请把你的问题发在与它最相关的网站上。提问的时候请善用格式化工具，尤其注意为代码添加格式，并且添加相关的标签（特别是编程语言、操作系统或库/包的名称）。当有人要求你提供更多相关信息时，请编辑你的贴子来补充它们[译注：而不是发一个回帖或回答！]。如果你觉得一个答案对你有帮助，点击向上的箭头来为它投票；如果一个答案提供了问题的正确解决方案，点击投票按钮下方的对勾来将它标记为正解。</p>
<p>Stack Exchange 已经成长到<a href="https://stackexchange.com/sites" target="_blank" rel="noreferrer">超过一百个网站</a>，以下是最常用的几个站：</p>
<ul>
<li>Super User 是问一些通用的电脑问题，如果你的问题跟代码或是写程序无关，只是一些网络连线之类的，请到这里。</li>
<li>Stack Overflow 是问写程序有关的问题。</li>
<li>Server Fault 是问服务器和网管相关的问题。</li>
</ul>
<h3 id="网站和-irc-论坛" tabindex="-1">网站和 IRC 论坛 <a class="header-anchor" href="#网站和-irc-论坛" aria-label="Permalink to &quot;网站和 IRC 论坛&quot;">&ZeroWidthSpace;</a></h3>
<p>本地的用户群组（user group），或者你所用的 Linux 发行版本也许正在宣传他们的网页论坛或 IRC 频道，并提供新手帮助（在一些非英语国家，新手论坛很可能还是邮件列表），这些都是开始提问的好地方，特别是当你觉得遇到的也许只是相对简单或者很普通的问题时。有广告赞助的 IRC 频道是公开欢迎提问的地方，通常可以即时得到回应。</p>
<p>事实上，如果程序出的问题只发生在特定 Linux 发行版提供的版本（这很常见），最好先去该发行版的论坛或邮件列表中提问，再到程序本身的论坛或邮件列表提问。（否则）该项目的黑客可能仅仅回复“使用<strong>我们的</strong>版本”。</p>
<p>在任何论坛发文以前，先确认一下有没有搜索功能。如果有，就试着搜索一下问题的几个关键词，也许这会有帮助。如果在此之前你已做过通用的网页搜索（你也该这样做），还是再搜索一下论坛，搜索引擎有可能没来得及索引此论坛的全部内容。</p>
<p>通过论坛或 IRC 频道来提供用户支持服务有增长的趋势，电子邮件则大多为项目开发者间的交流而保留。所以最好先在论坛或 IRC 中寻求与该项目相关的协助。</p>
<p>在使用 IRC 的时候，首先最好不要发布很长的问题描述，有些人称之为频道洪水。最好通过一句话的问题描述来开始聊天。</p>
<h3 id="第二步-使用项目邮件列表" tabindex="-1">第二步，使用项目邮件列表 <a class="header-anchor" href="#第二步-使用项目邮件列表" aria-label="Permalink to &quot;第二步，使用项目邮件列表&quot;">&ZeroWidthSpace;</a></h3>
<p>当某个项目提供开发者邮件列表时，要向列表而不是其中的个别成员提问，即使你确信他能最好地回答你的问题。查一查项目的文件和首页，找到项目的邮件列表并使用它。有几个很好的理由支持我们采用这种办法：</p>
<ul>
<li>任何好到需要向个别开发者提出的问题，也将对整个项目群组有益。反之，如果你认为自己的问题对整个项目群组来说太愚蠢，那这也不能成为骚扰个别开发者的理由。</li>
<li>向列表提问可以分散开发者的负担，个别开发者（尤其是项目领导人）也许太忙以至于没法回答你的问题。</li>
<li>大多数邮件列表都会被存档，那些被存档的内容将被搜索引擎索引。如果你向列表提问并得到解答，将来其他人可以通过网页搜索找到你的问题和答案，也就不用再次发问了。</li>
<li>如果某些问题经常被问到，开发者可以利用此信息来改进说明文件或软件本身，以使其更清楚。如果只是私下提问，就没有人能看到最常见问题的完整场景。</li>
</ul>
<p>如果一个项目既有“用户”也有“开发者”（或“黑客”）邮件列表或论坛，而你又不会动到那些源代码，那么就向“用户”列表或论坛提问。不要假设自己会在开发者列表中受到欢迎，那些人多半会将你的提问视为干扰他们开发的噪音。</p>
<p>然而，如果你<strong>确信</strong>你的问题很特别，而且在“用户”列表或论坛中几天都没有回复，可以试试前往“开发者”列表或论坛发问。建议你在张贴前最好先暗地里观察几天以了解那里的行事方式（事实上这是参与任何私有或半私有列表的好主意）</p>
<p>如果你找不到一个项目的邮件列表，而只能查到项目维护者的电子邮件地址，尽管向他发信。即使是在这种情况下，也别假设（项目）邮件列表不存在。在你的电子邮件中，请陈述你已经试过但没有找到合适的邮件列表，也提及你不反对将自己的邮件转发给他人（许多人认为，即使没什么秘密，私人电子邮件也不应该被公开。通过允许将你的电子邮件转发他人，你给了相应人员处置你邮件的选择）。</p>
<h3 id="使用有意义且描述明确的标题" tabindex="-1">使用有意义且描述明确的标题 <a class="header-anchor" href="#使用有意义且描述明确的标题" aria-label="Permalink to &quot;使用有意义且描述明确的标题&quot;">&ZeroWidthSpace;</a></h3>
<p>在邮件列表、新闻群组或论坛中，大约 50 字以内的标题是抓住资深专家注意力的好机会。别用喋喋不休的<code>帮帮忙</code>、<code>跪求</code>、<code>急</code>（更别说<code>救命啊！！！！</code>这样让人反感的话，用这种标题会被条件反射式地忽略）来浪费这个机会。不要妄想用你的痛苦程度来打动我们，而应该是在这点空间中使用极简单扼要的描述方式来提出问题。</p>
<p>一个好标题范例是<code>目标 —— 差异</code>式的描述，许多技术支持组织就是这样做的。在<code>目标</code>部分指出是哪一个或哪一组东西有问题，在<code>差异</code>部分则描述与期望的行为不一致的地方。</p>
<blockquote>
<p>蠢问题：救命啊！我的笔记本电脑不能正常显示了！</p>
</blockquote>
<blockquote>
<p>聪明问题：X.org 6.8.1 的鼠标指针会变形，某牌显卡 MV1005 芯片组。</p>
</blockquote>
<blockquote>
<p>更聪明问题：X.org 6.8.1 的鼠标指针，在某牌显卡 MV1005 芯片组环境下 - 会变形。</p>
</blockquote>
<p>编写<code>目标 —— 差异</code> 式描述的过程有助于你组织对问题的细致思考。是什么被影响了？ 仅仅是鼠标指针或者还有其它图形？只在 X.org 的 X 版中出现？或只是出现在 6.8.1 版中？ 是针对某牌显卡芯片组？或者只是其中的 MV1005 型号？ 一个黑客只需瞄一眼就能够立即明白你的环境<strong>和</strong>你遇到的问题。</p>
<p>总而言之，请想像一下你正在一个只显示标题的存档讨论串（Thread）索引中查寻。让你的标题更好地反映问题，可使下一个搜索类似问题的人能够关注这个讨论串，而不用再次提问相同的问题。</p>
<p>如果你想在回复中提出问题，记得要修改内容标题，以表明你是在问一个问题， 一个看起来像 <code>Re: 测试</code> 或者 <code>Re: 新 bug</code> 的标题很难引起足够重视。另外，在不影响连贯性之下，适当引用并删减前文的内容，能给新来的读者留下线索。</p>
<p>对于讨论串，不要直接点击回复来开始一个全新的讨论串，这将限制你的观众。因为有些邮件阅读程序，比如 mutt ，允许用户按讨论串排序并通过折叠讨论串来隐藏消息，这样做的人永远看不到你发的消息。</p>
<p>仅仅改变标题还不够。mutt 和其它一些邮件阅读程序还会检查邮件标题以外的其它信息，以便为其指定讨论串。所以宁可发一个全新的邮件。</p>
<p>在网页论坛上，好的提问方式稍有不同，因为讨论串与特定的信息紧密结合，并且通常在讨论串外就看不到里面的内容，故通过回复提问，而非改变标题是可接受的。不是所有论坛都允许在回复中出现分离的标题，而且这样做了基本上没有人会去看。不过，通过回复提问，这本身就是暧昧的做法，因为它们只会被正在查看该标题的人读到。所以，除非你<strong>只想</strong>在该讨论串当前活跃的人群中提问，不然还是另起炉灶比较好。</p>
<h3 id="使问题容易回复" tabindex="-1">使问题容易回复 <a class="header-anchor" href="#使问题容易回复" aria-label="Permalink to &quot;使问题容易回复&quot;">&ZeroWidthSpace;</a></h3>
<p>以<code>请将你的回复发送到……</code>来结束你的问题多半会使你得不到回答。如果你觉得花几秒钟在邮件客户端设置一下回复地址都麻烦，我们也觉得花几秒钟思考你的问题更麻烦。如果你的邮件程序不支持这样做，<a href="http://linuxmafia.com/faq/Mail/muas.html" target="_blank" rel="noreferrer">换个好点的</a>；如果是操作系统不支持这种邮件程序，也换个好点的。</p>
<p>在论坛，要求通过电子邮件回复是非常无礼的，除非你认为回复的信息可能比较敏感（有人会为了某些未知的原因，只让你而不是整个论坛知道答案）。如果你只是想在有人回复讨论串时得到电子邮件提醒，可以要求网页论坛发送给你。几乎所有论坛都支持诸如<code>追踪此讨论串</code>、<code>有回复时发送邮件提醒</code>等功能。</p>
<h3 id="使用清晰、正确、精准且合乎语法的语句" tabindex="-1">使用清晰、正确、精准且合乎语法的语句 <a class="header-anchor" href="#使用清晰、正确、精准且合乎语法的语句" aria-label="Permalink to &quot;使用清晰、正确、精准且合乎语法的语句&quot;">&ZeroWidthSpace;</a></h3>
<p>我们从经验中发现，粗心的提问者通常也会粗心地写程序与思考（我敢打包票）。回答粗心大意者的问题很不值得，我们宁愿把时间耗在别处。</p>
<p>正确的拼写、标点符号和大小写是很重要的。一般来说，如果你觉得这样做很麻烦，不想在乎这些，那我们也觉得麻烦，不想在乎你的提问。花点额外的精力斟酌一下字句，用不着太僵硬与正式 —— 事实上，黑客文化很看重能准确地使用非正式、俚语和幽默的语句。但它<strong>必须很</strong>准确，而且有迹象表明你是在思考和关注问题。</p>
<p>正确地拼写、使用标点和大小写，不要将<code>its</code>混淆为<code>it's</code>，<code>loose</code>搞成<code>lose</code>或者将<code>discrete</code>弄成<code>discreet</code>。不要<strong>全部用大写</strong>，这会被视为无礼的大声嚷嚷（全部小写也好不到哪去，因为不易阅读。<a href="http://en.wikipedia.org/wiki/Alan_Cox" target="_blank" rel="noreferrer">Alan Cox</a> 也许可以这样做，但你不行）。</p>
<p>更白话的说，如果你写得像是个半文盲[译注：<a href="http://zh.wikipedia.org/wiki/%E5%B0%8F%E7%99%BD" target="_blank" rel="noreferrer">小白</a>]，那多半得不到理睬。也不要使用即时通信中的简写或<a href="http://zh.wikipedia.org/wiki/%E7%81%AB%E6%98%9F%E6%96%87" target="_blank" rel="noreferrer">火星文</a>，如将<code>的</code>简化为<code>d</code>会使你看起来像一个为了少打几个键而省字的小白。更糟的是，如果像个小孩似地鬼画符那绝对是在找死，可以肯定没人会理你（或者最多是给你一大堆指责与挖苦）。</p>
<p>如果在使用非母语的论坛提问，你可以犯点拼写和语法上的小错，但决不能在思考上马虎（没错，我们通常能弄清两者的分别）。同时，除非你知道回复者使用的语言，否则请使用英语书写。繁忙的黑客一般会直接删除用他们看不懂的语言写的消息。在网络上英语是通用语言，用英语书写可以将你的问题在尚未被阅读就被直接删除的可能性降到最低。</p>
<p>如果英文是你的外语（Second language），提示潜在回复者你有潜在的语言困难是很好的： [译注：以下附上原文以供使用]</p>
<blockquote>
<p>English is not my native language; please excuse typing errors.</p>
</blockquote>
<ul>
<li>英文不是我的母语，请原谅我的错字或语法。</li>
</ul>
<blockquote>
<p>If you speak $LANGUAGE, please email/PM me; I may need assistance translating my question.</p>
</blockquote>
<ul>
<li>如果你说<strong>某语言</strong>，请向我发电邮/私信；</li>
<li>我需要有人协助我翻译我的问题。</li>
</ul>
<blockquote>
<p>I am familiar with the technical terms, but some slang expressions and idioms are difficult for me.</p>
</blockquote>
<ul>
<li>我对技术名词很熟悉，但对于俗语或是特别用法不甚了解。</li>
</ul>
<blockquote>
<p>I've posted my question in $LANGUAGE and English. I'll be glad to translate responses, if you only use one or the other.</p>
</blockquote>
<ul>
<li>我把我的问题用<strong>某语言</strong>和英文写出来。</li>
<li>如果你只用其中的一种语言回答，我会乐意将回复翻译成为你使用的语言。</li>
</ul>
<h3 id="使用易于读取且标准的文件格式发送问题" tabindex="-1">使用易于读取且标准的文件格式发送问题 <a class="header-anchor" href="#使用易于读取且标准的文件格式发送问题" aria-label="Permalink to &quot;使用易于读取且标准的文件格式发送问题&quot;">&ZeroWidthSpace;</a></h3>
<p>如果你人为地将问题搞得难以阅读，它多半会被忽略，人们更愿读易懂的问题，所以：</p>
<ul>
<li>使用纯文字而不是 HTML (<a href="http://archive.birdhouse.org/etc/evilmail.html" target="_blank" rel="noreferrer">关闭 HTML</a> 并不难）。</li>
<li>使用 MIME 附件通常是可以的，前提是真正有内容（譬如附带的源代码或 patch），而不仅仅是邮件程序生成的模板（譬如只是信件内容的拷贝）。</li>
<li>不要发送一段文字只是一行句子但自动换行后会变成多行的邮件（这使得回复部分内容非常困难）。设想你的读者是在 80 个字符宽的终端机上阅读邮件，最好设置你的换行分割点小于 80 字。</li>
<li>但是，对一些特殊的文件<strong>不要</strong>设置固定宽度（譬如日志文件拷贝或会话记录）。数据应该原样包含，让回复者有信心他们看到的是和你看到的一样的东西。</li>
<li>在英语论坛中，不要使用<code>Quoted-Printable</code> MIME 编码发送消息。这种编码对于张贴非 ASCII 语言可能是必须的，但很多邮件程序并不支持这种编码。当它们处理换行时，那些文本中四处散布的<code>=20</code>符号既难看也分散注意力，甚至有可能破坏内容的语意。</li>
<li>绝对，<strong>永远</strong>不要指望黑客们阅读使用封闭格式编写的文档，像微软公司的 Word 或 Excel 文件等。大多数黑客对此的反应就像有人将还在冒热气的猪粪倒在你家门口时你的反应一样。即便他们能够处理，他们也很厌恶这么做。</li>
<li>如果你从使用 Windows 的电脑发送电子邮件，关闭微软愚蠢的<code>智能引号</code>功能 （从[选项] &gt; [校订] &gt; [自动校正选项]，勾选掉<code>智能引号</code>单选框），以免在你的邮件中到处散布垃圾字符。</li>
<li>在论坛，勿滥用<code>表情符号</code>和<code>HTML</code>功能（当它们提供时）。一两个表情符号通常没有问题，但花哨的彩色文本倾向于使人认为你是个无能之辈。过滥地使用表情符号、色彩和字体会使你看来像个傻笑的小姑娘。这通常不是个好主意，除非你只是对性而不是对答案感兴趣。</li>
</ul>
<p>如果你使用图形用户界面的邮件程序（如微软公司的 Outlook 或者其它类似的），注意它们的默认设置不一定满足这些要求。大多数这类程序有基于选单的<code>查看源代码</code>命令，用它来检查发送文件夹中的邮件，以确保发送的是纯文本文件同时没有一些奇怪的字符。</p>
<h3 id="精确地描述问题并言之有物" tabindex="-1">精确地描述问题并言之有物 <a class="header-anchor" href="#精确地描述问题并言之有物" aria-label="Permalink to &quot;精确地描述问题并言之有物&quot;">&ZeroWidthSpace;</a></h3>
<ul>
<li>仔细、清楚地描述你的问题或 Bug 的症状。</li>
<li>描述问题发生的环境（机器配置、操作系统、应用程序、以及相关的信息），提供经销商的发行版和版本号（如：<code>Fedora Core 4</code>、<code>Slackware 9.1</code>等）。</li>
<li>描述在提问前你是怎样去研究和理解这个问题的。</li>
<li>描述在提问前为确定问题而采取的诊断步骤。</li>
<li>描述最近做过什么可能相关的硬件或软件变更。</li>
<li>尽可能地提供一个可以<code>重现这个问题的可控环境</code>的方法。</li>
</ul>
<p>尽量去揣测一个黑客会怎样反问你，在你提问之前预先将黑客们可能提出的问题回答一遍。</p>
<p>以上几点中，当你报告的是你认为可能在代码中的问题时，给黑客一个可以重现你的问题的环境尤其重要。当你这么做时，你得到有效的回答的机会和速度都会大大的提升。</p>
<p><a href="http://www.chiark.greenend.org.uk/~sgtatham/" target="_blank" rel="noreferrer">Simon Tatham</a> 写过一篇名为《<a href="http://www.chiark.greenend.org.uk/~sgtatham/bugs-cn.html" target="_blank" rel="noreferrer">如何有效地报告Bug</a>》的出色文章。强力推荐你也读一读。</p>
<h3 id="话不在多而在精" tabindex="-1">话不在多而在精 <a class="header-anchor" href="#话不在多而在精" aria-label="Permalink to &quot;话不在多而在精&quot;">&ZeroWidthSpace;</a></h3>
<p>你需要提供精确有内容的信息。这并不是要求你简单的把成堆的出错代码或者资料完全转录到你的提问中。如果你有庞大而复杂的测试样例能重现程序挂掉的情境，尽量将它剪裁得越小越好。</p>
<p>这样做的用处至少有三点。 第一，表现出你为简化问题付出了努力，这可以使你得到回答的机会增加； 第二，简化问题使你更有可能得到<strong>有用</strong>的答案； 第三，在精炼你的 bug 报告的过程中，你很可能就自己找到了解决方法或权宜之计。</p>
<h3 id="别动辄声称找到-bug" tabindex="-1">别动辄声称找到 Bug <a class="header-anchor" href="#别动辄声称找到-bug" aria-label="Permalink to &quot;别动辄声称找到 Bug&quot;">&ZeroWidthSpace;</a></h3>
<p>当你在使用软件中遇到问题，除非你非常、<strong>非常</strong>的有根据，不要动辄声称找到了 Bug。提示：除非你能提供解决问题的源代码补丁，或者提供回归测试来表明前一版本中行为不正确，否则你都多半不够完全确信。这同样适用在网页和文件，如果你（声称）发现了文件的<code>Bug</code>，你应该能提供相应位置的修正或替代文件。</p>
<p>请记得，还有其他许多用户没遇到你发现的问题，否则你在阅读文件或搜索网页时就应该发现了（你在抱怨前<a href="https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md#%E5%9C%A8%E6%8F%90%E9%97%AE%E4%B9%8B%E5%89%8D" target="_blank" rel="noreferrer">已经做了这些，是吧</a>？）。这也意味着很有可能是你弄错了而不是软件本身有问题。</p>
<p>编写软件的人总是非常辛苦地使它尽可能完美。如果你声称找到了 Bug，也就是在质疑他们的能力，即使你是对的，也有可能会冒犯到其中某部分人。当你在标题中嚷嚷着有<code>Bug</code>时，这尤其严重。</p>
<p>提问时，即使你私下非常确信已经发现一个真正的 Bug，最好写得像是<strong>你</strong>做错了什么。如果真的有 Bug，你会在回复中看到这点。这样做的话，如果真有 Bug，维护者就会向你道歉，这总比你惹恼别人然后欠别人一个道歉要好一点。</p>
<h3 id="低声下气不能代替你的功课" tabindex="-1">低声下气不能代替你的功课 <a class="header-anchor" href="#低声下气不能代替你的功课" aria-label="Permalink to &quot;低声下气不能代替你的功课&quot;">&ZeroWidthSpace;</a></h3>
<p>有些人明白他们不该粗鲁或傲慢的提问并要求得到答复，但他们选择另一个极端 —— 低声下气：<code>我知道我只是个可悲的新手，一个失败者，但...</code>。这既使人困扰，也没有用，尤其是伴随着与实际问题含糊不清的描述时更令人反感。</p>
<p>别用原始灵长类动物的把戏来浪费你我的时间。取而代之的是，尽可能清楚地描述背景条件和你的问题情况。这比低声下气更好地定位了你的位置。</p>
<p>有时网页论坛会设有专为新手提问的版面，如果你真的认为遇到了初学者的问题，到那去就是了，但一样别那么低声下气。</p>
<h3 id="描述问题症状而非你的猜测" tabindex="-1">描述问题症状而非你的猜测 <a class="header-anchor" href="#描述问题症状而非你的猜测" aria-label="Permalink to &quot;描述问题症状而非你的猜测&quot;">&ZeroWidthSpace;</a></h3>
<p>告诉黑客们你认为问题是怎样造成的并没什么帮助。（如果你的推断如此有效，还用向别人求助吗？），因此要确信你原原本本告诉了他们问题的症状，而不是你的解释和理论；让黑客们来推测和诊断。如果你认为陈述自己的猜测很重要，清楚地说明这只是你的猜测，并描述为什么它们不起作用。</p>
<p><strong>蠢问题</strong></p>
<blockquote>
<p>我在编译内核时接连遇到 SIG11 错误， 我怀疑某条飞线搭在主板的走线上了，这种情况应该怎样检查最好？</p>
</blockquote>
<p><strong>聪明问题</strong></p>
<blockquote>
<p>我的组装电脑是 FIC-PA2007 主机板搭载 AMD K6/233 CPU（威盛 Apollo VP2 芯片组）， 256MB Corsair PC133 SDRAM 内存，在编译内核时，从开机 20 分钟以后就频频产生 SIG11 错误， 但是在头 20 分钟内从没发生过相同的问题。重新启动也没有用，但是关机一晚上就又能工作 20 分钟。 所有内存都换过了，没有效果。相关部分的标准编译记录如下…</p>
</blockquote>
<p>由于以上这点似乎让许多人觉得难以配合，这里有句话可以提醒你：<code>所有的诊断专家都来自密苏里州。</code> 美国国务院的官方座右铭则是：<code>让我看看</code>（出自国会议员 Willard D. Vandiver 在 1899 年时的讲话：<code>我来自一个出产玉米，棉花，牛蒡和民主党人的国家，滔滔雄辩既不能说服我，也不会让我满意。我来自密苏里州，你必须让我看看。</code>） 针对诊断者而言，这并不是一种怀疑，而只是一种真实而有用的需求，以便让他们看到的是与你看到的原始证据尽可能一致的东西，而不是你的猜测与归纳的结论。所以，大方地展示给我们看吧！</p>
<h3 id="按发生时间先后列出问题症状" tabindex="-1">按发生时间先后列出问题症状 <a class="header-anchor" href="#按发生时间先后列出问题症状" aria-label="Permalink to &quot;按发生时间先后列出问题症状&quot;">&ZeroWidthSpace;</a></h3>
<p>问题发生前的一系列操作，往往就是对找出问题最有帮助的线索。因此，你的说明里应该包含你的操作步骤，以及机器和软件的反应，直到问题发生。在命令行处理的情况下，提供一段操作记录（例如运行脚本工具所生成的），并引用相关的若干行（如 20 行）记录会非常有帮助。</p>
<p>如果挂掉的程序有诊断选项（如 -v 的详述开关），试着选择这些能在记录中增加调试信息的选项。记住，<code>多</code>不等于<code>好</code>。试着选取适当的调试级别以便提供有用的信息而不是让读者淹没在垃圾中。</p>
<p>如果你的说明很长（如超过四个段落），在开头简述问题，接下来再按时间顺序详述会有所帮助。这样黑客们在读你的记录时就知道该注意哪些内容了。</p>
<h3 id="描述目标而不是过程" tabindex="-1">描述目标而不是过程 <a class="header-anchor" href="#描述目标而不是过程" aria-label="Permalink to &quot;描述目标而不是过程&quot;">&ZeroWidthSpace;</a></h3>
<p>如果你想弄清楚如何做某事（而不是报告一个 Bug），在开头就描述你的目标，然后才陈述重现你所卡住的特定步骤。</p>
<p>经常寻求技术帮助的人在心中有个更高层次的目标，而他们在自以为能达到目标的特定道路上被卡住了，然后跑来问该怎么走，但没有意识到这条路本身就有问题。结果要费很大的劲才能搞定。</p>
<p><strong>蠢问题</strong></p>
<blockquote>
<p>我怎样才能从某绘图程序的颜色选择器中取得十六进制的 RGB 值？</p>
</blockquote>
<p><strong>聪明问题</strong></p>
<blockquote>
<p>我正试着用替换一幅图片的色码（color table）成自己选定的色码，我现在知道的唯一方法是编辑每个色码区块（table slot）， 但却无法从某绘图程序的颜色选择器取得十六进制的 RGB 值。</p>
</blockquote>
<p>第二种提问法比较聪明，你可能得到像是<code>建议采用另一个更合适的工具</code>的回复。</p>
<h3 id="别要求使用私人电邮回复" tabindex="-1">别要求使用私人电邮回复 <a class="header-anchor" href="#别要求使用私人电邮回复" aria-label="Permalink to &quot;别要求使用私人电邮回复&quot;">&ZeroWidthSpace;</a></h3>
<p>黑客们认为问题的解决过程应该公开、透明，此过程中如果更有经验的人注意到不完整或者不当之处，最初的回复才能够、也应该被纠正。同时，作为提供帮助者可以得到一些奖励，奖励就是他的能力和学识被其他同行看到。</p>
<p>当你要求私下回复时，这个过程和奖励都被中止。别这样做，让<strong>回复者</strong>来决定是否私下回答 —— 如果他真这么做了，通常是因为他认为问题编写太差或者太肤浅，以至于不可能使其他人产生兴趣。</p>
<p>这条规则存在一条有限的例外，如果你确信提问可能会引来大量雷同的回复时，那么这个神奇的提问句会是<code>向我发电邮，我将为论坛归纳这些回复</code>。试着将邮件列表或新闻群组从洪水般的雷同回复中解救出来是非常有礼貌的 —— 但你必须信守诺言。</p>
<h3 id="清楚明确地表达你的问题以及需求" tabindex="-1">清楚明确地表达你的问题以及需求 <a class="header-anchor" href="#清楚明确地表达你的问题以及需求" aria-label="Permalink to &quot;清楚明确地表达你的问题以及需求&quot;">&ZeroWidthSpace;</a></h3>
<p>漫无边际的提问是近乎无休无止的时间黑洞。最有可能给你有用答案的人通常也正是最忙的人（他们忙是因为要亲自完成大部分工作）。这样的人对无节制的时间黑洞相当厌恶，所以他们也倾向于厌恶那些漫无边际的提问。</p>
<p>如果你明确表述需要回答者做什么（如提供指点、发送一段代码、检查你的补丁、或是其他等等），就最有可能得到有用的答案。因为这会定出一个时间和精力的上限，便于回答者能集中精力来帮你。这么做很棒。</p>
<p>要理解专家们所处的世界，请把专业技能想像为充裕的资源，而回复的时间则是稀缺的资源。你要求他们奉献的时间越少，你越有可能从真正专业而且很忙的专家那里得到解答。</p>
<p>所以，界定一下你的问题，使专家花在辨识你的问题和回答所需要付出的时间减到最少，这技巧对你获得有用的答案相当有帮助 —— 但这技巧通常和简化问题有所区别。因此，问<code>我想更好地理解 X，可否指点一下哪有好一点说明？</code>通常比问<code>你能解释一下 X 吗？</code>更好。如果你的代码不能运作，通常请别人看看哪里有问题，比要求别人替你改正要明智得多。</p>
<h3 id="询问有关代码的问题时" tabindex="-1">询问有关代码的问题时 <a class="header-anchor" href="#询问有关代码的问题时" aria-label="Permalink to &quot;询问有关代码的问题时&quot;">&ZeroWidthSpace;</a></h3>
<p>如果没有提示别人应该从何入手，别要求他人帮你调试有问题的代码。张贴几百行的代码，然后说一声：<code>它不能工作</code>会让你完全被忽略。只贴几十行代码，然后说一句：<code>在第七行以后，我期待它显示 &lt;x&gt;，但实际出现的是 &lt;y&gt;</code>比较有可能让你得到回应。</p>
<p>最有效描述程序问题的方法是提供最精简的 Bug 展示测试用例（bug-demonstrating test case）。什么是最精简的测试用例？那是问题的缩影；一小个程序片段能<strong>刚好</strong>展示出程序的异常行为，而不包含其他令人分散注意力的内容。怎么制作最精简的测试用例？如果你知道哪一行或哪一段代码会造成异常的行为，复制下来并加入足够重现这个状况的代码（例如，足以让这段代码能被编译/直译/被应用程序处理）。如果你无法将问题缩减到一个特定区块，就复制一份代码并移除不影响产生问题行为的部分。总之，测试用例越小越好（查看<a href="https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md#%E8%AF%9D%E4%B8%8D%E5%9C%A8%E5%A4%9A%E8%80%8C%E5%9C%A8%E7%B2%BE" target="_blank" rel="noreferrer">话不在多而在精</a>一节）。</p>
<p>一般而言，要得到一段相当精简的测试用例并不太容易，但永远先尝试这样做是一个好习惯。这种方式可以帮助你了解如何自行解决这个问题 —— 而且即使你的尝试不成功，黑客们也会看到你在尝试取得答案的过程中付出了努力，这可以让他们更愿意与你合作。</p>
<p>如果你只是想让别人帮忙审查（Review）一下代码，在信的开头就要说出来，并且一定要提到你认为哪一部分特别需要关注以及为什么。</p>
<h3 id="别把自己家庭作业的问题贴上来" tabindex="-1">别把自己家庭作业的问题贴上来 <a class="header-anchor" href="#别把自己家庭作业的问题贴上来" aria-label="Permalink to &quot;别把自己家庭作业的问题贴上来&quot;">&ZeroWidthSpace;</a></h3>
<p>黑客们很擅长分辨哪些问题是家庭作业式的问题；因为我们中的大多数都曾自己解决这类问题。同样，这些问题得由<strong>你</strong>来搞定，你会从中学到东西。你可以要求给点提示，但别要求得到完整的解决方案。</p>
<p>如果你怀疑自己碰到了一个家庭作业式的问题，但仍然无法解决，试试在用户群组，论坛或（最后一招）在项目的<strong>用户</strong>邮件列表或论坛中提问。尽管黑客们<strong>会</strong>看出来，但一些有经验的用户也许仍会给你一些提示。</p>
<h3 id="去掉无意义的提问句" tabindex="-1">去掉无意义的提问句 <a class="header-anchor" href="#去掉无意义的提问句" aria-label="Permalink to &quot;去掉无意义的提问句&quot;">&ZeroWidthSpace;</a></h3>
<p>避免用无意义的话结束提问，例如<code>有人能帮我吗？</code>或者<code>这有答案吗？</code>。</p>
<p>首先：如果你对问题的描述不是很好，这样问更是画蛇添足。</p>
<p>其次：由于这样问是画蛇添足，黑客们会很厌烦你 —— 而且通常会用逻辑上正确，但毫无意义的回答来表示他们的蔑视， 例如：<code>没错，有人能帮你</code>或者<code>不，没答案</code>。</p>
<p>一般来说，避免用 <code>是或否</code>、<code>对或错</code>、<code>有或没有</code>类型的问句，除非你想得到<a href="https://strcat.de/questions-with-yes-or-no-answers.html" target="_blank" rel="noreferrer">是或否类型的回答</a>。</p>
<h3 id="即使你很急也不要在标题写紧急" tabindex="-1">即使你很急也不要在标题写<code>紧急</code> <a class="header-anchor" href="#即使你很急也不要在标题写紧急" aria-label="Permalink to &quot;即使你很急也不要在标题写`紧急`&quot;">&ZeroWidthSpace;</a></h3>
<p>这是你的问题，不是我们的。宣称<code>紧急</code>极有可能事与愿违：大多数黑客会直接删除无礼和自私地企图即时引起关注的问题。更严重的是，<code>紧急</code>这个字（或是其他企图引起关注的标题）通常会被垃圾信过滤器过滤掉 —— 你希望能看到你问题的人可能永远也看不到。</p>
<p>有半个例外的情况是，如果你是在一些很高调，会使黑客们兴奋的地方，也许值得这样去做。在这种情况下，如果你有时间压力，也很有礼貌地提到这点，人们也许会有兴趣回答快一点。</p>
<p>当然，这风险很大，因为黑客们兴奋的点多半与你的不同。譬如从 NASA 国际空间站（International Space Station）发这样的标题没有问题，但用自我感觉良好的慈善行为或政治原因发肯定不行。事实上，张贴诸如<code>紧急：帮我救救这个毛茸茸的小海豹！</code>肯定让你被黑客忽略或惹恼他们，即使他们认为毛茸茸的小海豹很重要。</p>
<p>如果你觉得这点很不可思议，最好再把这份指南剩下的内容多读几遍，直到你弄懂了再发文。</p>
<h3 id="礼多人不怪-而且有时还很有帮助" tabindex="-1">礼多人不怪，而且有时还很有帮助 <a class="header-anchor" href="#礼多人不怪-而且有时还很有帮助" aria-label="Permalink to &quot;礼多人不怪，而且有时还很有帮助&quot;">&ZeroWidthSpace;</a></h3>
<p>彬彬有礼，多用<code>请</code>和<code>谢谢您的关注</code>，或<code>谢谢你的关照</code>。让大家都知道你对他们花时间免费提供帮助心存感激。</p>
<p>坦白说，这一点并没有比使用清晰、正确、精准且合乎语法和避免使用专用格式重要（也不能取而代之）。黑客们一般宁可读有点唐突但技术上鲜明的 Bug 报告，而不是那种有礼但含糊的报告。（如果这点让你不解，记住我们是按问题能教给我们什么来评价问题的价值的）</p>
<p>然而，如果你有一串的问题待解决，客气一点肯定会增加你得到有用回应的机会。</p>
<p>（我们注意到，自从本指南发布后，从资深黑客那里得到的唯一严重缺陷反馈，就是对预先道谢这一条。一些黑客觉得<code>先谢了</code>意味着事后就不用再感谢任何人的暗示。我们的建议是要么先说<code>先谢了</code>，<strong>然后</strong>事后再对回复者表示感谢，或者换种方式表达感激，譬如用<code>谢谢你的关注</code>或<code>谢谢你的关照</code>。）</p>
<h3 id="问题解决后-加个简短的补充说明" tabindex="-1">问题解决后，加个简短的补充说明 <a class="header-anchor" href="#问题解决后-加个简短的补充说明" aria-label="Permalink to &quot;问题解决后，加个简短的补充说明&quot;">&ZeroWidthSpace;</a></h3>
<p>问题解决后，向所有帮助过你的人发个说明，让他们知道问题是怎样解决的，并再一次向他们表示感谢。如果问题在新闻组或者邮件列表中引起了广泛关注，应该在那里贴一个说明比较恰当。</p>
<p>最理想的方式是向最初提问的话题回复此消息，并在标题中包含<code>已修正</code>，<code>已解决</code>或其它同等含义的明显标记。在人来人往的邮件列表里，一个看见讨论串<code>问题 X</code>和<code>问题 X - 已解决</code>的潜在回复者就明白不用再浪费时间了（除非他个人觉得<code>问题 X</code>有趣），因此可以利用此时间去解决其它问题。</p>
<p>补充说明不必很长或是很深入；简单的一句<code>你好，原来是网线出了问题！谢谢大家 – Bill</code>比什么也不说要来的好。事实上，除非结论真的很有技术含量，否则简短可爱的小结比长篇大论更好。说明问题是怎样解决的，但大可不必将解决问题的过程复述一遍。</p>
<p>对于有深度的问题，张贴调试记录的摘要是有帮助的。描述问题的最终状态，说明是什么解决了问题，在此<strong>之后</strong>才指明可以避免的盲点。避免盲点的部分应放在正确的解决方案和其它总结材料之后，而不要将此信息搞成侦探推理小说。列出那些帮助过你的名字，会让你交到更多朋友。</p>
<p>除了有礼貌和有内涵以外，这种类型的补充也有助于他人在邮件列表/新闻群组/论坛中搜索到真正解决你问题的方案，让他们也从中受益。</p>
<p>至少，这种补充有助于让每位参与协助的人因问题的解决而从中得到满足感。如果你自己不是技术专家或者黑客，那就相信我们，这种感觉对于那些你向他们求助的大师或者专家而言，是非常重要的。问题悬而未决会让人灰心；黑客们渴望看到问题被解决。好人有好报，满足他们的渴望，你会在下次提问时尝到甜头。</p>
<p>思考一下怎样才能避免他人将来也遇到类似的问题，自问写一份文件或加个常见问题（FAQ）会不会有帮助。如果是的话就将它们发给维护者。</p>
<p>在黑客中，这种良好的后继行动实际上比传统的礼节更为重要，也是你如何透过善待他人而赢得声誉的方式，这是非常有价值的资产。</p>
<h2 id="如何解读答案" tabindex="-1">如何解读答案 <a class="header-anchor" href="#如何解读答案" aria-label="Permalink to &quot;如何解读答案&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="rtfm-和-stfw-如何知道你已完全搞砸了" tabindex="-1">RTFM 和 STFW：如何知道你已完全搞砸了 <a class="header-anchor" href="#rtfm-和-stfw-如何知道你已完全搞砸了" aria-label="Permalink to &quot;RTFM 和 STFW：如何知道你已完全搞砸了&quot;">&ZeroWidthSpace;</a></h3>
<p>有一个古老而神圣的传统：如果你收到<code>RTFM（Read The Fucking Manual）</code>的回应，回答者认为你<strong>应该去读他妈的手册</strong>。当然，基本上他是对的，你应该去读一读。</p>
<p>RTFM 有一个年轻的亲戚。如果你收到<code>STFW（Search The Fucking Web）</code>的回应，回答者认为你<strong>应该到他妈的网上搜索</strong>。那人多半也是对的，去搜索一下吧。（更温和一点的说法是 <strong><a href="http://lmgtfy.com/" target="_blank" rel="noreferrer">Google 是你的朋友</a></strong>！）</p>
<p>在论坛，你也可能被要求去爬爬论坛的旧文。事实上，有人甚至可能热心地为你提供以前解决此问题的讨论串。但不要依赖这种关照，提问前应该先搜索一下旧文。</p>
<p>通常，用这两句之一回答你的人会给你一份包含你需要内容的手册或者一个网址，而且他们打这些字的时候也正在读着。这些答复意味着回答者认为：</p>
<ul>
<li><strong>你需要的信息非常容易获得</strong>；</li>
<li><strong>你自己去搜索这些信息比灌给你，能让你学到更多</strong>。</li>
</ul>
<p>你不应该因此不爽；<strong>依照黑客的标准，他已经表示了对你一定程度的关注，而没有对你的要求视而不见</strong>。你应该对他祖母般的慈祥表示感谢。</p>
<h3 id="如果还是搞不懂" tabindex="-1">如果还是搞不懂 <a class="header-anchor" href="#如果还是搞不懂" aria-label="Permalink to &quot;如果还是搞不懂&quot;">&ZeroWidthSpace;</a></h3>
<p>如果你看不懂回应，别立刻要求对方解释。像你以前试着自己解决问题时那样（利用手册，FAQ，网络，身边的高手），先试着去搞懂他的回应。如果你真的需要对方解释，记得表现出你已经从中学到了点什么。</p>
<p>比方说，如果我回答你：<code>看来似乎是 zentry 卡住了；你应该先清除它。</code>，然后，这是一个<strong>很糟的</strong>后续问题回应：<code>zentry 是什么？</code> <strong>好</strong>的问法应该是这样：<code>哦~~~我看过说明了但是只有 -z 和 -p 两个参数中提到了 zentries，而且还都没有清楚的解释如何清除它。你是指这两个中的哪一个吗？还是我看漏了什么？</code></p>
<h3 id="处理无礼的回应" tabindex="-1">处理无礼的回应 <a class="header-anchor" href="#处理无礼的回应" aria-label="Permalink to &quot;处理无礼的回应&quot;">&ZeroWidthSpace;</a></h3>
<p>很多黑客圈子中看似无礼的行为并不是存心冒犯。相反，它是直截了当，一针见血式的交流风格，这种风格更注重解决问题，而不是使人感觉舒服而却模模糊糊。</p>
<p>如果你觉得被冒犯了，试着平静地反应。如果有人真的做了出格的事，邮件列表、新闻群组或论坛中的前辈多半会招呼他。如果这<strong>没有</strong>发生而你却发火了，那么你发火对象的言语可能在黑客社区中看起来是正常的，而<strong>你</strong>将被视为有错的一方，这将伤害到你获取信息或帮助的机会。</p>
<p>另一方面，你偶尔真的会碰到无礼和无聊的言行。与上述相反，对真正的冒犯者狠狠地打击，用犀利的语言将其驳得体无完肤都是可以接受的。然而，在行事之前一定要非常非常的有根据。纠正无礼的言论与开始一场毫无意义的口水战仅一线之隔，黑客们自己莽撞地越线的情况并不鲜见。如果你是新手或外人，避开这种莽撞的机会并不高。如果你想得到的是信息而不是消磨时光，这时最好不要把手放在键盘上以免冒险。</p>
<p>（有些人断言很多黑客都有轻度的自闭症或亚斯伯格综合症，缺少用于润滑人类社会<strong>正常</strong>交往所需的神经。这既可能是真也可能是假的。如果你自己不是黑客，兴许你认为我们脑袋有问题还能帮助你应付我们的古怪行为。只管这么干好了，我们不在乎。我们<strong>喜欢</strong>我们现在这个样子，并且通常对病患标记都有站得住脚的怀疑。）</p>
<p>Jeff Bigler 的观察总结和这个相关也值得一读 (<strong><a href="http://www.mit.edu/~jcb/tact.html" target="_blank" rel="noreferrer">tact filters</a></strong>)。</p>
<p>在下一节，我们会谈到另一个问题，当<strong>你</strong>行为不当时所会受到的<code>冒犯</code>。</p>
<h2 id="如何避免扮演失败者" tabindex="-1">如何避免扮演失败者 <a class="header-anchor" href="#如何避免扮演失败者" aria-label="Permalink to &quot;如何避免扮演失败者&quot;">&ZeroWidthSpace;</a></h2>
<p>在黑客社区的论坛中，你以本指南所描述的或类似的方式，可能会有那么几次搞砸了。而你会在公开场合中被告知你是如何搞砸的，也许攻击的言语中还会带点夹七夹八的颜色。</p>
<p>这种事发生以后，你能做的最糟糕的事莫过于哀嚎你的遭遇、宣称被言语攻击、要求道歉、高声尖叫、憋闷气、威胁诉诸法律、向其雇主报怨、不去关马桶盖等等。相反地，你该这么做：</p>
<p>熬过去，这很正常。事实上，它是有益健康且合理的。</p>
<p>社区的标准不会自行维持，它们是通过参与者积极而<strong>公开地</strong>执行来维持的。不要哭嚎所有的批评都应该通过私下的邮件传送，它不是这样运作的。当有人评论你的一个说法有误或者提出不同看法时，坚持声称受到个人攻击也毫无益处，这些都是失败者的态度。</p>
<p>也有其它的黑客论坛，受过高礼节要求的误导，禁止参与者张贴任何对别人帖子挑毛病的消息，并声称<code>如果你不想帮助用户就闭嘴。</code> 结果造成有想法的参与者纷纷离开，这么做只会使它们沦为毫无意义的唠叨与无用的技术论坛。</p>
<p>夸张的讲法是：你要的是“友善”（以上述方式）还是有用？两个里面挑一个。</p>
<p>记着：当黑客说你搞砸了，并且（无论多么刺耳）告诉你别再这样做时，他正在为关心<strong>你</strong>和<strong>他的社区</strong>而行动。对他而言，不理你并将你从他的生活中滤掉更简单。如果你无法做到感谢，至少要表现得有点尊严，别大声哀嚎，也别因为自己是个有戏剧性超级敏感的灵魂和自以为有资格的新来者，就指望别人像对待脆弱的洋娃娃那样对你。</p>
<p>有时候，即使你没有搞砸（或者只是在他的想像中你搞砸了），有些人也会无缘无故地攻击你本人。在这种情况下，抱怨倒是<strong>真的</strong>会把问题搞砸。</p>
<p>这些来找麻烦的人要么是毫无办法但自以为是专家的不中用家伙，要么就是测试你是否真会搞砸的心理专家。其它读者要么不理睬，要么用自己的方式对付他们。这些来找麻烦的人在给他们自己找麻烦，这点你不用操心。</p>
<p>也别让自己卷入口水战，最好不要理睬大多数的口水战 —— 当然，这是在你检验它们只是口水战，并且未指出你有搞砸的地方，同时也没有巧妙地将问题真正的答案藏于其后（这也是有可能的）。</p>
<h2 id="不该问的问题" tabindex="-1">不该问的问题 <a class="header-anchor" href="#不该问的问题" aria-label="Permalink to &quot;不该问的问题&quot;">&ZeroWidthSpace;</a></h2>
<p>以下是几个经典蠢问题，以及黑客没回答时心中所想的：</p>
<p>问题：<a href="https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md#q1" target="_blank" rel="noreferrer">我能在哪找到 X 程序或 X 资源？</a></p>
<p>问题：<a href="https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md#q2" target="_blank" rel="noreferrer">我怎样用 X 做 Y？</a></p>
<p>问题：<a href="https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md#q3" target="_blank" rel="noreferrer">如何设定我的 shell 提示？</a></p>
<p>问题：<a href="https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md#q4" target="_blank" rel="noreferrer">我可以用 Bass-o-matic 文件转换工具将 AcmeCorp 文件转换为 TeX 格式吗？</a></p>
<p>问题：<a href="https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md#q5" target="_blank" rel="noreferrer">我的程序/设定/SQL 语句没有用</a></p>
<p>问题：<a href="https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md#q6" target="_blank" rel="noreferrer">我的 Windows 电脑有问题，你能帮我吗？</a></p>
<p>问题：<a href="https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md#q7" target="_blank" rel="noreferrer">我的程序不会动了，我认为系统工具 X 有问题</a></p>
<p>问题：<a href="https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md#q8" target="_blank" rel="noreferrer">我在安装 Linux（或者 X ）时有问题，你能帮我吗？</a></p>
<p>问题：<a href="https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md#q9" target="_blank" rel="noreferrer">我怎么才能破解 root 帐号/窃取 OP 特权/读别人的邮件呢？</a></p>
<hr>
<blockquote>
<p>问题：我能在哪找到 X 程序或 X 资源？</p>
</blockquote>
<p>回答：就在我找到它的地方啊，白痴 —— 搜索引擎的那一头。天哪！难道还有人不会用 <a href="https://www.google.com/" target="_blank" rel="noreferrer">Google</a> 吗？</p>
<blockquote>
<p>问题：我怎样用 X 做 Y？</p>
</blockquote>
<p>回答：如果你想解决的是 Y ，提问时别给出可能并不恰当的方法。这种问题说明提问者不但对 X 完全无知，也对 Y 要解决的问题糊涂，还被特定形势禁锢了思维。最好忽略这种人，等他们把问题搞清楚了再说。</p>
<blockquote>
<p>问题：如何设定我的 shell 提示？？</p>
</blockquote>
<p>回答：如果你有足够的智慧提这个问题，你也该有足够的智慧去 <a href="https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md#RTFM" target="_blank" rel="noreferrer">RTFM</a>，然后自己去找出来。</p>
<blockquote>
<p>问题：我可以用 Bass-o-matic 文件转换工具将 AcmeCorp 文件转换为 TeX 格式吗？</p>
</blockquote>
<p>回答：试试看就知道了。如果你试过，你就知道了答案，就不用浪费我的时间了。</p>
<blockquote>
<p>问题：我的{程序/设定/SQL 语句}没有用</p>
</blockquote>
<p>回答：这不算是问题吧，我对要我问你二十个问题才找得出你真正问题的问题没兴趣 —— 我有更有意思的事要做呢。在看到这类问题的时候，我的反应通常不外如下三种</p>
<ul>
<li>你还有什么要补充的吗？</li>
<li>真糟糕，希望你能搞定。</li>
<li>这关我屁事？</li>
</ul>
<blockquote>
<p>问题：我的 Windows 电脑有问题，你能帮我吗？</p>
</blockquote>
<p>回答：能啊，扔掉微软的垃圾，换个像 Linux 或 BSD 的开源操作系统吧。</p>
<p>注意：如果程序有官方版 Windows 或者与 Windows 有互动（如 Samba），你<strong>可以</strong>问与 Windows 相关的问题，只是别对问题是由 Windows 操作系统而不是程序本身造成的回复感到惊讶， 因为 Windows 一般来说实在太烂，这种说法通常都是对的。</p>
<blockquote>
<p>问题：我的程序不会动了，我认为系统工具 X 有问题</p>
</blockquote>
<p>回答：你完全有可能是第一个注意到被成千上万用户反复使用的系统调用与函数库文件有明显缺陷的人，更有可能的是你完全没有根据。不同凡响的说法需要不同凡响的证据，当你这样声称时，你必须有清楚而详尽的缺陷说明文件作后盾。</p>
<blockquote>
<p>问题：我在安装 Linux（或者 X ）时有问题，你能帮我吗？</p>
</blockquote>
<p>回答：不能，我只有亲自在你的电脑上动手才能找到毛病。还是去找你当地的 Linux 使用群组者寻求实际的指导吧（你能在<a href="http://www.linux.org/groups/index.html" target="_blank" rel="noreferrer">这儿</a>找到用户群组的清单）。</p>
<p>注意：如果安装问题与某 Linux 的发行版有关，在它的邮件列表、论坛或本地用户群组中提问也许是恰当的。此时，应描述问题的准确细节。在此之前，先用 <code>Linux</code> 和<strong>所有</strong>被怀疑的硬件作关键词仔细搜索。</p>
<blockquote>
<p>问题：我怎么才能破解 root 帐号/窃取 OP 特权/读别人的邮件呢？</p>
</blockquote>
<p>回答：想要这样做，说明了你是个卑鄙小人；想找个黑客帮你，说明你是个白痴！</p>
<h2 id="好问题与蠢问题" tabindex="-1">好问题与蠢问题 <a class="header-anchor" href="#好问题与蠢问题" aria-label="Permalink to &quot;好问题与蠢问题&quot;">&ZeroWidthSpace;</a></h2>
<p>最后，我将透过举一些例子，来说明怎样聪明的提问；同一个问题的两种问法被放在一起，一种是愚蠢的，另一种才是明智的。</p>
<p><strong>蠢问题</strong>：</p>
<blockquote>
<p>我可以在哪儿找到关于 Foonly Flurbamatic 的资料？</p>
</blockquote>
<p>这种问法无非想得到 <a href="https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md#RTFM" target="_blank" rel="noreferrer">STFW</a> 这样的回答。</p>
<p><strong>聪明问题</strong>：</p>
<blockquote>
<p>我用 Google 搜索过 &quot;Foonly Flurbamatic 2600&quot;，但是没找到有用的结果。谁知道上哪儿去找对这种设备编程的资料？</p>
</blockquote>
<p>这个问题已经 STFW 过了，看起来他真的遇到了麻烦。</p>
<p><strong>蠢问题</strong>：</p>
<blockquote>
<p>我从 foo 项目找来的源码没法编译。它怎么这么烂？</p>
</blockquote>
<p>他觉得都是别人的错，这个傲慢自大的提问者。</p>
<p><strong>聪明问题</strong>：</p>
<blockquote>
<p>foo 项目代码在 Nulix 6.2 版下无法编译通过。我读过了 FAQ，但里面没有提到跟 Nulix 有关的问题。这是我编译过程的记录，我有什么做的不对的地方吗？</p>
</blockquote>
<p>提问者已经指明了环境，也读过了 FAQ，还列出了错误，并且他没有把问题的责任推到别人头上，他的问题值得被关注。</p>
<p><strong>蠢问题</strong>：</p>
<blockquote>
<p>我的主机板有问题了，谁来帮我？</p>
</blockquote>
<p>某黑客对这类问题的回答通常是：<code>好的，还要帮你拍拍背和换尿布吗？</code>，然后按下删除键。</p>
<p><strong>聪明问题</strong>：</p>
<blockquote>
<p>我在 S2464 主机板上试过了 X 、 Y 和 Z ，但没什么作用，我又试了 A 、 B 和 C 。请注意当我尝试 C 时的奇怪现象。显然 florbish 正在 grommicking，但结果出人意料。通常在 Athlon MP 主机板上引起 grommicking 的原因是什么？有谁知道接下来我该做些什么测试才能找出问题？</p>
</blockquote>
<p>这个家伙，从另一个角度来看，值得去回答他。他表现出了解决问题的能力，而不是坐等天上掉答案。</p>
<p>在最后一个问题中，注意<code>告诉我答案</code>和<code>给我启示，指出我还应该做什么诊断工作</code>之间微妙而又重要的区别。</p>
<p>事实上，后一个问题源自于 2001 年 8 月在 Linux 内核邮件列表（lkml）上的一个真实的提问。我（Eric）就是那个提出问题的人。我在 Tyan S2464 主板上观察到了这种无法解释的锁定现象，列表成员们提供了解决这一问题的重要信息。</p>
<p>通过我的提问方法，我给了别人可以咀嚼玩味的东西；我设法让人们很容易参与并且被吸引进来。我显示了自己具备和他们同等的能力，并邀请他们与我共同探讨。通过告诉他们我所走过的弯路，以避免他们再浪费时间，我也表明了对他们宝贵时间的尊重。</p>
<p>事后，当我向每个人表示感谢，并且赞赏这次良好的讨论经历的时候，一个 Linux 内核邮件列表的成员表示，他觉得我的问题得到解决并非由于我是这个列表中的<strong>名</strong>人，而是因为我用了正确的方式来提问。</p>
<p>黑客从某种角度来说是拥有丰富知识但缺乏人情味的家伙；我相信他是对的，如果我<strong>像</strong>个乞讨者那样提问，不论我是谁，一定会惹恼某些人或者被他们忽视。他建议我记下这件事，这直接导致了本指南的出现。</p>
<h2 id="如果得不到回答" tabindex="-1">如果得不到回答 <a class="header-anchor" href="#如果得不到回答" aria-label="Permalink to &quot;如果得不到回答&quot;">&ZeroWidthSpace;</a></h2>
<p>如果仍得不到回答，请不要以为我们觉得无法帮助你。有时只是看到你问题的人不知道答案罢了。没有回应不代表你被忽视，虽然不可否认这种差别很难区分。</p>
<p>总的来说，简单地重复张贴问题是个很糟的点子。这将被视为无意义的喧闹。有点耐心，知道你问题答案的人可能生活在不同的时区，可能正在睡觉，也有可能你的问题一开始就没有组织好。</p>
<p>你可以通过其他渠道获得帮助，这些渠道通常更适合初学者的需要。</p>
<p>有许多网上的以及本地的用户群组，由热情的软件爱好者（即使他们可能从没亲自写过任何软件）组成。通常人们组建这样的团体来互相帮助并帮助新手。</p>
<p>另外，你可以向很多商业公司寻求帮助，不论公司大还是小。别为要付费才能获得帮助而感到沮丧！毕竟，假使你的汽车发动机汽缸密封圈爆掉了 —— 完全可能如此 —— 你还得把它送到修车铺，并且为维修付费。就算软件没花费你一分钱，你也不能强求技术支持总是免费的。</p>
<p>对像是 Linux 这种大众化的软件，每个开发者至少会对应到上万名用户。根本不可能由一个人来处理来自上万名用户的求助电话。要知道，即使你要为这些协助付费，和你所购买的同类软件相比，你所付出的也是微不足道的（通常封闭源代码软件的技术支持费用比开源软件的要高得多，且内容也没那么丰富）。</p>
<h2 id="如何更好地回答问题" tabindex="-1">如何更好地回答问题 <a class="header-anchor" href="#如何更好地回答问题" aria-label="Permalink to &quot;如何更好地回答问题&quot;">&ZeroWidthSpace;</a></h2>
<p><strong>态度和善一点。</strong> 问题带来的压力常使人显得无礼或愚蠢，其实并不是这样。</p>
<p><strong>对初犯者私下回复。</strong> 对那些坦诚犯错之人没有必要当众羞辱，一个真正的新手也许连怎么搜索或在哪找常见问题都不知道。</p>
<p><strong>如果你不确定，一定要说出来！</strong> 一个听起来权威的错误回复比没有还要糟，别因为听起来像个专家很好玩，就给别人乱指路。要谦虚和诚实，给提问者与同行都树个好榜样。</p>
<p><strong>如果帮不了忙，也别妨碍他。</strong> 不要在实际步骤上开玩笑，那样也许会毁了提问者的设置 —— 有些可怜的呆瓜会把它当成真的指令。</p>
<p><strong>试探性的反问以引出更多的细节。</strong> 如果你做得好，提问者可以学到点东西 —— 你也可以。试试将蠢问题转变成好问题，别忘了我们都曾是新手。</p>
<p>尽管对那些懒虫抱怨一声 RTFM 是正当的，但能给出文档的链接（即使只是建议个 Google 搜索关键词）会更好。</p>
<p><strong>如果你决定回答，就请给出好的答案。</strong> 当别人正在用错误的工具或方法时别建议笨拙的权宜之计（workaround），应推荐更好的工具，重新界定问题。</p>
<p><strong>正面地回答问题！</strong> 如果这个提问者已经很深入的研究而且也表明已经试过 X 、 Y 、 Z 、 A 、 B 、 C 但没得到结果，回答 <code>试试看 A 或是 B</code> 或者 <code>试试 X 、 Y 、 Z 、 A 、 B 、 C</code> 并附上一个链接一点用都没有。</p>
<p><strong>帮助你的社区从问题中学习。</strong> 当回复一个好问题时，问问自己<code>如何修改相关文件或常见问题文件以免再次解答同样的问题？</code>，接着再向文件维护者发一份补丁。</p>
<p>如果你在研究一番后才作出了回答，<strong>展现你的技巧而不是直接端出结果</strong>。毕竟<code>授人以鱼不如授人以渔</code>。</p>
]]></content>
        <author>
            <name>duyl328</name>
            <uri>https://seyl.me/about</uri>
        </author>
        <category label="转载"/>
        <category label="思考"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[软件工程师简历撰写的实用指南]]></title>
        <id>https://seyl.me/posts/2025/04/a-guide-to-writing-a-resume-for-software-engineers</id>
        <link href="https://seyl.me/posts/2025/04/a-guide-to-writing-a-resume-for-software-engineers"/>
        <updated>2025-04-09T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[<h1 id="frontmatter-title-转载" tabindex="-1">{{ $frontmatter.title }}(转载) <a class="header-anchor" href="#frontmatter-title-转载" aria-label="Permalink to &quot;{{ $frontmatter.title }}(转载)&quot;">&ZeroWidthSpace;</a></h1>
<div class="warning custom-block github-alert"><p class="custom-block-title">版权声明</p>
<p>原文地址地址：<a href="https://www.techinterviewhandbook.org/" target="_blank" rel="noreferrer">https://www.techinterviewhandbook.org/</a></p>
</div>
<blockquote>
<p>✒️ 文章摘要</p>
</blockquote>
<!-- DESC SEP -->
<p>这篇指南为软件工程师求职提供了简明实用的简历与面试建议。<br>
<strong>简历方面</strong>，推荐使用标准格式（Word/Docs 编辑，PDF 提交）、常用字体、窄边距排版，确保 ATS 可识别。内容应聚焦于量化成果、核心技能和关键词，简历长度控制在一页。</p>
<p><strong>结构建议</strong>包括：专业摘要、工作经历、教育背景、项目经验和奖项，强调条理清晰、结果导向。</p>
<p><strong>行为面试部分</strong>介绍了 STAR 答题法（情境-任务-行动-结果）与高频题目，鼓励结合实际经历展现沟通、合作与解决问题能力。</p>
<p>文章还强调简洁有力的自我介绍（电梯游说）和结束提问的重要性，并推荐使用简历优化工具进行自检。</p>
<p>整体目标是：让简历易读、内容精准，展现候选人价值，提升进入大厂面试和拿 offer 的几率。</p>
<!-- DESC SEP -->
<br/>
]]></summary>
        <content type="html"><![CDATA[<h1 id="frontmatter-title-转载" tabindex="-1">{{ $frontmatter.title }}(转载) <a class="header-anchor" href="#frontmatter-title-转载" aria-label="Permalink to &quot;{{ $frontmatter.title }}(转载)&quot;">&ZeroWidthSpace;</a></h1>
<div class="warning custom-block github-alert"><p class="custom-block-title">版权声明</p>
<p>原文地址地址：<a href="https://www.techinterviewhandbook.org/" target="_blank" rel="noreferrer">https://www.techinterviewhandbook.org/</a></p>
</div>
<blockquote>
<p>✒️ 文章摘要</p>
</blockquote>
<!-- DESC SEP -->
<p>这篇指南为软件工程师求职提供了简明实用的简历与面试建议。<br>
<strong>简历方面</strong>，推荐使用标准格式（Word/Docs 编辑，PDF 提交）、常用字体、窄边距排版，确保 ATS 可识别。内容应聚焦于量化成果、核心技能和关键词，简历长度控制在一页。</p>
<p><strong>结构建议</strong>包括：专业摘要、工作经历、教育背景、项目经验和奖项，强调条理清晰、结果导向。</p>
<p><strong>行为面试部分</strong>介绍了 STAR 答题法（情境-任务-行动-结果）与高频题目，鼓励结合实际经历展现沟通、合作与解决问题能力。</p>
<p>文章还强调简洁有力的自我介绍（电梯游说）和结束提问的重要性，并推荐使用简历优化工具进行自检。</p>
<p>整体目标是：让简历易读、内容精准，展现候选人价值，提升进入大厂面试和拿 offer 的几率。</p>
<!-- DESC SEP -->
<br/>
<hr>
<br/>
<h1 id="完善简历" tabindex="-1">完善简历 <a class="header-anchor" href="#完善简历" aria-label="Permalink to &quot;完善简历&quot;">&ZeroWidthSpace;</a></h1>
<p>作为 <code>FAANG</code><sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup> 面试官阅读了大量软件工程简历，即使是我认识的一些最合格的候选人也因简历不佳而未能入围。大多数人犯的错误是立即假设他们不够合格 —— 但这可能远非事实。</p>
<p>值得庆幸的是，您可以满足一些特定的步骤和要求来撰写一份优秀的软件工程师简历。从您的简历结构、内容到可用于测试简历的免费工具，我整理了一份非常简洁的最佳实践摘要，以准备您的 <code>FAANG</code> 软件工程工作申请的简历：</p>
<ol>
<li>设置适合 <code>ATS</code><sup class="footnote-ref"><a href="#fn2" id="fnref2">[2]</a></sup> 的简历模板</li>
<li>以有意义的顺序用结构良好的内容填充您的模板</li>
<li>通过优先级和关键词优化您的简历</li>
<li>使用免费工具测试简历</li>
</ol>
<h2 id="仅使用-microsoft-word-或-google-docs-创建和编辑您的简历" tabindex="-1">仅使用 Microsoft Word 或 Google Docs 创建和编辑您的简历 <a class="header-anchor" href="#仅使用-microsoft-word-或-google-docs-创建和编辑您的简历" aria-label="Permalink to &quot;仅使用 Microsoft Word 或 Google Docs 创建和编辑您的简历&quot;">&ZeroWidthSpace;</a></h2>
<p><strong>建议：</strong></p>
<ul>
<li>以 PDF 文件的形式提交您的简历以保留格式，但始终从 Microsoft Word 或 Google Docs 编辑它。确保简历中的文本清晰可见非常重要，这是轻松解析的前提条件。</li>
<li><code>ATS</code> 工具一直在努力提高它们对标准简历格式的可读性——因此你的简历格式越常见越好。</li>
<li>为了最大限度地利用简历上的空间，不要使用页眉或页脚，而是减少页面的边距 - 每边的窄边距为 0.5。</li>
</ul>
<p><strong>不建议：</strong></p>
<ul>
<li>不要使用 Photoshop、其他图形设计工具或在线简历生成器来构建您的简历</li>
<li>不要在 Word/Google Docs 文件中使用页眉或页脚部分 - 减少边距，只将信息写入正文中。</li>
</ul>
<h3 id="仅使用可读大小的标准字体" tabindex="-1">仅使用可读大小的标准字体 <a class="header-anchor" href="#仅使用可读大小的标准字体" aria-label="Permalink to &quot;仅使用可读大小的标准字体&quot;">&ZeroWidthSpace;</a></h3>
<p>新字体可能会将字母转换为 <code>ATS</code> 无法读取的特殊字符。您应该使用的字体 - <strong>Arial、Calibri、Garamond</strong>。</p>
<p>确保您的字体大小在招聘流程的后期对人类保持可读性 - 使用最小 <strong>10 像素</strong>的大小以确保可读性。</p>
<h2 id="好的软件工程师简历" tabindex="-1">好的软件工程师简历 <a class="header-anchor" href="#好的软件工程师简历" aria-label="Permalink to &quot;好的软件工程师简历&quot;">&ZeroWidthSpace;</a></h2>
<p>由于软件工程在所需的技能和经验方面与其他职业有着本质上的不同，因此对软件工程师简历的内容期望也是独一无二的。</p>
<h3 id="撰写专业总结" tabindex="-1">撰写专业总结 <a class="header-anchor" href="#撰写专业总结" aria-label="Permalink to &quot;撰写专业总结&quot;">&ZeroWidthSpace;</a></h3>
<p>根据我作为软件工程面试官的个人经验，我强烈推荐专业的摘要，因为面试官通常可能没有时间阅读细节——因此直接说明为什么候选人适合这份工作的摘要可以大大提高他们吸引注意力的机会。</p>
<p>以下是我撰写出色的软件工程简历摘要的重要技巧。</p>
<h4 id="开始之前-列出您的最佳优势" tabindex="-1">开始之前：列出您的最佳优势 <a class="header-anchor" href="#开始之前-列出您的最佳优势" aria-label="Permalink to &quot;开始之前：列出您的最佳优势&quot;">&ZeroWidthSpace;</a></h4>
<p>从您的整个专业经验中，列出满足您申请的职位描述的最重要要点。这可能包括工作经验或技能。</p>
<h4 id="将优势总结到你的简历摘要中" tabindex="-1">将优势总结到你的简历摘要中 <a class="header-anchor" href="#将优势总结到你的简历摘要中" aria-label="Permalink to &quot;将优势总结到你的简历摘要中&quot;">&ZeroWidthSpace;</a></h4>
<p>尽量总结优势，把它们框定成一个50字以内的简短总结：</p>
<p>可以参照以下内容：</p>
<p>✅ <strong>说明你为什么适合这份工作</strong><br>
✅ <strong>使用主动语态表达 (如“我做了 XXX”)</strong>
✅ <strong>多用行动性动词（如“设计”、“推动”、“优化”等）</strong><br>
✅ <strong>用职位名称作为句子的开头，例如：“软件工程师”、“前端工程师”</strong></p>
<h4 id="为简历摘要定义一个标题" tabindex="-1">为简历摘要定义一个标题 <a class="header-anchor" href="#为简历摘要定义一个标题" aria-label="Permalink to &quot;为简历摘要定义一个标题&quot;">&ZeroWidthSpace;</a></h4>
<p>与其将“专业摘要”作为该部分的标题，不如将您的经验进一步简化为少于 10 个字的标题。</p>
<p>如：</p>
<h5 id="软件工程师-全栈" tabindex="-1">软件工程师 （全栈） <a class="header-anchor" href="#软件工程师-全栈" aria-label="Permalink to &quot;软件工程师 （全栈）&quot;">&ZeroWidthSpace;</a></h5>
<p>拥有 X 年全栈 Web 开发经验的软件工程师，专门研究 Ruby on Rails 和 PostgreSQL。由于在多家电子商务公司工作，因此成为电子商务和支付领域的专家。</p>
<h5 id="高级前端工程师" tabindex="-1">高级前端工程师 <a class="header-anchor" href="#高级前端工程师" aria-label="Permalink to &quot;高级前端工程师&quot;">&ZeroWidthSpace;</a></h5>
<p>前端工程师，拥有 X 年的经验和强大的前端技术基础。喜欢构建可扩展的 Web 基础设施和使网站更快。热衷于编程语言、编译器和开发人员工具。</p>
<h5 id="软件工程主管" tabindex="-1">软件工程主管 <a class="header-anchor" href="#软件工程主管" aria-label="Permalink to &quot;软件工程主管&quot;">&ZeroWidthSpace;</a></h5>
<p>软件工程师，在后端、扩展复杂的分布式系统和各种云平台方面拥有 X 年的经验。领导了两家公司的 5 多个工程团队，平均规模为 6 人，并指导了 20 多名初级成员。</p>
<h5 id="x-大学大四" tabindex="-1">X 大学大四 <a class="header-anchor" href="#x-大学大四" aria-label="Permalink to &quot;X 大学大四&quot;">&ZeroWidthSpace;</a></h5>
<p>X 大学大四学生，主修人工智能和机器学习 （ML）。在 X 公司实习，担任全栈开发和 ML 工程角色。</p>
<h3 id="撰写工作经验" tabindex="-1">撰写工作经验 <a class="header-anchor" href="#撰写工作经验" aria-label="Permalink to &quot;撰写工作经验&quot;">&ZeroWidthSpace;</a></h3>
<p>以熟悉的格式和时间倒序列出您的工作经验。列出的每个职位都应该有：</p>
<p>公司、地点、职称、工作时长遵循此结构</p>
<blockquote>
<p>[公司或组织]、[位置] |[职称] |[开始日期和结束日期格式为 MM/YYYY]</p>
</blockquote>
<p>例</p>
<blockquote>
<p>Facebook， 新加坡 |前端工程主管 |2018 年 8 月 - 至今</p>
</blockquote>
<p>主要成就列表，包括：</p>
<ul>
<li>工作范围和所需技能</li>
<li>按照此结构列出的成就
<ul>
<li>
<blockquote>
<p>[成就总结] ： 导致 [可量化结果] 的 [成果]</p>
</blockquote>
</li>
</ul>
</li>
</ul>
<h3 id="撰写教育经历" tabindex="-1">撰写教育经历 <a class="header-anchor" href="#撰写教育经历" aria-label="Permalink to &quot;撰写教育经历&quot;">&ZeroWidthSpace;</a></h3>
<p>大多数软件工程工作至少需要本科学位。但是，除非您是应届毕业生或没有太多工作经验，<strong>否则不应将其置于您的工作经验之上</strong>。</p>
<p>使用以下格式，删除不相关的信息：</p>
<blockquote>
<p>[学位名称]， [毕业年份 - 如果未毕业，请写下预期毕业日期]<br>
[大学名称]，[位置]<br>
GPA： X.XX / 4.0 （如果超过 3.50/4.00，则列出 GPA，或在 5 分制下超过 4.3）<br>
列出关键成就，包括领导职位、技能、社团、项目、奖项等。</p>
</blockquote>
<p>例：</p>
<blockquote>
<p>计算机、计算机科学学士， 2015<br>
年毕业 新加坡国立大学， 新加坡<br>
GPA： 3.82 / 4.00 （Magna cum laude）<br>
院长名单，骇客协会<br>
主席</p>
</blockquote>
<h3 id="撰写项目经验" tabindex="-1">撰写项目经验 <a class="header-anchor" href="#撰写项目经验" aria-label="Permalink to &quot;撰写项目经验&quot;">&ZeroWidthSpace;</a></h3>
<p>包括至少 2 个您参与的项目，并概述您的主要贡献。始终尝试将您的项目名称链接到 GitHub 或招聘经理可以查看您的项目的地方。</p>
<blockquote>
<p><a href="https://github.com/facebook/docusaurus" target="_blank" rel="noreferrer">facebook/docusaurus Docusaurus</a><br>
v2 的维护者和首席工程师，Docusaurus v2 是一个静态站点生成器，为 Meta 的许多开源项目提供文档支持，包括 React Native、Jest、Relay、Reason 等。在 GitHub 有超 7.6k 项目使用。</p>
</blockquote>
<h3 id="撰写奖项、荣誉和认证" tabindex="-1">撰写奖项、荣誉和认证 <a class="header-anchor" href="#撰写奖项、荣誉和认证" aria-label="Permalink to &quot;撰写奖项、荣誉和认证&quot;">&ZeroWidthSpace;</a></h3>
<p>仅包含与工作申请相关的成就，并尝试量化您的成就。一个好的格式是</p>
<blockquote>
<p>[年份][定量] [比赛]</p>
</blockquote>
<p>例</p>
<blockquote>
<p>2016 年 |50 支球队中的最佳全能产品 |Facebook 黑客马拉松</p>
</blockquote>
<h2 id="使用关键字优化简历" tabindex="-1">使用关键字优化简历 <a class="header-anchor" href="#使用关键字优化简历" aria-label="Permalink to &quot;使用关键字优化简历&quot;">&ZeroWidthSpace;</a></h2>
<p>优化内容的必备条件：</p>
<h3 id="少即是多" tabindex="-1">少即是多 <a class="header-anchor" href="#少即是多" aria-label="Permalink to &quot;少即是多&quot;">&ZeroWidthSpace;</a></h3>
<p><strong>应该做的事</strong></p>
<ul>
<li>突出您的一些最佳成就比在简历中包含许多“平均”成就要好</li>
<li>简历只用 1 页</li>
</ul>
<p><strong>注意 事项</strong></p>
<ul>
<li>不要列出你的所有成就，不要只是为了展示更多的成就而不进行筛选</li>
</ul>
<h3 id="关键词优化" tabindex="-1">关键词优化 <a class="header-anchor" href="#关键词优化" aria-label="Permalink to &quot;关键词优化&quot;">&ZeroWidthSpace;</a></h3>
<p>想象一下，您是一名招聘经理或招聘人员，一边筛选简历，一边处理工作中的许多其他任务。您根本不会有太多时间处理每份简历！当招聘经理查看简历时，他们实际上是在快速扫描他们重视的技能或经验的关键词，然后再额外关注您的简历。</p>
<p>招聘人员和 <code>ATS</code> 也会这样做，但要根据招聘经理帮助编写的职位描述。这就是为什么根据职位描述优化简历非常重要的原因。</p>
<div class="info custom-block github-alert"><p class="custom-block-title">信息</p>
<p>一些 ATS 会根据简历中关键字的频率来确定您的技能强度，而另一些 ATS 会根据技能在简历中的位置分配技能的估计经验量。</p>
<p>例如，如果您之前的工作经验为 3 年，并且您提到处理搜索引擎营销 （SEM），则 ATS 将假定您有 5 年的 SEM 经验。</p>
</div>
<h4 id="在简历中包含职位描述中的关键字" tabindex="-1">在简历中包含职位描述中的关键字 <a class="header-anchor" href="#在简历中包含职位描述中的关键字" aria-label="Permalink to &quot;在简历中包含职位描述中的关键字&quot;">&ZeroWidthSpace;</a></h4>
<p>您应该首先分析职位描述中必须具备和最好具备的技能或经验，并确保将关键字添加到您的简历中。</p>
<p>将它们包含在 “技能” 部分下，并将相同的关键词加入 “工作经验 ”和 “教育 ”部分。请务必严格模仿职位描述中的语言。</p>
<p>请记住还要包含常见缩写的完整版本。例如，使用 Amazon Web Services 而不是 AWS，使用 Google Cloud Platform 而不是 GCP。</p>
<p>但是，不要为了它而进行关键字填充 - 永远记住，简历最终会被招聘人员或招聘经理阅读。</p>
<h4 id="优化关键词频率和投放" tabindex="-1">优化关键词频率和投放 <a class="header-anchor" href="#优化关键词频率和投放" aria-label="Permalink to &quot;优化关键词频率和投放&quot;">&ZeroWidthSpace;</a></h4>
<p>分析职位描述并确定每项技能和经验的重要性，然后根据其重要性优化关键字的频率。</p>
<div class="tip custom-block github-alert"><p class="custom-block-title">提示</p>
<p>虽然针对每个经验进行优化是理想的，但您可以将您的简历推广到某种类型的职位。</p>
<ol>
<li>为该职位整理 3 到 5 个职位描述</li>
<li>将它们复制并粘贴到文件中，然后将其上传到免费的“单词和短语”频率工具中，例如 <a href="./.html">Online-Utility.org 的文本分析器，</a>以识别经常使用的关键字<code>.txt</code></li>
<li>将您拥有的技能和经验融入简历中</li>
</ol>
</div>
<h2 id="查看简历的免费工具" tabindex="-1">查看简历的免费工具 <a class="header-anchor" href="#查看简历的免费工具" aria-label="Permalink to &quot;查看简历的免费工具&quot;">&ZeroWidthSpace;</a></h2>
<p>我建议使用这些免费工具来优化您的简历：</p>
<h3 id="_1-免费简历审核" tabindex="-1">1. 免费简历审核 <a class="header-anchor" href="#_1-免费简历审核" aria-label="Permalink to &quot;1. 免费简历审核&quot;">&ZeroWidthSpace;</a></h3>
<p>Tech Interview Handbook 有一个<a href="./.html">简历审查门户</a>，您可以在其中上传您的简历并从其他社区成员甚至 Tech Interview Handbook 的作者那里获得有用的评论和反馈！</p>
<p>如果您愿意花一些钱， <a href="./.html">FAANG Tech Leads 的简历审查服务</a> 也是不错的选择，您的简历将由前 FAANG 招聘经理和工程师审查，而不是由不了解技术的随机作者审查。</p>
<h3 id="_2-使用行业标准-ats-测试可读性" tabindex="-1">2. 使用行业标准 ATS 测试可读性 <a class="header-anchor" href="#_2-使用行业标准-ats-测试可读性" aria-label="Permalink to &quot;2. 使用行业标准 ATS 测试可读性&quot;">&ZeroWidthSpace;</a></h3>
<ul>
<li>使用行业标准的 ATS（如 <a href="./.html">Resume Worded</a> 等免费工具测试简历的可读性和格式。大多数大公司都使用这种简历扫描仪。</li>
<li>根据工作要求定制您的简历。您可以使用 [Targeted Resume](</li>
</ul>
<h1 id="行为面试" tabindex="-1">行为面试 <a class="header-anchor" href="#行为面试" aria-label="Permalink to &quot;行为面试&quot;">&ZeroWidthSpace;</a></h1>
<h2 id="什么是行为面试" tabindex="-1">什么是行为面试 <a class="header-anchor" href="#什么是行为面试" aria-label="Permalink to &quot;什么是行为面试&quot;">&ZeroWidthSpace;</a></h2>
<p>在工程事业中取得成功不仅仅涉及技术技能。随着工程师的资历越来越深，人际交往能力变得更加重要。高级工程师应该具备领导和影响、解决冲突、预测风险、规划路线图等的能力。
司希望雇用合适的人，他们能够与现有员工很好地合作，并帮助团队和公司达到更高的高度，而行为面试是从非技术角度确定某人是否适合合作的一种方式。</p>
<h3 id="_1-了解-star-答案格式" tabindex="-1">1. 了解 STAR<sup class="footnote-ref"><a href="#fn3" id="fnref3">[3]</a></sup> 答案格式 <a class="header-anchor" href="#_1-了解-star-答案格式" aria-label="Permalink to &quot;1. 了解 STAR[^3] 答案格式&quot;">&ZeroWidthSpace;</a></h3>
<p><a href="https://en.wikipedia.org/wiki/Situation,_task,_action,_result" target="_blank" rel="noreferrer">STAR</a> 格式是一个框架，可帮助您组织行为问题的答案 - 尤其是那些要求您讨论以前经验的问题</p>
<ul>
<li><strong>情境</strong> - 面试官希望你介绍你最近遇到的挑战和情况</li>
<li><strong>任务</strong> - 您需要完成什么？面试官会想看看你试图从这种情况中达到什么目的。某些性能开发方法使用 “Target” 而不是 “Task”。求职者如果描述的是他们自己设定的 “目标 ”，而不是外部强加的 “任务 ”，则强调他们自己执行和发展绩效的内在动机</li>
<li><strong>行动</strong> - 您做了什么？面试官将寻找有关您做了什么、为什么这样做以及替代方案的信息</li>
<li><strong>结果</strong> - 您的行动结果如何？您通过行动取得了什么成果，学到了什么？体验后，您采取了哪些措施来改进？</li>
</ul>
<h4 id="如何将-star-应用于行为面试问题的示例" tabindex="-1">如何将 STAR 应用于行为面试问题的示例 <a class="header-anchor" href="#如何将-star-应用于行为面试问题的示例" aria-label="Permalink to &quot;如何将 STAR 应用于行为面试问题的示例&quot;">&ZeroWidthSpace;</a></h4>
<p>下面是一个如何使用 STAR 格式来回答问题的示例：“告诉我您遇到冲突并需要影响他人的一次经历”。</p>
<h4 id="情况" tabindex="-1">情况 <a class="header-anchor" href="#情况" aria-label="Permalink to &quot;情况&quot;">&ZeroWidthSpace;</a></h4>
<blockquote>
<p>“我是一个关于构建社交网络移动 Web 应用程序的学校项目的团队负责人。我们的设计师的期中考试快到了，没有时间制作模型。我们的前端人员催促他制作模型，以便他可以继续他的工作，这让设计师感到压力很大。团队的气氛很紧张。</p>
</blockquote>
<h4 id="任务" tabindex="-1">任务 <a class="header-anchor" href="#任务" aria-label="Permalink to &quot;任务&quot;">&ZeroWidthSpace;</a></h4>
<blockquote>
<p>“作为团队负责人，我必须解决前端开发人员和设计师之间的紧张关系，以便团队能够和平合作并按时完成项目。”</p>
</blockquote>
<h4 id="行动" tabindex="-1">行动 <a class="header-anchor" href="#行动" aria-label="Permalink to &quot;行动&quot;">&ZeroWidthSpace;</a></h4>
<blockquote>
<p>“我和前端开发人员谈过，问他为什么急于让设计师进行设计。他说他希望尽早完成设计，因为如果设计师最终设计出不同的东西，重建将是浪费时间。我向他解释说，期中考试日期超出了设计师的控制范围，我们必须更加了解彼此的日程安排。我与设计师交谈，大致了解他的想法，并问他什么时候可以承诺生产高保真设计。他回答说，他可以在期中考试结束后立即开始。我向他解释了为什么前端开发人员要催促他制作模型，而前端开发人员没有恶意，只是希望项目成功。作为在 UI/UX 设计方面有一定经验的人，我提出了线框模拟，由设计师运行它们以获得批准，然后将它们传递给前端开发人员开始构建。我鼓励前端开发人员使用占位符，暂时不要太关心细节。我们可以先构建非 UI 部分（身份验证、与 API 挂钩），然后调整像素并稍后添加润色。前端开发人员同意并继续采用该方法。我向前端开发人员解释说，设计师将在期中考试后，即之前将模型交给我们。</p>
</blockquote>
<h4 id="结果" tabindex="-1">结果 <a class="header-anchor" href="#结果" aria-label="Permalink to &quot;结果&quot;">&ZeroWidthSpace;</a></h4>
<blockquote>
<p>“当我们的设计师结束期中考试时，他带来了漂亮的模型，非常适合。我们的前端开发人员非常注重细节地实现了它们。我们最终在项目中获得了最高分，并成为了一个伟大的团队。</p>
</blockquote>
<h3 id="_2-准备对常见问题的回答" tabindex="-1">2. 准备对常见问题的回答 <a class="header-anchor" href="#_2-准备对常见问题的回答" aria-label="Permalink to &quot;2. 准备对常见问题的回答&quot;">&ZeroWidthSpace;</a></h3>
<p>下一个自然的步骤是开始为常见的行为面试问题准备答案。您可以参考我为此在顶级科技公司整理的 30 个问题清单。</p>
<ol>
<li>你为什么想加入X公司？</li>
<li>你为什么想离开当前/上一家公司？</li>
<li>你在下一份职位中寻求什么？</li>
<li>请举例说明你与同事发生冲突的一次经历。</li>
<li>请描述你曾需要说服他人并化解冲突的案例。</li>
<li>你目前正在参与什么项目？</li>
<li>你当前项目中最具挑战性的部分是什么？</li>
<li>在过去六个月内，你修复过最棘手的漏洞是什么？</li>
<li>你如何应对挑战？请举例说明你在项目中遇到的重大挑战、解决方法及收获。</li>
<li>什么事物会让你感到兴奋？</li>
<li>什么事情会让你感到沮丧？</li>
<li>假设今天是你在公司的第一天，你希望负责什么工作？会优先改进哪些功能？</li>
<li>你参与过哪些与本公司业务相关的最有趣项目？请说明关联性。</li>
<li>请描述你与上级意见不合的一次经历。</li>
<li>谈谈你最热衷或表现最出色的项目。</li>
<li>你理想的最佳工作日是怎样的？</li>
<li>你在过往项目中曾极力推动过什么事情？</li>
<li>你职业生涯中收到过最有建设性的反馈是什么？</li>
<li>你曾持续数月努力攻克过什么难题？</li>
<li>请举例说明你如何在紧迫期限内完成任务。</li>
<li>假设此时是你加入我们公司的第一次年度评估，我现在会对你做出怎样的评价？</li>
<li>时间管理是高效工作的关键。请举例说明你在工作中应用过的时间管理技巧。</li>
<li>请描述你与同事相处困难的经历。</li>
<li>你的工作最常受到哪些方面的批评？</li>
<li>你如何应对他人对你工作的批评？</li>
<li>你认为该岗位最重要的核心能力是什么？</li>
<li>你的同事会用哪三个词形容你？</li>
<li>如果被录用，你希望在前六个月达成什么目标？</li>
<li>请说明你为何适合这个岗位。</li>
<li>你觉得 5 年后的自己会怎样？</li>
</ol>
<p>虽然大多数人可能倾向于背诵，但最好为每个问题写下要点，并在面试时练习用语言表达它们，这样你的答案就会更自然。</p>
<h3 id="_3-准备体验以展示与公司文化-核心价值观的契合度" tabindex="-1">3. 准备体验以展示与公司文化/核心价值观的契合度 <a class="header-anchor" href="#_3-准备体验以展示与公司文化-核心价值观的契合度" aria-label="Permalink to &quot;3. 准备体验以展示与公司文化/核心价值观的契合度&quot;">&ZeroWidthSpace;</a></h3>
<p>如前所述，大多数顶级科技公司在行为面试中使用他们的公司价值观来评估候选人。因此，您应该进行研究，找出这些价值观是什么，并确保您准备好了适合的体验。</p>
<h3 id="行为面试评分标准" tabindex="-1">行为面试评分标准 <a class="header-anchor" href="#行为面试评分标准" aria-label="Permalink to &quot;行为面试评分标准&quot;">&ZeroWidthSpace;</a></h3>
<p>与技术访谈不同，行为访谈在评估标准方面有更大的差异。然而，大多数顶级科技公司都使用他们的公司价值观来评估候选人。面试官通常必须填写一个部分，以评估候选人如何表现出符合公司价值观的行为。正是出于这个原因，您应该搜索公司的文化和价值观，并确保将它们体现在您的答案中。您还会发现，与目前在您申请的公司工作的一位联系人交谈会很有用，以了解更多关于团队中通常重视哪些价值观的信息。</p>
<p>评估的常见值的一些示例包括：</p>
<ul>
<li><strong>动机</strong> - 是什么驱动着你？理想的候选人是自我激励的，对具有真正影响的技术和产品充满热情。</li>
<li><strong>积极主动的能力</strong> - 您能够采取主动吗？给定一个难题，您能否弄清楚如何完成并执行它？</li>
<li><strong>在非结构化环境中工作的能力</strong> - 您在模棱两可的情况下拥有所有权的能力如何？还是依赖别人告诉你该怎么做？</li>
<li><strong>毅力</strong> - 您能够解决困难的问题或障碍吗？</li>
<li><strong>冲突解决</strong> - 您处理和处理具有挑战性的关系的能力如何？</li>
<li><strong>同理心</strong> - 您能够从他人的角度看待事物并理解您的动机吗？</li>
<li><strong>成长</strong> - 您对自己的优势、劣势和成长领域了解多少？您是否在不断努力发展？</li>
<li><strong>沟通</strong> - 您能否在面试中清楚地传达您的故事？</li>
</ul>
<h2 id="自我介绍" tabindex="-1">自我介绍 <a class="header-anchor" href="#自我介绍" aria-label="Permalink to &quot;自我介绍&quot;">&ZeroWidthSpace;</a></h2>
<p>在回答 “tell me about yourself” 时，您可以将问题改写为：</p>
<blockquote>
<p>“跟我说说你进入科技行业的经历吧。您是如何对编码产生兴趣的，为什么 Web 开发（或替换为其他特定工作技能）非常适合您？这如何适用于我们的角色或公司目标？花宝贵的时间谈论与工作无关的事情可能不是一个好主意！</p>
</blockquote>
<h2 id="电梯游说" tabindex="-1">电梯游说 <a class="header-anchor" href="#电梯游说" aria-label="Permalink to &quot;电梯游说&quot;">&ZeroWidthSpace;</a></h2>
<p>“电梯游说”起源于记者试图向编辑推销一个想法。唯一能抓住编辑的时间是在电梯里，她只有大约 30 秒的时间。电梯演讲的关键要素包括：</p>
<ul>
<li><strong>简短</strong> - 您的时间有限！</li>
<li><strong>直接</strong> - 由于您的时间有限，因此您应该直奔主题</li>
<li><strong>引人注目</strong> - 展示您最有吸引力的想法</li>
</ul>
<p>无论您是与数百名其他候选人一起参加招聘会，但时间有限，还是只是向潜在的联系人或客户解释您是谁，能够快速简洁地清晰准确地描述您的知识和技能都很重要。您的自我介绍是您自己的电梯游说！</p>
<p>以下是一些为您的软件工程师自我介绍制定好的电梯游说的技巧：</p>
<h3 id="_1-从基本背景信息开始" tabindex="-1">1. 从基本背景信息开始 <a class="header-anchor" href="#_1-从基本背景信息开始" aria-label="Permalink to &quot;1. 从基本背景信息开始&quot;">&ZeroWidthSpace;</a></h3>
<p>包括您是谁、您为谁工作（或学校和专业）以及您做什么。</p>
<ul>
<li><strong>实习</strong> - 您应该提及以下内容：姓名、学校和专业、重点领域、过去的实习和/或值得注意的项目</li>
<li><strong>全职</strong> - 您应该提及以下内容：姓名、过去的公司、值得注意的项目（最好是他们听说过的公共消费产品）</li>
</ul>
<p>这看起来很熟悉吗？应该是的，因为它和你的简历很相似！你的简历是你知识和经验的浓缩版，而<strong>你的自我介绍本质上是你简历的浓缩版</strong>。随着年龄的增长，专业经验变得更加重要，学校背景变得不那么重要。因此，随着您变得更资深，您的自我介绍会发生变化。</p>
<h3 id="_2-kiss-保持简单甜美" tabindex="-1">2. KISS （保持简单甜美） <a class="header-anchor" href="#_2-kiss-保持简单甜美" aria-label="Permalink to &quot;2. KISS （保持简单甜美）&quot;">&ZeroWidthSpace;</a></h3>
<p>告诉他们您最喜欢/最令人印象深刻的项目中的一些亮点，如果它们令人印象深刻或您克服了挑战，请包括一些数字。不要深入研究如何对游戏进行逆向工程和解密数据包，以预测何时在掉线时使用 DKP。告诉他们执行摘要：“我通过解密 Y 数据包来预测 Z，对 X 游戏进行逆向工程。如果这引起了他们的兴趣，他们可能会自己提出进一步的问题。</p>
<h3 id="_3-他们为什么需要你" tabindex="-1">3. 他们为什么需要你？ <a class="header-anchor" href="#_3-他们为什么需要你" aria-label="Permalink to &quot;3. 他们为什么需要你？&quot;">&ZeroWidthSpace;</a></h3>
<p>告诉面试官为什么你会成为一个好的招聘对象。您的经验与公司相关吗？您是否使用过与公司类似的技术堆栈或构建了相关产品？您有哪些独特的才能可以让他们对您为公司做出贡献的能力充满信心？</p>
<h3 id="_4-练习" tabindex="-1">4. 练习！ <a class="header-anchor" href="#_4-练习" aria-label="Permalink to &quot;4. 练习！&quot;">&ZeroWidthSpace;</a></h3>
<p>最后，你必须练习你的自我介绍！只有当您能够真正快速自然的自我介绍，对您的技能进行出色、简洁的总结才会有所帮助！您应该练习保持快速但易于遵循的步伐，这不会让他们不知所措，但不会让他们感到厌烦。这是一个不稳定的平衡，但可以通过练习来解决。</p>
<p>在想出你的自我介绍后，把它放在你以后可以参考/调整的地方。记住它们，将来你可以在需要时使用它，但当你真正说出来时，不要听起来像是从记忆中回忆起它。听起来很自然！</p>
<h3 id="例子" tabindex="-1">例子 <a class="header-anchor" href="#例子" aria-label="Permalink to &quot;例子&quot;">&ZeroWidthSpace;</a></h3>
<h3 id="示例-1-meta-的前端工程师" tabindex="-1">示例 1：Meta 的前端工程师 <a class="header-anchor" href="#示例-1-meta-的前端工程师" aria-label="Permalink to &quot;示例 1：Meta 的前端工程师&quot;">&ZeroWidthSpace;</a></h3>
<h4 id="自我介绍-1" tabindex="-1">自我介绍 <a class="header-anchor" href="#自我介绍-1" aria-label="Permalink to &quot;自我介绍&quot;">&ZeroWidthSpace;</a></h4>
<blockquote>
<p>“嗨，我是 XXX，我于 2015 年毕业于新加坡国立大学，获得计算机科学学位。我的兴趣是前端工程，我喜欢创造美观、高性能的产品，并提供令人愉悦的用户体验。</p>
<p>回到学校后，我设计并构建了一个 Web 应用程序 NUSMods，它解决了每学期课程和时间表规划的巨大问题。它每月收到超过 100 万次浏览量，被超过 40,000 名 NUS 学生甚至一些教授使用。它是使用现代 Web 技术堆栈构建的 - React、Redux、Jest、Babel、Flow、webpack，并且是移动响应式的。</p>
<p>我对 Meta 的前端工程师角色很感兴趣，因为我已经使用 Meta 开源前端技术有一段时间了，并且受到 Meta 的使命和开源文化的启发。</p>
</blockquote>
<h4 id="分解" tabindex="-1">分解 <a class="header-anchor" href="#分解" aria-label="Permalink to &quot;分解&quot;">&ZeroWidthSpace;</a></h4>
<blockquote>
<p>“我喜欢创造美观、高性能的产品，并提供令人愉悦的用户体验。”</p>
</blockquote>
<p>前端工程师应具备的品质。</p>
<blockquote>
<p>“它每月的浏览量超过 100 万次，被超过 40,000 名 NUS 本科生甚至一些教授使用。”</p>
</blockquote>
<p>提及有关该项目的一些突出内容。</p>
<blockquote>
<p>“它是使用现代 Web 技术堆栈构建的 - React、Redux、Jest、Babel、Flow、webpack，并且是移动响应式的。”</p>
</blockquote>
<p>元技术栈！还暗示您让自己了解现代 Web 技术的最新情况。</p>
<h3 id="示例-2-lyft-的前端工程师" tabindex="-1">示例 2：Lyft 的前端工程师 <a class="header-anchor" href="#示例-2-lyft-的前端工程师" aria-label="Permalink to &quot;示例 2：Lyft 的前端工程师&quot;">&ZeroWidthSpace;</a></h3>
<h4 id="自我介绍-2" tabindex="-1">自我介绍 <a class="header-anchor" href="#自我介绍-2" aria-label="Permalink to &quot;自我介绍&quot;">&ZeroWidthSpace;</a></h4>
<blockquote>
<p>“嗨，我是 XXX，我于 2015 年毕业于新加坡国立大学，获得计算机科学学位。我的兴趣是前端工程，我喜欢创造具有令人愉悦用户体验的精美、高性能的产品。</p>
<p>我之前在 Grab 工作，在那里我领导了 Grab for Work 项目。Grab for Work 是一项为公司提供便利的公司交通费用的服务。公司可以创建员工群组、设置乘车政策并与员工共享公司付款方式。我和另一位工程师在 3 个月的时间里在 React/Redux 和 Golang 堆栈上构建了这个项目。</p>
<p>我对 Lyft 的前端工程师职位很感兴趣，因为我喜欢在这个拼车领域工作，并创造产品来改善用户的生活。</p>
</blockquote>
<h4 id="分解-1" tabindex="-1">分解 <a class="header-anchor" href="#分解-1" aria-label="Permalink to &quot;分解&quot;">&ZeroWidthSpace;</a></h4>
<blockquote>
<p>“我喜欢创造美观、高性能的产品，并提供令人愉悦的用户体验。”</p>
</blockquote>
<p>同上，前端工程师应具备的品质。</p>
<blockquote>
<p>“我之前在 Grab 工作，在那里我领导了 Grab for Work 项目。”</p>
</blockquote>
<p>Lyft 是 Grab 的姊妹公司！事实上，他们过去甚至有过合作关系。大多数 Lyft 工程师以前都听说过 Grab，提到这一点会引起他们的注意。</p>
<blockquote>
<p>“我和另一位工程师在 React/Redux 和 Golang 堆栈上用了 3 个月的时间构建了这个项目。”</p>
</blockquote>
<p>承认您与他人合作。在 3 个月内仅用 2 个人构建一个非平凡的系统对于一个非平凡系统来说是相当不错的。Lyft 还将 Golang 用于其高性能系统。</p>
<h2 id="面试结束最后要问的问题" tabindex="-1">面试结束最后要问的问题 <a class="header-anchor" href="#面试结束最后要问的问题" aria-label="Permalink to &quot;面试结束最后要问的问题&quot;">&ZeroWidthSpace;</a></h2>
<p>在软件工程师面试结束时（无论是技术轮次还是非技术轮次），几乎在最后都会被询问：“你还有什么问题吗？”</p>
<h3 id="为了解技术工作更多信息而提出的问题" tabindex="-1">为了解技术工作更多信息而提出的问题 <a class="header-anchor" href="#为了解技术工作更多信息而提出的问题" aria-label="Permalink to &quot;为了解技术工作更多信息而提出的问题&quot;">&ZeroWidthSpace;</a></h3>
<ul>
<li><strong>公司/团队面临的工程挑战是什么？</strong></li>
<li><strong>最近发生的最严重的技术错误是什么？你们是怎么应对的？之后实施了哪些更改以确保它不会再次发生？</strong></li>
<li><strong>公司现在面临的最昂贵的技术决策是什么？</strong></li>
<li><strong>到目前为止，你在这里做过的最有成就感/最令人兴奋/技术最复杂的项目是什么？</strong></li>
<li><strong>我在 X 领域有/没有经验。这对我成功有多重要？</strong></li>
</ul>
<h3 id="为了解有关职位的更多信息而提出的问题" tabindex="-1">为了解有关职位的更多信息而提出的问题 <a class="header-anchor" href="#为了解有关职位的更多信息而提出的问题" aria-label="Permalink to &quot;为了解有关职位的更多信息而提出的问题&quot;">&ZeroWidthSpace;</a></h3>
<ul>
<li><strong>在招聘这个职位时，您会注意哪些品质？</strong></li>
<li><strong>如果我加入你们的团队，你们希望我解决的最重要的问题是什么？</strong></li>
<li>如果我加入这个团队，我会做什么，我会与谁密切合作？</li>
</ul>
<h3 id="了解更多文化和福利的最佳问题" tabindex="-1">了解更多文化和福利的最佳问题 <a class="header-anchor" href="#了解更多文化和福利的最佳问题" aria-label="Permalink to &quot;了解更多文化和福利的最佳问题&quot;">&ZeroWidthSpace;</a></h3>
<ul>
<li><strong>在这家公司工作有什么独特之处，是你在其他地方没有经历过的？</strong></li>
<li>如何衡量个人表现？</li>
<li>公司如何培养和培训员工？</li>
</ul>
<h3 id="了解更多关于团队领导或管理的问题" tabindex="-1">了解更多关于团队领导或管理的问题 <a class="header-anchor" href="#了解更多关于团队领导或管理的问题" aria-label="Permalink to &quot;了解更多关于团队领导或管理的问题&quot;">&ZeroWidthSpace;</a></h3>
<p>这些问题适合询问工程经理或高级管理人员，例如 CEO、CTO、VP，对于 Google 面试的团队匹配阶段或招聘人员与各个团队经理安排的录用后电话特别有用。</p>
<ul>
<li><strong>您如何培训/提升团队的新工程师？</strong></li>
<li>您的工程师如何知道每天要做什么？</li>
<li>您如何衡量个人表现？</li>
<li>目前的团队组成是什么样的？</li>
<li>有哪些机会可以转换角色？这是如何工作的？</li>
<li>您的管理理念是什么？</li>
<li>如果我加入你们的团队，你们希望我解决的最重要的问题是什么？</li>
<li>您的团队将提供哪些成长机会？</li>
<li>如果我加入这个团队，我会做什么，我会与谁密切合作？</li>
</ul>
<h2 id="要更多地了解公司发展方向的问题" tabindex="-1">要更多地了解公司发展方向的问题 <a class="header-anchor" href="#要更多地了解公司发展方向的问题" aria-label="Permalink to &quot;要更多地了解公司发展方向的问题&quot;">&ZeroWidthSpace;</a></h2>
<ul>
<li><strong>公司如何决定下一步的工作内容？</strong></li>
<li>哪些公司是您的主要竞争对手，您的公司有何与众不同之处？</li>
<li>您现在的首要任务是什么？例如，新功能、新产品、巩固现有代码、减少运营开销？</li>
</ul>
<hr class="footnotes-sep">
<section class="footnotes">
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p><code>FAANG</code> 指的是 Facebook、Apple、Amazon、Netflix、Google <a href="#fnref1" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn2" class="footnote-item"><p><code>ATS</code> 指的是 <code>Applicant Tracking System</code> 中文常翻译为 <code>候选人追踪系统</code> 或 <code>简历筛选系统</code> <a href="#fnref2" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn3" class="footnote-item"><p><code>STAR</code> 指的是: Situation(情况), task(任务), action(行动), result(结果) <a href="#fnref3" class="footnote-backref">↩︎</a></p>
</li>
</ol>
</section>
]]></content>
        <author>
            <name>duyl328</name>
            <uri>https://seyl.me/about</uri>
        </author>
        <category label="面试技巧"/>
        <category label="转载"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[tauri 中创建和管理全局 emit 任务]]></title>
        <id>https://seyl.me/posts/2025/01/tauri-global-emit-error-handling</id>
        <link href="https://seyl.me/posts/2025/01/tauri-global-emit-error-handling"/>
        <updated>2025-01-21T00:00:00.000Z</updated>
        <content type="html"><![CDATA[<h1 id="tauri-全局-emit-任务管理与错误处理机制" tabindex="-1">Tauri 全局 Emit 任务管理与错误处理机制 <a class="header-anchor" href="#tauri-全局-emit-任务管理与错误处理机制" aria-label="Permalink to &quot;Tauri 全局 Emit 任务管理与错误处理机制&quot;">&ZeroWidthSpace;</a></h1>
<blockquote>
<p>✒️ 文章摘要</p>
</blockquote>
<!-- DESC SEP -->
<p>在 Tauri 中，前端通过 <code>listen</code> API 来监听特定事件，而后端则通过 <code>AppHandle</code> 中的 <code>emit</code> 方法触发这些事件。然而，由于 <code>AppHandle</code> 的生命周期问题，它不能作为全局对象存储，这就引发了一个问题：如何在没有前端 <code>command</code> 触发的情况下，从后端触发全局的 <code>emit</code>。</p>
<p>为了解决这个问题，笔者提出了一种通过创建异步任务管理器的方法。通过使用 Tokio 创建一个后台线程来监听 <code>mpsc</code> 通道，后端可以通过该通道发送全局错误消息。当错误发生时，消息通过通道发送到前端，前端通过 <code>emit</code> API 处理并展示这些信息。此方案避免了 <code>AppHandle</code> 的生命周期问题，并保证了全局事件的触发机制。</p>
<!-- DESC SEP -->
<h2 id="preface" tabindex="-1">前言 <a class="header-anchor" href="#preface" aria-label="Permalink to &quot;前言{#preface}&quot;">&ZeroWidthSpace;</a></h2>
<p>当在使用 <code>tauri</code> 时，可以使用其提供的 <code>command</code> 通过前端来调用后端，也可以使用 <code>emit</code> 通过后端来调用前端，当后端发生错误时，我们需要一种机制将错误信息传递到前端并进行处理。传统的 <code>command</code> 机制依赖于前端调用，而 <code>emit</code> 则更适合处理这种场景，因为它支持多个事件的触发。通过在多个地方绑定相同的事件，后端可以通过触发 <code>emit</code> 来统一通知前端进行错误处理。</p>
<p>基于此就可以做出很多事情，其中之一就是当后端运行出错时，可以通过全局的 <code>emit</code> 将错误信息传递到前端，并通过前端进行展示，或者提示用户错误错误处理，因为后端的报错是不可预知的，所以对于该 <code>emit</code> 来说，也应该是全局的，随时可以调用的。</p>
<h2 id="emit-introduce" tabindex="-1"><code>emit</code> 介绍 <a class="header-anchor" href="#emit-introduce" aria-label="Permalink to &quot;`emit` 介绍{#emit-introduce}&quot;">&ZeroWidthSpace;</a></h2>
<p>我们先介绍 <code>tauri</code> 中是如何做到 <code>emit</code> 的触发和绑定的</p>
<h4 id="前端监听" tabindex="-1">前端监听 <a class="header-anchor" href="#前端监听" aria-label="Permalink to &quot;前端监听&quot;">&ZeroWidthSpace;</a></h4>
<p>NPM 软件包提供了用于侦听全局事件和特定于 webview 的事件的 API。<code>@tauri-apps/api</code></p>
<div class="language-js vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { listen } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> '@tauri-apps/api/event'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">type</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> DownloadStarted</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">  url</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">  downloadId</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> number</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">  contentLength</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> number</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line highlighted"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">listen</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">DownloadStarted</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'download-started'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">event</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    `downloading ${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">event</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">payload</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">contentLength</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">} bytes from ${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">event</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">payload</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">url</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">}`</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  );</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">});</span></span></code></pre>
</div><p>绑定方式通过对一个 '频道' 进行监听，然后来监控是否触发，可以定义接收的数据类型来传递数据</p>
<h4 id="后端触发" tabindex="-1">后端触发 <a class="header-anchor" href="#后端触发" aria-label="Permalink to &quot;后端触发&quot;">&ZeroWidthSpace;</a></h4>
<div class="language-rust vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">rust</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">use</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> tauri</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">::</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AppHandle</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Emitter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">#[tauri</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">::</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">command]</span></span>
<span class="line highlighted"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">fn</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> download</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(app</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> AppHandle</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, url</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> String</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  app</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">emit</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"download-started"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">url)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">unwrap</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> progress </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> [</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">15</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">50</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">80</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">] {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    app</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">emit</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"download-progress"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, progress)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">unwrap</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  app</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">emit</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"download-finished"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">url)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">unwrap</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div><p>后端的触发使用 <code>AppHandle</code> 中提供的 <code>emit</code> 函数，调用时</p>
<ol>
<li>通过前端调用后端提供的指令<code>download</code> 然后将对应的链接(<code>url</code>)传递进来</li>
<li>而 <code>app: AppHandle</code> 则由 <code>tauri</code> 自动填充，这里的 <code>app</code> 就是软件的实例</li>
<li>当拿到 <code>app</code> 后，使用其 <code>emit</code> 函数进行触发，从而触发前端的监听</li>
</ol>
<p>整个过程在类似点击下载，后端开始下载，并且前端需要展示下载进度的场景没有什么问题，不过还记得我们的目的吗？我们需要完成的是全局的 <code>emit</code> 的触发，并通过此完成错误的提示</p>
<p>这时就会造成一个很严重的问题 :</p>
<blockquote>
<p>我们的错误是不可预知的，而前端 <code>emit</code> 的触发是需要 <code>AppHandle</code> 的，&gt; <code>AppHandle</code> 作为 Tauri 应用的实例对象，其生命周期和应用的运行状态密切相关，因此不能存储为全局静态对象。在常规情况下，<code>emit</code> 触发需要通过 <code>AppHandle</code>，但如果依赖前端的 <code>command</code> 触发 <code>emit</code>，就会陷入循环问题。为了避免这一问题，我们采用了异步线程管理，通过 <code>tokio</code> 和 <code>mpsc</code> 通道将事件传递给前端。</p>
</blockquote>
<h2 id="think" tabindex="-1">想法 <a class="header-anchor" href="#think" aria-label="Permalink to &quot;想法{#think}&quot;">&ZeroWidthSpace;</a></h2>
<p>我们重新整理一下现在需要做什么，现在需要将后端错误通过全局的 <code>emit</code> 进行前端，并且想要触发就需要 <code>AppHandle</code> ；并且不能将其存储为静态内容。</p>
<p>不过仔细观察官方提供的示例，我们的确无法将 <code>AppHandle</code> 进行存储，但是就像官方实例中那样，通过 <code>Command</code> 不仅可以拿到 <code>AppHandle</code> 实例，还可以通过 <code>while</code> 等循环方式让 <code>emit</code> 多次触发。
不过我们可以在 <code>command</code> 调用时，可以通过 <code>takio</code> 创建一个消息等待的线程，并 <code>takio</code> 的消息通知渠道保存起来，通过消息通知来传递触发对应的事件</p>
<h2 id="common-thread-processing" tabindex="-1">创建通用线程处理 <a class="header-anchor" href="#common-thread-processing" aria-label="Permalink to &quot;创建通用线程处理{#common-thread-processing}&quot;">&ZeroWidthSpace;</a></h2>
<p>主要的思路是，创建对应的全局的后台任务处理，并通过循环等待</p>
<p>创建一个通用的任务管理器：</p>
<div class="language-rust vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">rust</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">pub</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> async</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> fn</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> task_h</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">T</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">F</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">mut</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> rx</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> mpsc</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">::</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Receiver</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">T</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>, f</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> F</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">where</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    F</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Fn</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">T</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">),  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // 无限循环确保 Receiver 一直保持活跃  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    loop</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        match</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> rx</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">recv</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">.await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">            Some</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(task) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">                f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(task);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            }  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">            None</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">                // 如果通道关闭，可以选择如何处理（这里是等待并继续）  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">                println!</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"通道关闭，继续等待..."</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            }  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br></div></div><p><code>task_h</code> 函数是一个异步任务管理器，它通过 <code>mpsc</code> 通道不断接收任务并执行相应的处理。这个函数的作用是确保事件能够在后台持续触发，而不会受到生命周期的限制。<code>emit_global_msg</code> 则是一个全局任务初始化函数，它在首次调用时设置状态并启动一个新的线程来处理错误信息的传递。</p>
<p>使用时，通过将要调用的函数，传递的数据都传递过来，根据我们需求，将会是这样：</p>
<div class="language-rust vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">rust</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">#[tauri</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">::</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">command]  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">pub</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> fn</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> emit_global_msg</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(app</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> AppHandle</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    let</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> mut</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> is_init </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> GLOBAL_EMIT_IS_INIT</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">lock</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">unwrap</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> is_init</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">clone</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() {  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    println!</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"前端 emit 初始化!"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    *</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">is_init </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    let</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> mut</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> emit </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> GLOBAL_EMIT_APP_HANDLE</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">lock</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">unwrap</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (emit_tx, emit_rx) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> mpsc</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">::</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">channel</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">::</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">String</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    *</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">emit </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Some</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(emit_tx);  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> f </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> move</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> |</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">info</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> String</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">|</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        app</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">clone</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">emit</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">global_front_emit</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">::</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">GLOBAL_ERROR_MSG_DISPLAY</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, info)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">unwrap</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    };  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // 在一个新的线程中启动 Tokio 运行时  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    thread</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">::</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">spawn</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">move</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> ||</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {  </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // 创建 Tokio 运行时并运行异步任务  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> runtime </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> tokio</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">::</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">runtime</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">::</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Runtime</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">::</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">new</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">unwrap</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        runtime</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">block_on</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">async</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> move</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {  </span></span>
<span class="line highlighted"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">            task_h</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(emit_rx, f)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">.await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        });  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    });  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div><p><code>GLOBAL_EMIT_APP_HANDLE</code> 和 <code>GLOBAL_EMIT_IS_INIT</code> 分别用于管理全局事件的发送者和初始化状态。通过 <code>lock</code> 锁定这些全局状态，确保多次调用时不会重复初始化，从而避免不必要的资源浪费和逻辑错误。</p>
<p>获取到 <code>AppHandle</code> 后，我们创建一个闭包，并将具体逻辑传入其中。由于该函数会多次触发，我们需要将 <code>AppHandle</code> 移入闭包并进行克隆使用。所有的内容准备好后，创建一个新的 <code>channel</code> 将<code>发送者</code>保存为全局对象，以供后期使用，而<code>接收者</code>交给新线程的任务处理者使用。</p>
<p>最后，通过 <code>thread::spawn</code> 启动一个新的线程，并创建一个 <code>tokio</code> 运行时来单独运行。</p>
<p>这个函数在进入运行时后，将一直循环和等待任务，<code>AppHandle</code> 会被劫持在其中</p>
<p>调用时：</p>
<div class="language-rust vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">rust</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> emit_option </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> emit </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> GLOBAL_EMIT_APP_HANDLE</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">lock</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">unwrap</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    emit</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">clone</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 移出作用域以释放锁  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">};  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> let</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Some</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(x) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> emit_option</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">as_ref</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() {  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ms </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> GlobalErrorMsg</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        title</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">:</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "标题"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">parse</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">unwrap</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(),  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        msg</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">:</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "内容"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">parse</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">unwrap</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(),  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        duration</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 5000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        kind</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">:</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> crate::</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">structs</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">::</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">global_error_msg</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">::</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GlobalErrorMsgTypeEnum</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">::</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Success</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    };  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> result </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> JsonUtil</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">::</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">stringify</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">ms)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">expect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"数据序列化失败!"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line highlighted"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> qqq </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> x</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">send</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(result)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">.await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;  </span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> qqq</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">is_err</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() {  </span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        println!</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"发送失败！"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }  </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div><p>通过拿到保存的<code>发送者</code>，并调用其中的 <code>send</code> 函数将数据传递到封装的函数中，以完成函数调用。</p>
]]></content>
        <author>
            <name>duyl328</name>
            <uri>https://seyl.me/about</uri>
        </author>
        <category label="编程"/>
        <category label="Blog"/>
        <category label="原创"/>
        <category label="tauri"/>
        <category label="rust"/>
        <category label="argus"/>
        <category label="思考"/>
        <category label="tokio"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[VitePress 笔记使用]]></title>
        <id>https://seyl.me/posts/2025/01/vitepress-note-use</id>
        <link href="https://seyl.me/posts/2025/01/vitepress-note-use"/>
        <updated>2025-01-20T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[<blockquote>
<p>✒️ 文章摘要</p>
</blockquote>
<!-- DESC SEP -->
<p>本文介绍了如何使用 vitepress</p>
<!-- DESC SEP -->
<h2 id="内部链接" tabindex="-1">内部链接 <a class="header-anchor" href="#内部链接" aria-label="Permalink to &quot;内部链接&quot;">&ZeroWidthSpace;</a></h2>
<p>内部链接将转换为单页导航的路由链接。此外，子目录中包含的每个 <code>index.md</code> 都会自动转换为 <code>index.html</code>，并带有相应的 URL <code>/</code>。
<a href="./vitepress-link-jump.html">vitepress-link-jump</a> <!-- 可以添加 .md --></p>
<div class="language-html vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">html</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[VitePress 链接跳转](./VitePress 链接跳转.md)</span></span></code></pre>
</div><h2 id="yaml-front-matter" tabindex="-1">YAML front matter <a class="header-anchor" href="#yaml-front-matter" aria-label="Permalink to &quot;YAML front matter&quot;">&ZeroWidthSpace;</a></h2>
<p>任何包含 <a href="https://yaml.org/" target="_blank" rel="noreferrer">YAML</a> front matter 块的文件都将是 由 Jekyll 作为特殊文件处理。前言必须是第一件事 ，并且必须采用在三短划线 线。下面是一个基本示例：</p>
<div class="language-markdown vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">markdown</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"></span></code></pre>
</div>]]></summary>
        <content type="html"><![CDATA[<blockquote>
<p>✒️ 文章摘要</p>
</blockquote>
<!-- DESC SEP -->
<p>本文介绍了如何使用 vitepress</p>
<!-- DESC SEP -->
<h2 id="内部链接" tabindex="-1">内部链接 <a class="header-anchor" href="#内部链接" aria-label="Permalink to &quot;内部链接&quot;">&ZeroWidthSpace;</a></h2>
<p>内部链接将转换为单页导航的路由链接。此外，子目录中包含的每个 <code>index.md</code> 都会自动转换为 <code>index.html</code>，并带有相应的 URL <code>/</code>。
<a href="./vitepress-link-jump.html">vitepress-link-jump</a> <!-- 可以添加 .md --></p>
<div class="language-html vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">html</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[VitePress 链接跳转](./VitePress 链接跳转.md)</span></span></code></pre>
</div><h2 id="yaml-front-matter" tabindex="-1">YAML front matter <a class="header-anchor" href="#yaml-front-matter" aria-label="Permalink to &quot;YAML front matter&quot;">&ZeroWidthSpace;</a></h2>
<p>任何包含 <a href="https://yaml.org/" target="_blank" rel="noreferrer">YAML</a> front matter 块的文件都将是 由 Jekyll 作为特殊文件处理。前言必须是第一件事 ，并且必须采用在三短划线 线。下面是一个基本示例：</p>
<div class="language-markdown vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">markdown</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">---</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">layout</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">post</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">title</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">Blogging Like a Hacker</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">---</span></span></code></pre>
</div><h3 id="frontmatter-配置" tabindex="-1">frontmatter 配置 <a class="header-anchor" href="#frontmatter-配置" aria-label="Permalink to &quot;frontmatter 配置&quot;">&ZeroWidthSpace;</a></h3>
<p>示例：</p>
<div class="language-markdown vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">markdown</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">--- </span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">title</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">Docs with VitePress</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> </span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">editLink</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">---</span></span></code></pre>
</div><p>可以通过 Vue 表达式中的 <code>$frontmatter</code> 全局变量访问 frontmatter 数据：</p>
<div class="language-Vue vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">Vue</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{{ $frontmatter.title }}</span></span></code></pre>
</div><blockquote>
<p>该内容由 Vue 渲染： <strong>{{ $frontmatter.title }}</strong></p>
</blockquote>
<h2 id="head" tabindex="-1">head <a class="header-anchor" href="#head" aria-label="Permalink to &quot;head&quot;">&ZeroWidthSpace;</a></h2>
<ul>
<li>类型：<code>HeadConfig[]</code></li>
</ul>
<p>指定要为当前页面注入的额外 head 标签。将附加在站点级配置注入的头部标签之后。</p>
<p>yaml</p>
<div class="language-markdown vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">markdown</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">---</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">head</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  - - </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">meta</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    - </span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">description</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">      content</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">hello</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  - - </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">meta</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    - </span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">keywords</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">      content</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">super duper SEO</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">---</span></span></code></pre>
</div><h2 id="layout" tabindex="-1">layout <a class="header-anchor" href="#layout" aria-label="Permalink to &quot;layout&quot;">&ZeroWidthSpace;</a></h2>
<ul>
<li>类型：<code>doc | home | page</code></li>
<li>默认值：<code>doc</code></li>
</ul>
<p>指定页面的布局。</p>
<ul>
<li><code>doc</code>——它将默认文档样式应用于 markdown 内容。</li>
<li><code>home</code>——“主页”的特殊布局。可以添加额外的选项，例如 <code>hero</code> 和 <code>features</code>，以快速创建漂亮的落地页。</li>
<li><code>page</code>——表现类似于 <code>doc</code>，但它不对内容应用任何样式。当想创建一个完全自定义的页面时很有用。</li>
</ul>
<div class="language-yaml vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">yaml</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">---</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">layout</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">doc</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">---</span></span></code></pre>
</div><h2 id="navbar" tabindex="-1">navbar <a class="header-anchor" href="#navbar" aria-label="Permalink to &quot;navbar&quot;">&ZeroWidthSpace;</a></h2>
<ul>
<li>类型：<code>boolean</code></li>
<li>默认值：<code>true</code></li>
</ul>
<p>是否显示导航栏。</p>
<div class="language-yaml vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">yaml</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">---</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">navbar</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">false</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">---</span></span></code></pre>
</div><h2 id="sidebar" tabindex="-1">sidebar <a class="header-anchor" href="#sidebar" aria-label="Permalink to &quot;sidebar&quot;">&ZeroWidthSpace;</a></h2>
<ul>
<li>类型：<code>boolean</code></li>
<li>默认值：<code>true</code></li>
</ul>
<p>是否显示 侧边栏</p>
<div class="language- vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>---</span></span>
<span class="line"><span>sidebar: false</span></span>
<span class="line"><span>---</span></span></code></pre>
</div><h2 id="aside" tabindex="-1">aside <a class="header-anchor" href="#aside" aria-label="Permalink to &quot;aside&quot;">&ZeroWidthSpace;</a></h2>
<ul>
<li>类型：<code>boolean | 'left'</code></li>
<li>默认值：<code>true</code></li>
</ul>
<p>定义侧边栏组件在 <code>doc</code> 布局中的位置。</p>
<p>将此值设置为 <code>false</code> 可禁用侧边栏容器。<br>
将此值设置为 <code>true</code> 会将侧边栏渲染到右侧。<br>
将此值设置为 <code>left</code> 会将侧边栏渲染到左侧。</p>
<div class="language-yaml vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">yaml</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">---</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">aside</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">false</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">---</span></span></code></pre>
</div><h2 id="lastupdated" tabindex="-1">lastUpdated <a class="header-anchor" href="#lastupdated" aria-label="Permalink to &quot;lastUpdated&quot;">&ZeroWidthSpace;</a></h2>
<ul>
<li>类型：<code>boolean | Date</code></li>
<li>默认值：<code>true</code></li>
</ul>
<p>是否在当前页面的页脚中显示最后更新时间的文本。如果指定了日期时间，则会显示该日期时间而不是上次 git 修改的时间戳。</p>
<div class="language-yaml vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">yaml</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">---</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">lastUpdated</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">false</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">---</span></span></code></pre>
</div><div class="tip custom-block github-alert"><p class="custom-block-title">TIP</p>
<p>你必须提交 markdown 文件才能看到最后更新时间。</p>
</div>
<h2 id="emoji" tabindex="-1">Emoji <a class="header-anchor" href="#emoji" aria-label="Permalink to &quot;Emoji&quot;">&ZeroWidthSpace;</a></h2>
<p>输入：</p>
<div class="language-html vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">html</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:tada: :100:</span></span></code></pre>
</div><p>输出：</p>
<p>🎉 💯</p>
<h2 id="自定义容器" tabindex="-1">自定义容器 <a class="header-anchor" href="#自定义容器" aria-label="Permalink to &quot;自定义容器&quot;">&ZeroWidthSpace;</a></h2>
<p>自定义容器可以通过它们的类型、标题和内容来定义。</p>
<p><strong>输入</strong></p>
<div class="language-md vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">md</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">::: info</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">This is an info box.</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:::</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">::: tip</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">This is a tip.</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:::</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">::: warning</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">This is a warning.</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:::</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">::: danger</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">This is a dangerous warning.</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:::</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">::: details</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">This is a details block.</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:::</span></span></code></pre>
</div><p><strong>输出</strong></p>
<div class="info custom-block"><p class="custom-block-title">INFO</p>
<p>This is an info box.</p>
</div>
<div class="tip custom-block"><p class="custom-block-title">TIP</p>
<p>This is a tip.</p>
</div>
<div class="warning custom-block"><p class="custom-block-title">WARNING</p>
<p>This is a warning.</p>
</div>
<div class="danger custom-block"><p class="custom-block-title">DANGER</p>
<p>This is a dangerous warning.</p>
</div>
<details class="details custom-block"><summary>Details</summary>
<p>This is a details block.</p>
</details>
<h2 id="自定义标题" tabindex="-1">自定义标题 <a class="header-anchor" href="#自定义标题" aria-label="Permalink to &quot;自定义标题&quot;">&ZeroWidthSpace;</a></h2>
<p>可以通过在容器的 &quot;type&quot; 之后附加文本来设置自定义标题。</p>
<p><strong>输入</strong></p>
<div class="language-md vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">md</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">::: danger STOP</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">危险区域，请勿继续</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:::</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">::: details 点我查看代码</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">```js</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'Hello, VitePress!'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span></code></pre>
</div><p><strong>输出</strong></p>
<div class="danger custom-block"><p class="custom-block-title">STOP</p>
<p>危险区域，请勿继续</p>
</div>
<details class="details custom-block"><summary>点我查看代码</summary>
<div class="language-js vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'Hello, VitePress!'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span></code></pre>
</div></details>
<h2 id="github-风格的警报" tabindex="-1">GitHub 风格的警报 <a class="header-anchor" href="#github-风格的警报" aria-label="Permalink to &quot;GitHub 风格的警报&quot;">&ZeroWidthSpace;</a></h2>
<div class="language-markdown vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">markdown</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">> [</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF;--shiki-light-text-decoration:underline;--shiki-dark-text-decoration:underline">!NOTE</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">]</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">> Useful information that users should know, even when skimming content.</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">> [</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF;--shiki-light-text-decoration:underline;--shiki-dark-text-decoration:underline">!TIP</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">]</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">> Helpful advice for doing things better or more easily.</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">> [</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF;--shiki-light-text-decoration:underline;--shiki-dark-text-decoration:underline">!IMPORTANT</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">]</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">> Key information users need to know to achieve their goal.</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">> [</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF;--shiki-light-text-decoration:underline;--shiki-dark-text-decoration:underline">!WARNING</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">]</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">> Urgent info that needs immediate user attention to avoid problems.</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">> [</span><span style="--shiki-light:#032F62;--shiki-dark:#DBEDFF;--shiki-light-text-decoration:underline;--shiki-dark-text-decoration:underline">!CAUTION</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">]</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">> Advises about risks or negative outcomes of certain actions.</span></span></code></pre>
</div><div class="note custom-block github-alert"><p class="custom-block-title">NOTE</p>
<p>Useful information that users should know, even when skimming content.</p>
</div>
<div class="tip custom-block github-alert"><p class="custom-block-title">TIP</p>
<p>Helpful advice for doing things better or more easily.</p>
</div>
<div class="important custom-block github-alert"><p class="custom-block-title">IMPORTANT</p>
<p>Key information users need to know to achieve their goal.</p>
</div>
<div class="warning custom-block github-alert"><p class="custom-block-title">WARNING</p>
<p>Urgent info that needs immediate user attention to avoid problems.</p>
</div>
<div class="caution custom-block github-alert"><p class="custom-block-title">CAUTION</p>
<p>Advises about risks or negative outcomes of certain actions.</p>
</div>
<h2 id="在代码块中实现行高亮" tabindex="-1">在代码块中实现行高亮 <a class="header-anchor" href="#在代码块中实现行高亮" aria-label="Permalink to &quot;在代码块中实现行高亮&quot;">&ZeroWidthSpace;</a></h2>
<p><strong>输入</strong></p>
<div class="language-md vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">md</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">```js{4}</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">  data</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> () {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      msg: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'Highlighted!'</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">```</span></span></code></pre>
</div><p><strong>输出</strong></p>
<div class="language-js vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">  data</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> () {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line highlighted"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      msg: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'Highlighted!'</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div><p>除了单行之外，还可以指定多个单行、多行，或两者均指定：</p>
<ul>
<li>多行：例如 <code>{5-8}</code>、<code>{3-10}</code>、<code>{10-17}</code></li>
<li>多个单行：例如 <code>{4,7,9}</code></li>
<li>多行与单行：例如 <code>{4,7-13,16,23-27,40}</code></li>
</ul>
<p><strong>输入</strong></p>
<div class="language-md vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">md</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">```js{1,4,6-8}</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// Highlighted</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">  data</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> () {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      msg: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">`Highlighted!</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">      This line isn't highlighted,</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">      but this and the next 2 are.`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      motd: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'VitePress is awesome'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      lorem: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'ipsum'</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">```</span></span></code></pre>
</div><p><strong>输出</strong></p>
<div class="language-js vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line highlighted"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// Highlighted</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">  data</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> () {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line highlighted"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      msg: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">`Highlighted!</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">      This line isn't highlighted,</span></span>
<span class="line highlighted"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">      but this and the next 2 are.`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line highlighted"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      motd: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'VitePress is awesome'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line highlighted"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      lorem: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'ipsum'</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div><p>也可以使用 <code>// [!code highlight]</code> 注释实现行高亮。
<strong>输入</strong></p>
<div class="language- vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark has-highlighted vp-code" tabindex="0" v-pre=""><code><span class="line"><span>```js</span></span>
<span class="line"><span>export default {</span></span>
<span class="line"><span>  data () {</span></span>
<span class="line"><span>    return {</span></span>
<span class="line highlighted"><span>      msg: 'Highlighted!'</span></span>
<span class="line"><span>    }</span></span>
<span class="line"><span>  }</span></span>
<span class="line"><span>}</span></span>
<span class="line"><span>```</span></span></code></pre>
</div><p><strong>输出</strong></p>
<div class="language-js vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki shiki-themes github-light github-dark has-highlighted vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">  data</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> () {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line highlighted"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      msg: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'Highlighted!'</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div><h2 id="代码块中聚焦" tabindex="-1">代码块中聚焦 <a class="header-anchor" href="#代码块中聚焦" aria-label="Permalink to &quot;代码块中聚焦&quot;">&ZeroWidthSpace;</a></h2>
<p>在某一行上添加 <code>// [!code focus]</code> 注释将聚焦它并模糊代码的其他部分。
此外，可以使用 <code>// [!code focus:&lt;lines&gt;]</code> 定义要聚焦的行数。</p>
<p><strong>输入</strong></p>
<div class="language- vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>```js</span></span>
<span class="line"><span>export default {</span></span>
<span class="line"><span>  data () {</span></span>
<span class="line"><span>    return {</span></span>
<span class="line"><span>      msg: 'Focused!' // [!!code focus]</span></span>
<span class="line"><span>    }</span></span>
<span class="line"><span>  }</span></span>
<span class="line"><span>}</span></span>
<span class="line"><span>```</span></span></code></pre>
</div><p><strong>输出</strong></p>
<div class="language-js vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki shiki-themes github-light github-dark has-focused-lines vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">  data</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> () {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line has-focus"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      msg: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'Focused!'</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div><h2 id="colored-diffs-in-code-blocks" tabindex="-1">代码块中的颜色差异 <a class="header-anchor" href="#colored-diffs-in-code-blocks" aria-label="Permalink to &quot;代码块中的颜色差异 {#colored-diffs-in-code-blocks}&quot;">&ZeroWidthSpace;</a></h2>
<p>在某一行添加 <code>// [!code --]</code> 或 <code>// [!code ++]</code> 注释将会为该行创建 diff，同时保留代码块的颜色。</p>
<p><strong>输入</strong></p>
<div class="language- vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>```js</span></span>
<span class="line"><span>export default {</span></span>
<span class="line"><span>  data () {</span></span>
<span class="line"><span>    return {</span></span>
<span class="line"><span>      msg: 'Removed' // [!!code --]</span></span>
<span class="line"><span>      msg: 'Added' // [!!code ++]</span></span>
<span class="line"><span>    }</span></span>
<span class="line"><span>  }</span></span>
<span class="line"><span>}</span></span>
<span class="line"><span>```</span></span></code></pre>
</div><p><strong>输出</strong></p>
<div class="language-js vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki shiki-themes github-light github-dark has-diff vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">  data</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> () {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line diff remove"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      msg: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'Removed'</span></span>
<span class="line diff add"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      msg: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'Added'</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div><h2 id="errors-and-warnings-in-code-blocks" tabindex="-1">高亮“错误”和“警告” <a class="header-anchor" href="#errors-and-warnings-in-code-blocks" aria-label="Permalink to &quot;高亮“错误”和“警告” {#errors-and-warnings-in-code-blocks}&quot;">&ZeroWidthSpace;</a></h2>
<p>在某一行添加 <code>// [!code warning]</code> 或 <code>// [!code error]</code> 注释将会为该行相应的着色。</p>
<p><strong>输入</strong></p>
<div class="language- vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>```js</span></span>
<span class="line"><span>export default {</span></span>
<span class="line"><span>  data () {</span></span>
<span class="line"><span>    return {</span></span>
<span class="line"><span>      msg: 'Error', // [!!code error]</span></span>
<span class="line"><span>      msg: 'Warning' // [!!code warning]</span></span>
<span class="line"><span>    }</span></span>
<span class="line"><span>  }</span></span>
<span class="line"><span>}</span></span>
<span class="line"><span>```</span></span></code></pre>
</div><p><strong>输出</strong></p>
<div class="language-js vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki shiki-themes github-light github-dark has-highlighted vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">  data</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line highlighted error"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      msg: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'Error'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span></span>
<span class="line highlighted warning"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      msg: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'Warning'</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div><h2 id="line-numbers" tabindex="-1">行号 <a class="header-anchor" href="#line-numbers" aria-label="Permalink to &quot;行号 {#line-numbers}&quot;">&ZeroWidthSpace;</a></h2>
<p>可以通过以下配置为每个代码块启用行号：</p>
<div class="language-js vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  markdown: {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    lineNumbers: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div><p>查看 <a href="./../reference/site-config.html#markdown"><code>markdown</code> 选项</a> 获取更多信息。</p>
<p>可以在代码块中添加 <code>:line-numbers</code> / <code>:no-line-numbers</code> 标记来覆盖在配置中的设置。</p>
<p>还可以通过在 <code>:line-numbers</code> 之后添加 <code>=</code> 来自定义起始行号，例如 <code>:line-numbers=2</code> 表示代码块中的行号从 2 开始。</p>
<p><strong>输入</strong></p>
<div class="language-md vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">md</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">```ts {1}</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 默认禁用行号</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> line2</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'This is line 2'</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> line3</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'This is line 3'</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">```</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">```ts:line-numbers {1}</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 启用行号</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> line2</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'This is line 2'</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> line3</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'This is line 3'</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">```</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">```ts:line-numbers=2 {1}</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 行号已启用，并从 2 开始</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> line3</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'This is line 3'</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> line4</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'This is line 4'</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">```</span></span></code></pre>
</div><p><strong>输出</strong></p>
<div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line highlighted"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 默认禁用行号</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> line2</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'This is line 2'</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> line3</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'This is line 3'</span></span></code></pre>
</div><div class="language-ts vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line highlighted"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 启用行号</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> line2</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'This is line 2'</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> line3</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'This is line 3'</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><div class="language-ts vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line highlighted"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 行号已启用，并从 2 开始</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> line3</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'This is line 3'</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> line4</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'This is line 4'</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div><h2 id="code-groups" tabindex="-1">代码组 <a class="header-anchor" href="#code-groups" aria-label="Permalink to &quot;代码组 {#code-groups}&quot;">&ZeroWidthSpace;</a></h2>
<p>可以像这样对多个代码块进行分组：</p>
<p><strong>输入</strong></p>
<div class="language-md vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">md</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">::: code-group</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">```js [config.js]</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">/**</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> * </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">@type</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> {import('vitepress').UserConfig}</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> */</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> config</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  // ...</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> config</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">```</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">```ts [config.ts]</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> type</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { UserConfig } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'vitepress'</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> config</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> UserConfig</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  // ...</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> config</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">```</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:::</span></span></code></pre>
</div><p><strong>输出</strong></p>
<div class="vp-code-group vp-adaptive-theme"><div class="tabs"><input type="radio" name="group-KUFFg" id="tab-s2i3FAw" checked><label for="tab-s2i3FAw">config.js</label><input type="radio" name="group-KUFFg" id="tab-xMyOgdL" ><label for="tab-xMyOgdL">config.ts</label></div><div class="blocks">
<div class="language-js vp-adaptive-theme active"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">/**</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> * </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">@type</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> {import('vitepress').UserConfig}</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> */</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> config</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  // ...</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> config</span></span></code></pre>
</div><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> type</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { UserConfig } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'vitepress'</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> config</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> UserConfig</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  // ...</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> config</span></span></code></pre>
</div></div></div>
<h2 id="math-equations" tabindex="-1">数学方程 <a class="header-anchor" href="#math-equations" aria-label="Permalink to &quot;数学方程 {#math-equations}&quot;">&ZeroWidthSpace;</a></h2>
<p>现在这是可选的。要启用它，需要安装 <code>markdown-it-mathjax3</code>，在配置文件中设置<code>markdown.math</code> 为 <code>true</code>：</p>
<div class="language-sh vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">npm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> add</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -D</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> markdown-it-mathjax3</span></span></code></pre>
</div><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  markdown: {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    math: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div><p><strong>输入</strong></p>
<div class="language-md vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">md</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">When $a \ne 0$, there are two solutions to $(ax^2 + bx + c = 0)$ and they are</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">$$ x = {-b \pm \sqrt{b^2-4ac} \over 2a} $$</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;--shiki-light-font-weight:bold;--shiki-dark-font-weight:bold">**Maxwell's equations:**</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">| equation                                                                                                                                                                  | description                                                                            |</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">| $\nabla \cdot \vec{\mathbf{B}}  = 0$                                                                                                                                      | divergence of $\vec{\mathbf{B}}$ is zero                                               |</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">| $\nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t}  = \vec{\mathbf{0}}$                                                          | curl of $\vec{\mathbf{E}}$ is proportional to the rate of change of $\vec{\mathbf{B}}$ |</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">| $\nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} = \frac{4\pi}{c}\vec{\mathbf{j}}    \nabla \cdot \vec{\mathbf{E}} = 4 \pi \rho$ | </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;--shiki-light-font-style:italic;--shiki-dark-font-style:italic">_wha?_</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                                                                                 |</span></span></code></pre>
</div><p><strong>输出</strong></p>
<p>When <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.486ex;" xmlns="http://www.w3.org/2000/svg" width="5.345ex" height="2.106ex" role="img" focusable="false" viewBox="0 -716 2362.6 931" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D44E" d="M33 157Q33 258 109 349T280 441Q331 441 370 392Q386 422 416 422Q429 422 439 414T449 394Q449 381 412 234T374 68Q374 43 381 35T402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487Q506 153 506 144Q506 138 501 117T481 63T449 13Q436 0 417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157ZM351 328Q351 334 346 350T323 385T277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q217 26 254 59T298 110Q300 114 325 217T351 328Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(806.8,0)"><path data-c="2260" d="M166 -215T159 -215T147 -212T141 -204T139 -197Q139 -190 144 -183L306 133H70Q56 140 56 153Q56 168 72 173H327L406 327H72Q56 332 56 347Q56 360 70 367H426Q597 702 602 707Q605 716 618 716Q625 716 630 712T636 703T638 696Q638 692 471 367H707Q722 359 722 347Q722 336 708 328L451 327L371 173H708Q722 163 722 153Q722 140 707 133H351Q175 -210 170 -212Q166 -215 159 -215Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(1862.6,0)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>a</mi><mo>≠</mo><mn>0</mn></math></mjx-assistive-mml></mjx-container>, there are two solutions to <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="18.163ex" height="2.452ex" role="img" focusable="false" viewBox="0 -833.9 8028 1083.9" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mo"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(389,0)"><path data-c="1D44E" d="M33 157Q33 258 109 349T280 441Q331 441 370 392Q386 422 416 422Q429 422 439 414T449 394Q449 381 412 234T374 68Q374 43 381 35T402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487Q506 153 506 144Q506 138 501 117T481 63T449 13Q436 0 417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157ZM351 328Q351 334 346 350T323 385T277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q217 26 254 59T298 110Q300 114 325 217T351 328Z" style="stroke-width: 3;"/></g><g data-mml-node="msup" transform="translate(918,0)"><g data-mml-node="mi"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(605,363) scale(0.707)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(2148.8,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(3149,0)"><path data-c="1D44F" d="M73 647Q73 657 77 670T89 683Q90 683 161 688T234 694Q246 694 246 685T212 542Q204 508 195 472T180 418L176 399Q176 396 182 402Q231 442 283 442Q345 442 383 396T422 280Q422 169 343 79T173 -11Q123 -11 82 27T40 150V159Q40 180 48 217T97 414Q147 611 147 623T109 637Q104 637 101 637H96Q86 637 83 637T76 640T73 647ZM336 325V331Q336 405 275 405Q258 405 240 397T207 376T181 352T163 330L157 322L136 236Q114 150 114 114Q114 66 138 42Q154 26 178 26Q211 26 245 58Q270 81 285 114T318 219Q336 291 336 325Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(3578,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(4372.2,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(5372.4,0)"><path data-c="1D450" d="M34 159Q34 268 120 355T306 442Q362 442 394 418T427 355Q427 326 408 306T360 285Q341 285 330 295T319 325T330 359T352 380T366 386H367Q367 388 361 392T340 400T306 404Q276 404 249 390Q228 381 206 359Q162 315 142 235T121 119Q121 73 147 50Q169 26 205 26H209Q321 26 394 111Q403 121 406 121Q410 121 419 112T429 98T420 83T391 55T346 25T282 0T202 -11Q127 -11 81 37T34 159Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(6083.2,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(7139,0)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(7639,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mo stretchy="false">(</mo><mi>a</mi><msup><mi>x</mi><mn>2</mn></msup><mo>+</mo><mi>b</mi><mi>x</mi><mo>+</mo><mi>c</mi><mo>=</mo><mn>0</mn><mo stretchy="false">)</mo></math></mjx-assistive-mml></mjx-container> and they are</p>
<mjx-container class="MathJax" jax="SVG" display="true" style="direction: ltr; display: block; text-align: center; margin: 1em 0; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -1.575ex;" xmlns="http://www.w3.org/2000/svg" width="20.765ex" height="5.291ex" role="img" focusable="false" viewBox="0 -1642.5 9178 2338.5" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(849.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(1905.6,0)"><g data-mml-node="mfrac"><g data-mml-node="mrow" transform="translate(220,676)"><g data-mml-node="mo"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(778,0)"><path data-c="1D44F" d="M73 647Q73 657 77 670T89 683Q90 683 161 688T234 694Q246 694 246 685T212 542Q204 508 195 472T180 418L176 399Q176 396 182 402Q231 442 283 442Q345 442 383 396T422 280Q422 169 343 79T173 -11Q123 -11 82 27T40 150V159Q40 180 48 217T97 414Q147 611 147 623T109 637Q104 637 101 637H96Q86 637 83 637T76 640T73 647ZM336 325V331Q336 405 275 405Q258 405 240 397T207 376T181 352T163 330L157 322L136 236Q114 150 114 114Q114 66 138 42Q154 26 178 26Q211 26 245 58Q270 81 285 114T318 219Q336 291 336 325Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(1429.2,0)"><path data-c="B1" d="M56 320T56 333T70 353H369V502Q369 651 371 655Q376 666 388 666Q402 666 405 654T409 596V500V353H707Q722 345 722 333Q722 320 707 313H409V40H707Q722 32 722 20T707 0H70Q56 7 56 20T70 40H369V313H70Q56 320 56 333Z" style="stroke-width: 3;"/></g><g data-mml-node="msqrt" transform="translate(2429.4,0)"><g transform="translate(853,0)"><g data-mml-node="msup"><g data-mml-node="mi"><path data-c="1D44F" d="M73 647Q73 657 77 670T89 683Q90 683 161 688T234 694Q246 694 246 685T212 542Q204 508 195 472T180 418L176 399Q176 396 182 402Q231 442 283 442Q345 442 383 396T422 280Q422 169 343 79T173 -11Q123 -11 82 27T40 150V159Q40 180 48 217T97 414Q147 611 147 623T109 637Q104 637 101 637H96Q86 637 83 637T76 640T73 647ZM336 325V331Q336 405 275 405Q258 405 240 397T207 376T181 352T163 330L157 322L136 236Q114 150 114 114Q114 66 138 42Q154 26 178 26Q211 26 245 58Q270 81 285 114T318 219Q336 291 336 325Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(462,289) scale(0.707)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(1087.8,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(2088,0)"><path data-c="34" d="M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(2588,0)"><path data-c="1D44E" d="M33 157Q33 258 109 349T280 441Q331 441 370 392Q386 422 416 422Q429 422 439 414T449 394Q449 381 412 234T374 68Q374 43 381 35T402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487Q506 153 506 144Q506 138 501 117T481 63T449 13Q436 0 417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157ZM351 328Q351 334 346 350T323 385T277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q217 26 254 59T298 110Q300 114 325 217T351 328Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(3117,0)"><path data-c="1D450" d="M34 159Q34 268 120 355T306 442Q362 442 394 418T427 355Q427 326 408 306T360 285Q341 285 330 295T319 325T330 359T352 380T366 386H367Q367 388 361 392T340 400T306 404Q276 404 249 390Q228 381 206 359Q162 315 142 235T121 119Q121 73 147 50Q169 26 205 26H209Q321 26 394 111Q403 121 406 121Q410 121 419 112T429 98T420 83T391 55T346 25T282 0T202 -11Q127 -11 81 37T34 159Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(0,106.5)"><path data-c="221A" d="M95 178Q89 178 81 186T72 200T103 230T169 280T207 309Q209 311 212 311H213Q219 311 227 294T281 177Q300 134 312 108L397 -77Q398 -77 501 136T707 565T814 786Q820 800 834 800Q841 800 846 794T853 782V776L620 293L385 -193Q381 -200 366 -200Q357 -200 354 -197Q352 -195 256 15L160 225L144 214Q129 202 113 190T95 178Z" style="stroke-width: 3;"/></g><rect width="3550" height="60" x="853" y="846.5"/></g></g><g data-mml-node="mrow" transform="translate(3121.7,-686)"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(500,0)"><path data-c="1D44E" d="M33 157Q33 258 109 349T280 441Q331 441 370 392Q386 422 416 422Q429 422 439 414T449 394Q449 381 412 234T374 68Q374 43 381 35T402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487Q506 153 506 144Q506 138 501 117T481 63T449 13Q436 0 417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157ZM351 328Q351 334 346 350T323 385T277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q217 26 254 59T298 110Q300 114 325 217T351 328Z" style="stroke-width: 3;"/></g></g><rect width="7032.4" height="60" x="120" y="220"/></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="block" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; overflow: hidden; width: 100%;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><mi>x</mi><mo>=</mo><mrow data-mjx-texclass="ORD"><mfrac><mrow><mo>−</mo><mi>b</mi><mo>±</mo><msqrt><msup><mi>b</mi><mn>2</mn></msup><mo>−</mo><mn>4</mn><mi>a</mi><mi>c</mi></msqrt></mrow><mrow><mn>2</mn><mi>a</mi></mrow></mfrac></mrow></math></mjx-assistive-mml></mjx-container><p><strong>Maxwell's equations:</strong></p>
<table>
<thead>
<tr>
<th>equation</th>
<th>description</th>
</tr>
</thead>
<tbody>
<tr>
<td><mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.186ex;" xmlns="http://www.w3.org/2000/svg" width="9.518ex" height="2.649ex" role="img" focusable="false" viewBox="0 -1089 4207 1171" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="2207" d="M46 676Q46 679 51 683H781Q786 679 786 676Q786 674 617 326T444 -26Q439 -33 416 -33T388 -26Q385 -22 216 326T46 676ZM697 596Q697 597 445 597T193 596Q195 591 319 336T445 80L697 596Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(1055.2,0)"><path data-c="22C5" d="M78 250Q78 274 95 292T138 310Q162 310 180 294T199 251Q199 226 182 208T139 190T96 207T78 250Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(1555.4,0)"><g data-mml-node="mover"><g data-mml-node="TeXAtom" data-mjx-texclass="ORD"><g data-mml-node="mi"><path data-c="1D401" d="M720 510Q720 476 704 448T665 404T619 377T580 362L564 359L583 356Q602 353 632 342T690 312Q712 292 725 276Q752 235 752 189V183Q752 160 741 125Q698 18 547 2Q543 1 288 0H39V62H147V624H39V686H264H409Q502 686 542 681T624 655Q720 607 720 510ZM563 513Q563 553 548 578T518 611T486 622Q479 624 385 624H293V382H375Q458 383 467 385Q563 405 563 513ZM590 192Q590 307 505 329Q504 330 503 330L398 331H293V62H391H400H444Q496 62 528 75T580 131Q590 155 590 192Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(409,275) translate(-250 0)"><path data-c="20D7" d="M377 694Q377 702 382 708T397 714Q404 714 409 709Q414 705 419 690Q429 653 460 633Q471 626 471 615Q471 606 468 603T454 594Q411 572 379 531Q377 529 374 525T369 519T364 517T357 516Q350 516 344 521T337 536Q337 555 384 595H213L42 596Q29 605 29 615Q29 622 42 635H401Q377 673 377 694Z" style="stroke-width: 3;"/></g></g></g><g data-mml-node="mo" transform="translate(2651.2,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(3707,0)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi mathvariant="normal">∇</mi><mo>⋅</mo><mrow data-mjx-texclass="ORD"><mover><mrow data-mjx-texclass="ORD"><mi mathvariant="bold">B</mi></mrow><mo stretchy="false">→</mo></mover></mrow><mo>=</mo><mn>0</mn></math></mjx-assistive-mml></mjx-container></td>
<td>divergence of <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: 0;" xmlns="http://www.w3.org/2000/svg" width="1.851ex" height="2.464ex" role="img" focusable="false" viewBox="0 -1089 818 1089" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="TeXAtom" data-mjx-texclass="ORD"><g data-mml-node="mover"><g data-mml-node="TeXAtom" data-mjx-texclass="ORD"><g data-mml-node="mi"><path data-c="1D401" d="M720 510Q720 476 704 448T665 404T619 377T580 362L564 359L583 356Q602 353 632 342T690 312Q712 292 725 276Q752 235 752 189V183Q752 160 741 125Q698 18 547 2Q543 1 288 0H39V62H147V624H39V686H264H409Q502 686 542 681T624 655Q720 607 720 510ZM563 513Q563 553 548 578T518 611T486 622Q479 624 385 624H293V382H375Q458 383 467 385Q563 405 563 513ZM590 192Q590 307 505 329Q504 330 503 330L398 331H293V62H391H400H444Q496 62 528 75T580 131Q590 155 590 192Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(409,275) translate(-250 0)"><path data-c="20D7" d="M377 694Q377 702 382 708T397 714Q404 714 409 709Q414 705 419 690Q429 653 460 633Q471 626 471 615Q471 606 468 603T454 594Q411 572 379 531Q377 529 374 525T369 519T364 517T357 516Q350 516 344 521T337 536Q337 555 384 595H213L42 596Q29 605 29 615Q29 622 42 635H401Q377 673 377 694Z" style="stroke-width: 3;"/></g></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mrow data-mjx-texclass="ORD"><mover><mrow data-mjx-texclass="ORD"><mi mathvariant="bold">B</mi></mrow><mo stretchy="false">→</mo></mover></mrow></math></mjx-assistive-mml></mjx-container> is zero</td>
</tr>
<tr>
<td><mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.817ex;" xmlns="http://www.w3.org/2000/svg" width="19.583ex" height="3.451ex" role="img" focusable="false" viewBox="0 -1164 8655.6 1525.2" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="2207" d="M46 676Q46 679 51 683H781Q786 679 786 676Q786 674 617 326T444 -26Q439 -33 416 -33T388 -26Q385 -22 216 326T46 676ZM697 596Q697 597 445 597T193 596Q195 591 319 336T445 80L697 596Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(1055.2,0)"><path data-c="D7" d="M630 29Q630 9 609 9Q604 9 587 25T493 118L389 222L284 117Q178 13 175 11Q171 9 168 9Q160 9 154 15T147 29Q147 36 161 51T255 146L359 250L255 354Q174 435 161 449T147 471Q147 480 153 485T168 490Q173 490 175 489Q178 487 284 383L389 278L493 382Q570 459 587 475T609 491Q630 491 630 471Q630 464 620 453T522 355L418 250L522 145Q606 61 618 48T630 29Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(2055.4,0)"><g data-mml-node="mover"><g data-mml-node="TeXAtom" data-mjx-texclass="ORD"><g data-mml-node="mi"><path data-c="1D404" d="M723 286Q721 284 700 145T677 3V0H39V62H147V618H39V680H660V676Q662 670 675 552T691 428V424H629V428Q629 429 627 448T618 494T601 541Q574 593 527 605T382 618H374H304V384H336Q338 384 347 384T361 384T376 386T392 390T407 397T421 407T432 423Q442 444 443 482V501H505V205H443V224Q442 258 435 278T411 307T380 318T336 322H304V62H375H394Q429 62 449 62T497 66T541 76T577 95T609 126T632 170T651 232Q661 287 661 289H723V286Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(378,269) translate(-250 0)"><path data-c="20D7" d="M377 694Q377 702 382 708T397 714Q404 714 409 709Q414 705 419 690Q429 653 460 633Q471 626 471 615Q471 606 468 603T454 594Q411 572 379 531Q377 529 374 525T369 519T364 517T357 516Q350 516 344 521T337 536Q337 555 384 595H213L42 596Q29 605 29 615Q29 622 42 635H401Q377 673 377 694Z" style="stroke-width: 3;"/></g></g></g><g data-mml-node="mstyle" transform="translate(2811.4,0)"><g data-mml-node="mspace"/></g><g data-mml-node="mo" transform="translate(3200.7,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mstyle" transform="translate(3978.7,0)"><g data-mml-node="mspace"/></g><g data-mml-node="mfrac" transform="translate(4367.9,0)"><g data-mml-node="mn" transform="translate(220,394) scale(0.707)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(243.7,-345) scale(0.707)"><path data-c="1D450" d="M34 159Q34 268 120 355T306 442Q362 442 394 418T427 355Q427 326 408 306T360 285Q341 285 330 295T319 325T330 359T352 380T366 386H367Q367 388 361 392T340 400T306 404Q276 404 249 390Q228 381 206 359Q162 315 142 235T121 119Q121 73 147 50Q169 26 205 26H209Q321 26 394 111Q403 121 406 121Q410 121 419 112T429 98T420 83T391 55T346 25T282 0T202 -11Q127 -11 81 37T34 159Z" style="stroke-width: 3;"/></g><rect width="553.6" height="60" x="120" y="220"/></g><g data-mml-node="mstyle" transform="translate(5161.4,0)"><g data-mml-node="mspace"/></g><g data-mml-node="mfrac" transform="translate(5328.4,0)"><g data-mml-node="mrow" transform="translate(220,394) scale(0.707)"><g data-mml-node="mi"><path data-c="1D715" d="M202 508Q179 508 169 520T158 547Q158 557 164 577T185 624T230 675T301 710L333 715H345Q378 715 384 714Q447 703 489 661T549 568T566 457Q566 362 519 240T402 53Q321 -22 223 -22Q123 -22 73 56Q42 102 42 148V159Q42 276 129 370T322 465Q383 465 414 434T455 367L458 378Q478 461 478 515Q478 603 437 639T344 676Q266 676 223 612Q264 606 264 572Q264 547 246 528T202 508ZM430 306Q430 372 401 400T333 428Q270 428 222 382Q197 354 183 323T150 221Q132 149 132 116Q132 21 232 21Q244 21 250 22Q327 35 374 112Q389 137 409 196T430 306Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(566,0)"><g data-mml-node="mover"><g data-mml-node="TeXAtom" data-mjx-texclass="ORD"><g data-mml-node="mi"><path data-c="1D401" d="M720 510Q720 476 704 448T665 404T619 377T580 362L564 359L583 356Q602 353 632 342T690 312Q712 292 725 276Q752 235 752 189V183Q752 160 741 125Q698 18 547 2Q543 1 288 0H39V62H147V624H39V686H264H409Q502 686 542 681T624 655Q720 607 720 510ZM563 513Q563 553 548 578T518 611T486 622Q479 624 385 624H293V382H375Q458 383 467 385Q563 405 563 513ZM590 192Q590 307 505 329Q504 330 503 330L398 331H293V62H391H400H444Q496 62 528 75T580 131Q590 155 590 192Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(409,275) translate(-250 0)"><path data-c="20D7" d="M377 694Q377 702 382 708T397 714Q404 714 409 709Q414 705 419 690Q429 653 460 633Q471 626 471 615Q471 606 468 603T454 594Q411 572 379 531Q377 529 374 525T369 519T364 517T357 516Q350 516 344 521T337 536Q337 555 384 595H213L42 596Q29 605 29 615Q29 622 42 635H401Q377 673 377 694Z" style="stroke-width: 3;"/></g></g></g></g><g data-mml-node="mrow" transform="translate(381.6,-345.6) scale(0.707)"><g data-mml-node="mi"><path data-c="1D715" d="M202 508Q179 508 169 520T158 547Q158 557 164 577T185 624T230 675T301 710L333 715H345Q378 715 384 714Q447 703 489 661T549 568T566 457Q566 362 519 240T402 53Q321 -22 223 -22Q123 -22 73 56Q42 102 42 148V159Q42 276 129 370T322 465Q383 465 414 434T455 367L458 378Q478 461 478 515Q478 603 437 639T344 676Q266 676 223 612Q264 606 264 572Q264 547 246 528T202 508ZM430 306Q430 372 401 400T333 428Q270 428 222 382Q197 354 183 323T150 221Q132 149 132 116Q132 21 232 21Q244 21 250 22Q327 35 374 112Q389 137 409 196T430 306Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(566,0)"><path data-c="1D461" d="M26 385Q19 392 19 395Q19 399 22 411T27 425Q29 430 36 430T87 431H140L159 511Q162 522 166 540T173 566T179 586T187 603T197 615T211 624T229 626Q247 625 254 615T261 596Q261 589 252 549T232 470L222 433Q222 431 272 431H323Q330 424 330 420Q330 398 317 385H210L174 240Q135 80 135 68Q135 26 162 26Q197 26 230 60T283 144Q285 150 288 151T303 153H307Q322 153 322 145Q322 142 319 133Q314 117 301 95T267 48T216 6T155 -11Q125 -11 98 4T59 56Q57 64 57 83V101L92 241Q127 382 128 383Q128 385 77 385H26Z" style="stroke-width: 3;"/></g></g><rect width="1178.6" height="60" x="120" y="220"/></g><g data-mml-node="mo" transform="translate(7024.9,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(8080.6,0)"><g data-mml-node="mover"><g data-mml-node="TeXAtom" data-mjx-texclass="ORD"><g data-mml-node="mn"><path data-c="1D7CE" d="M266 654H280H282Q500 654 524 418Q529 370 529 320Q529 125 456 52Q397 -10 287 -10Q110 -10 63 154Q45 212 45 316Q45 504 113 585Q140 618 185 636T266 654ZM374 548Q347 604 286 604Q247 604 218 575Q197 552 193 511T188 311Q188 159 196 116Q202 87 225 64T287 41Q339 41 367 87Q379 107 382 152T386 329Q386 518 374 548Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(287.5,243) translate(-250 0)"><path data-c="20D7" d="M377 694Q377 702 382 708T397 714Q404 714 409 709Q414 705 419 690Q429 653 460 633Q471 626 471 615Q471 606 468 603T454 594Q411 572 379 531Q377 529 374 525T369 519T364 517T357 516Q350 516 344 521T337 536Q337 555 384 595H213L42 596Q29 605 29 615Q29 622 42 635H401Q377 673 377 694Z" style="stroke-width: 3;"/></g></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi mathvariant="normal">∇</mi><mo>×</mo><mrow data-mjx-texclass="ORD"><mover><mrow data-mjx-texclass="ORD"><mi mathvariant="bold">E</mi></mrow><mo stretchy="false">→</mo></mover></mrow><mstyle scriptlevel="0"><mspace width="0.167em"/></mstyle><mo>+</mo><mstyle scriptlevel="0"><mspace width="0.167em"/></mstyle><mfrac><mn>1</mn><mi>c</mi></mfrac><mstyle scriptlevel="0"><mspace width="0.167em"/></mstyle><mfrac><mrow><mi>∂</mi><mrow data-mjx-texclass="ORD"><mover><mrow data-mjx-texclass="ORD"><mi mathvariant="bold">B</mi></mrow><mo stretchy="false">→</mo></mover></mrow></mrow><mrow><mi>∂</mi><mi>t</mi></mrow></mfrac><mo>=</mo><mrow data-mjx-texclass="ORD"><mover><mrow data-mjx-texclass="ORD"><mn mathvariant="bold">0</mn></mrow><mo stretchy="false">→</mo></mover></mrow></math></mjx-assistive-mml></mjx-container></td>
<td>curl of <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: 0;" xmlns="http://www.w3.org/2000/svg" width="1.71ex" height="2.45ex" role="img" focusable="false" viewBox="0 -1083 756 1083" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="TeXAtom" data-mjx-texclass="ORD"><g data-mml-node="mover"><g data-mml-node="TeXAtom" data-mjx-texclass="ORD"><g data-mml-node="mi"><path data-c="1D404" d="M723 286Q721 284 700 145T677 3V0H39V62H147V618H39V680H660V676Q662 670 675 552T691 428V424H629V428Q629 429 627 448T618 494T601 541Q574 593 527 605T382 618H374H304V384H336Q338 384 347 384T361 384T376 386T392 390T407 397T421 407T432 423Q442 444 443 482V501H505V205H443V224Q442 258 435 278T411 307T380 318T336 322H304V62H375H394Q429 62 449 62T497 66T541 76T577 95T609 126T632 170T651 232Q661 287 661 289H723V286Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(378,269) translate(-250 0)"><path data-c="20D7" d="M377 694Q377 702 382 708T397 714Q404 714 409 709Q414 705 419 690Q429 653 460 633Q471 626 471 615Q471 606 468 603T454 594Q411 572 379 531Q377 529 374 525T369 519T364 517T357 516Q350 516 344 521T337 536Q337 555 384 595H213L42 596Q29 605 29 615Q29 622 42 635H401Q377 673 377 694Z" style="stroke-width: 3;"/></g></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mrow data-mjx-texclass="ORD"><mover><mrow data-mjx-texclass="ORD"><mi mathvariant="bold">E</mi></mrow><mo stretchy="false">→</mo></mover></mrow></math></mjx-assistive-mml></mjx-container> is proportional to the rate of change of <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: 0;" xmlns="http://www.w3.org/2000/svg" width="1.851ex" height="2.464ex" role="img" focusable="false" viewBox="0 -1089 818 1089" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="TeXAtom" data-mjx-texclass="ORD"><g data-mml-node="mover"><g data-mml-node="TeXAtom" data-mjx-texclass="ORD"><g data-mml-node="mi"><path data-c="1D401" d="M720 510Q720 476 704 448T665 404T619 377T580 362L564 359L583 356Q602 353 632 342T690 312Q712 292 725 276Q752 235 752 189V183Q752 160 741 125Q698 18 547 2Q543 1 288 0H39V62H147V624H39V686H264H409Q502 686 542 681T624 655Q720 607 720 510ZM563 513Q563 553 548 578T518 611T486 622Q479 624 385 624H293V382H375Q458 383 467 385Q563 405 563 513ZM590 192Q590 307 505 329Q504 330 503 330L398 331H293V62H391H400H444Q496 62 528 75T580 131Q590 155 590 192Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(409,275) translate(-250 0)"><path data-c="20D7" d="M377 694Q377 702 382 708T397 714Q404 714 409 709Q414 705 419 690Q429 653 460 633Q471 626 471 615Q471 606 468 603T454 594Q411 572 379 531Q377 529 374 525T369 519T364 517T357 516Q350 516 344 521T337 536Q337 555 384 595H213L42 596Q29 605 29 615Q29 622 42 635H401Q377 673 377 694Z" style="stroke-width: 3;"/></g></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mrow data-mjx-texclass="ORD"><mover><mrow data-mjx-texclass="ORD"><mi mathvariant="bold">B</mi></mrow><mo stretchy="false">→</mo></mover></mrow></math></mjx-assistive-mml></mjx-container></td>
</tr>
<tr>
<td><mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.817ex;" xmlns="http://www.w3.org/2000/svg" width="33.284ex" height="3.441ex" role="img" focusable="false" viewBox="0 -1159.8 14711.4 1520.9" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="2207" d="M46 676Q46 679 51 683H781Q786 679 786 676Q786 674 617 326T444 -26Q439 -33 416 -33T388 -26Q385 -22 216 326T46 676ZM697 596Q697 597 445 597T193 596Q195 591 319 336T445 80L697 596Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(1055.2,0)"><path data-c="D7" d="M630 29Q630 9 609 9Q604 9 587 25T493 118L389 222L284 117Q178 13 175 11Q171 9 168 9Q160 9 154 15T147 29Q147 36 161 51T255 146L359 250L255 354Q174 435 161 449T147 471Q147 480 153 485T168 490Q173 490 175 489Q178 487 284 383L389 278L493 382Q570 459 587 475T609 491Q630 491 630 471Q630 464 620 453T522 355L418 250L522 145Q606 61 618 48T630 29Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(2055.4,0)"><g data-mml-node="mover"><g data-mml-node="TeXAtom" data-mjx-texclass="ORD"><g data-mml-node="mi"><path data-c="1D401" d="M720 510Q720 476 704 448T665 404T619 377T580 362L564 359L583 356Q602 353 632 342T690 312Q712 292 725 276Q752 235 752 189V183Q752 160 741 125Q698 18 547 2Q543 1 288 0H39V62H147V624H39V686H264H409Q502 686 542 681T624 655Q720 607 720 510ZM563 513Q563 553 548 578T518 611T486 622Q479 624 385 624H293V382H375Q458 383 467 385Q563 405 563 513ZM590 192Q590 307 505 329Q504 330 503 330L398 331H293V62H391H400H444Q496 62 528 75T580 131Q590 155 590 192Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(409,275) translate(-250 0)"><path data-c="20D7" d="M377 694Q377 702 382 708T397 714Q404 714 409 709Q414 705 419 690Q429 653 460 633Q471 626 471 615Q471 606 468 603T454 594Q411 572 379 531Q377 529 374 525T369 519T364 517T357 516Q350 516 344 521T337 536Q337 555 384 595H213L42 596Q29 605 29 615Q29 622 42 635H401Q377 673 377 694Z" style="stroke-width: 3;"/></g></g></g><g data-mml-node="mo" transform="translate(3095.7,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"/></g><g data-mml-node="mstyle" transform="translate(3873.7,0)"><g data-mml-node="mspace"/></g><g data-mml-node="mfrac" transform="translate(4262.9,0)"><g data-mml-node="mn" transform="translate(220,394) scale(0.707)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(243.7,-345) scale(0.707)"><path data-c="1D450" d="M34 159Q34 268 120 355T306 442Q362 442 394 418T427 355Q427 326 408 306T360 285Q341 285 330 295T319 325T330 359T352 380T366 386H367Q367 388 361 392T340 400T306 404Q276 404 249 390Q228 381 206 359Q162 315 142 235T121 119Q121 73 147 50Q169 26 205 26H209Q321 26 394 111Q403 121 406 121Q410 121 419 112T429 98T420 83T391 55T346 25T282 0T202 -11Q127 -11 81 37T34 159Z" style="stroke-width: 3;"/></g><rect width="553.6" height="60" x="120" y="220"/></g><g data-mml-node="mstyle" transform="translate(5056.4,0)"><g data-mml-node="mspace"/></g><g data-mml-node="mfrac" transform="translate(5223.4,0)"><g data-mml-node="mrow" transform="translate(220,394) scale(0.707)"><g data-mml-node="mi"><path data-c="1D715" d="M202 508Q179 508 169 520T158 547Q158 557 164 577T185 624T230 675T301 710L333 715H345Q378 715 384 714Q447 703 489 661T549 568T566 457Q566 362 519 240T402 53Q321 -22 223 -22Q123 -22 73 56Q42 102 42 148V159Q42 276 129 370T322 465Q383 465 414 434T455 367L458 378Q478 461 478 515Q478 603 437 639T344 676Q266 676 223 612Q264 606 264 572Q264 547 246 528T202 508ZM430 306Q430 372 401 400T333 428Q270 428 222 382Q197 354 183 323T150 221Q132 149 132 116Q132 21 232 21Q244 21 250 22Q327 35 374 112Q389 137 409 196T430 306Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(566,0)"><g data-mml-node="mover"><g data-mml-node="TeXAtom" data-mjx-texclass="ORD"><g data-mml-node="mi"><path data-c="1D404" d="M723 286Q721 284 700 145T677 3V0H39V62H147V618H39V680H660V676Q662 670 675 552T691 428V424H629V428Q629 429 627 448T618 494T601 541Q574 593 527 605T382 618H374H304V384H336Q338 384 347 384T361 384T376 386T392 390T407 397T421 407T432 423Q442 444 443 482V501H505V205H443V224Q442 258 435 278T411 307T380 318T336 322H304V62H375H394Q429 62 449 62T497 66T541 76T577 95T609 126T632 170T651 232Q661 287 661 289H723V286Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(378,269) translate(-250 0)"><path data-c="20D7" d="M377 694Q377 702 382 708T397 714Q404 714 409 709Q414 705 419 690Q429 653 460 633Q471 626 471 615Q471 606 468 603T454 594Q411 572 379 531Q377 529 374 525T369 519T364 517T357 516Q350 516 344 521T337 536Q337 555 384 595H213L42 596Q29 605 29 615Q29 622 42 635H401Q377 673 377 694Z" style="stroke-width: 3;"/></g></g></g></g><g data-mml-node="mrow" transform="translate(359.7,-345.6) scale(0.707)"><g data-mml-node="mi"><path data-c="1D715" d="M202 508Q179 508 169 520T158 547Q158 557 164 577T185 624T230 675T301 710L333 715H345Q378 715 384 714Q447 703 489 661T549 568T566 457Q566 362 519 240T402 53Q321 -22 223 -22Q123 -22 73 56Q42 102 42 148V159Q42 276 129 370T322 465Q383 465 414 434T455 367L458 378Q478 461 478 515Q478 603 437 639T344 676Q266 676 223 612Q264 606 264 572Q264 547 246 528T202 508ZM430 306Q430 372 401 400T333 428Q270 428 222 382Q197 354 183 323T150 221Q132 149 132 116Q132 21 232 21Q244 21 250 22Q327 35 374 112Q389 137 409 196T430 306Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(566,0)"><path data-c="1D461" d="M26 385Q19 392 19 395Q19 399 22 411T27 425Q29 430 36 430T87 431H140L159 511Q162 522 166 540T173 566T179 586T187 603T197 615T211 624T229 626Q247 625 254 615T261 596Q261 589 252 549T232 470L222 433Q222 431 272 431H323Q330 424 330 420Q330 398 317 385H210L174 240Q135 80 135 68Q135 26 162 26Q197 26 230 60T283 144Q285 150 288 151T303 153H307Q322 153 322 145Q322 142 319 133Q314 117 301 95T267 48T216 6T155 -11Q125 -11 98 4T59 56Q57 64 57 83V101L92 241Q127 382 128 383Q128 385 77 385H26Z" style="stroke-width: 3;"/></g></g><rect width="1134.8" height="60" x="120" y="220"/></g><g data-mml-node="mo" transform="translate(6876,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="mfrac" transform="translate(7931.8,0)"><g data-mml-node="mrow" transform="translate(220,394) scale(0.707)"><g data-mml-node="mn"><path data-c="34" d="M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(500,0)"><path data-c="1D70B" d="M132 -11Q98 -11 98 22V33L111 61Q186 219 220 334L228 358H196Q158 358 142 355T103 336Q92 329 81 318T62 297T53 285Q51 284 38 284Q19 284 19 294Q19 300 38 329T93 391T164 429Q171 431 389 431Q549 431 553 430Q573 423 573 402Q573 371 541 360Q535 358 472 358H408L405 341Q393 269 393 222Q393 170 402 129T421 65T431 37Q431 20 417 5T381 -10Q370 -10 363 -7T347 17T331 77Q330 86 330 121Q330 170 339 226T357 318T367 358H269L268 354Q268 351 249 275T206 114T175 17Q164 -11 132 -11Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mi" transform="translate(445.2,-345) scale(0.707)"><path data-c="1D450" d="M34 159Q34 268 120 355T306 442Q362 442 394 418T427 355Q427 326 408 306T360 285Q341 285 330 295T319 325T330 359T352 380T366 386H367Q367 388 361 392T340 400T306 404Q276 404 249 390Q228 381 206 359Q162 315 142 235T121 119Q121 73 147 50Q169 26 205 26H209Q321 26 394 111Q403 121 406 121Q410 121 419 112T429 98T420 83T391 55T346 25T282 0T202 -11Q127 -11 81 37T34 159Z" style="stroke-width: 3;"/></g><rect width="956.6" height="60" x="120" y="220"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(9128.4,0)"><g data-mml-node="mover"><g data-mml-node="TeXAtom" data-mjx-texclass="ORD"><g data-mml-node="mi"><path data-c="1D423" d="M104 610Q104 649 130 672T191 695Q225 693 249 670T273 610Q273 572 249 549T189 525Q152 525 128 548T104 610ZM78 442L173 446L268 450H274V196Q274 -5 274 -37T269 -83Q256 -132 201 -166T71 -200Q10 -200 -30 -173T-71 -102Q-71 -70 -51 -51T-1 -31Q27 -31 48 -49T69 -100Q69 -121 53 -147H56Q66 -149 77 -149H80Q90 -149 100 -146T127 -125T149 -73Q151 -55 151 149V362Q150 364 148 366T145 370T142 373T138 375T133 377T124 378T113 379T97 380H75V442H78Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(175.5,284) translate(-250 0)"><path data-c="20D7" d="M377 694Q377 702 382 708T397 714Q404 714 409 709Q414 705 419 690Q429 653 460 633Q471 626 471 615Q471 606 468 603T454 594Q411 572 379 531Q377 529 374 525T369 519T364 517T357 516Q350 516 344 521T337 536Q337 555 384 595H213L42 596Q29 605 29 615Q29 622 42 635H401Q377 673 377 694Z" style="stroke-width: 3;"/></g></g></g><g data-mml-node="mi" transform="translate(9479.4,0)"><path data-c="2207" d="M46 676Q46 679 51 683H781Q786 679 786 676Q786 674 617 326T444 -26Q439 -33 416 -33T388 -26Q385 -22 216 326T46 676ZM697 596Q697 597 445 597T193 596Q195 591 319 336T445 80L697 596Z" style="stroke-width: 3;"/></g><g data-mml-node="mo" transform="translate(10534.6,0)"><path data-c="22C5" d="M78 250Q78 274 95 292T138 310Q162 310 180 294T199 251Q199 226 182 208T139 190T96 207T78 250Z" style="stroke-width: 3;"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(11034.8,0)"><g data-mml-node="mover"><g data-mml-node="TeXAtom" data-mjx-texclass="ORD"><g data-mml-node="mi"><path data-c="1D404" d="M723 286Q721 284 700 145T677 3V0H39V62H147V618H39V680H660V676Q662 670 675 552T691 428V424H629V428Q629 429 627 448T618 494T601 541Q574 593 527 605T382 618H374H304V384H336Q338 384 347 384T361 384T376 386T392 390T407 397T421 407T432 423Q442 444 443 482V501H505V205H443V224Q442 258 435 278T411 307T380 318T336 322H304V62H375H394Q429 62 449 62T497 66T541 76T577 95T609 126T632 170T651 232Q661 287 661 289H723V286Z" style="stroke-width: 3;"/></g></g><g data-mml-node="mo" transform="translate(378,269) translate(-250 0)"><path data-c="20D7" d="M377 694Q377 702 382 708T397 714Q404 714 409 709Q414 705 419 690Q429 653 460 633Q471 626 471 615Q471 606 468 603T454 594Q411 572 379 531Q377 529 374 525T369 519T364 517T357 516Q350 516 344 521T337 536Q337 555 384 595H213L42 596Q29 605 29 615Q29 622 42 635H401Q377 673 377 694Z" style="stroke-width: 3;"/></g></g></g><g data-mml-node="mo" transform="translate(12068.6,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"/></g><g data-mml-node="mn" transform="translate(13124.4,0)"><path data-c="34" d="M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(13624.4,0)"><path data-c="1D70B" d="M132 -11Q98 -11 98 22V33L111 61Q186 219 220 334L228 358H196Q158 358 142 355T103 336Q92 329 81 318T62 297T53 285Q51 284 38 284Q19 284 19 294Q19 300 38 329T93 391T164 429Q171 431 389 431Q549 431 553 430Q573 423 573 402Q573 371 541 360Q535 358 472 358H408L405 341Q393 269 393 222Q393 170 402 129T421 65T431 37Q431 20 417 5T381 -10Q370 -10 363 -7T347 17T331 77Q330 86 330 121Q330 170 339 226T357 318T367 358H269L268 354Q268 351 249 275T206 114T175 17Q164 -11 132 -11Z" style="stroke-width: 3;"/></g><g data-mml-node="mi" transform="translate(14194.4,0)"><path data-c="1D70C" d="M58 -216Q25 -216 23 -186Q23 -176 73 26T127 234Q143 289 182 341Q252 427 341 441Q343 441 349 441T359 442Q432 442 471 394T510 276Q510 219 486 165T425 74T345 13T266 -10H255H248Q197 -10 165 35L160 41L133 -71Q108 -168 104 -181T92 -202Q76 -216 58 -216ZM424 322Q424 359 407 382T357 405Q322 405 287 376T231 300Q217 269 193 170L176 102Q193 26 260 26Q298 26 334 62Q367 92 389 158T418 266T424 322Z" style="stroke-width: 3;"/></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi mathvariant="normal">∇</mi><mo>×</mo><mrow data-mjx-texclass="ORD"><mover><mrow data-mjx-texclass="ORD"><mi mathvariant="bold">B</mi></mrow><mo stretchy="false">→</mo></mover></mrow><mo>−</mo><mstyle scriptlevel="0"><mspace width="0.167em"/></mstyle><mfrac><mn>1</mn><mi>c</mi></mfrac><mstyle scriptlevel="0"><mspace width="0.167em"/></mstyle><mfrac><mrow><mi>∂</mi><mrow data-mjx-texclass="ORD"><mover><mrow data-mjx-texclass="ORD"><mi mathvariant="bold">E</mi></mrow><mo stretchy="false">→</mo></mover></mrow></mrow><mrow><mi>∂</mi><mi>t</mi></mrow></mfrac><mo>=</mo><mfrac><mrow><mn>4</mn><mi>π</mi></mrow><mi>c</mi></mfrac><mrow data-mjx-texclass="ORD"><mover><mrow data-mjx-texclass="ORD"><mi mathvariant="bold">j</mi></mrow><mo stretchy="false">→</mo></mover></mrow><mi mathvariant="normal">∇</mi><mo>⋅</mo><mrow data-mjx-texclass="ORD"><mover><mrow data-mjx-texclass="ORD"><mi mathvariant="bold">E</mi></mrow><mo stretchy="false">→</mo></mover></mrow><mo>=</mo><mn>4</mn><mi>π</mi><mi>ρ</mi></math></mjx-assistive-mml></mjx-container></td>
<td><em>wha?</em></td>
</tr>
</tbody>
</table>
]]></content>
        <author>
            <name>duyl328</name>
            <uri>https://seyl.me/about</uri>
        </author>
        <category label="学习"/>
        <category label="VitePress"/>
        <category label="Blog"/>
        <category label="原创"/>
        <category label="Markdown"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Vue3新属性 — css中使用v-bind（v-bind in css）]]></title>
        <id>https://seyl.me/posts/2022/08/v-bind-in-css</id>
        <link href="https://seyl.me/posts/2022/08/v-bind-in-css"/>
        <updated>2024-08-11T00:00:00.000Z</updated>
        <content type="html"><![CDATA[<h1 id="frontmatter-title" tabindex="-1">{{ $frontmatter.title }} <a class="header-anchor" href="#frontmatter-title" aria-label="Permalink to &quot;{{ $frontmatter.title }}&quot;">&ZeroWidthSpace;</a></h1>
<blockquote>
<p>✒️ 文章摘要</p>
</blockquote>
<!-- DESC SEP -->
<p>这篇文章介绍了在 Vue3 中如何使用 v-bind() 来动态绑定 CSS 样式，尤其是在 CSS、LESS 和 SCSS 文件中的应用。</p>
<p>关键内容总结：
背景：文章解释了 Vue3 中 v-bind() 在样式绑定中的新用法，展示了在不同样式表语言（CSS、LESS、SCSS）中的常见应用场景。
实际示例：
CSS：展示了通过 v-bind() 绑定直接使用的值、拼接值、对象调用和组合使用四种方式。
LESS：与 CSS 类似，使用变量和 v-bind() 绑定数据，但在 LESS 中出现了拼接使用的问题。
问题分析：
拼接使用问题：在 LESS 中，某些拼接方式无法正常工作，导致变量无法正确转换为带单位的值，甚至会导致错误。
错误提示：解释了因 LESS 在拼接操作时报错，导致绑定失败的问题。</p>
<!-- DESC SEP -->
<h1 id="vue3新属性-css-中的-v-bind" tabindex="-1">Vue3新属性：CSS 中的 <code>v-bind()</code> <a class="header-anchor" href="#vue3新属性-css-中的-v-bind" aria-label="Permalink to &quot;Vue3新属性：CSS 中的 `v-bind()`&quot;">&ZeroWidthSpace;</a></h1>
<h2 id="write-in-front" tabindex="-1">写在前面 <a class="header-anchor" href="#write-in-front" aria-label="Permalink to &quot;写在前面 {#write-in-front}&quot;">&ZeroWidthSpace;</a></h2>
<p>本文主要介绍Vue3中的新增的<code>v-bind()</code>的常用使用方式，主要包括在<code>css</code>,<code>less</code>,<code>scss</code>中的使用，可以参考官方文档查看：<a href="https://cn.vuejs.org/api/sfc-css-features.html#v-bind-in-css" target="_blank" rel="noreferrer">Vue3官方文档</a>，本文将主要通过一个demo中的使用来展示</p>
<h2 id="actual-use" tabindex="-1">实际使用 <a class="header-anchor" href="#actual-use" aria-label="Permalink to &quot;实际使用{#actual-use}&quot;">&ZeroWidthSpace;</a></h2>
<p>先创建一个通过的页面结构，因为是结构是通用内容，所以这里在直接进行简单的定义</p>
<div class="language-html vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">html</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"div"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"span"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"span_title"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      这是测试文字</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    &#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  &#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span></code></pre>
</div><ul>
<li>
<p>在<code>css</code>中：</p>
<p>在<code>css</code>中主要通过直接进行绑定，主要包括几种使用方式（我自己编的名词）：<code>直接使用</code>、<code>拼接使用</code>、<code>对象调用</code>、<code>组合使用</code>【这是我想到的几种常见方式，如果有特殊需求，可以评论区沟通】</p>
<p>在JS中先对需要用的数据进行定义：</p>
<div class="language-js vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 进行拼接调用测试的数据</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> width </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 400</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 直接调用的数据</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> div_height </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> '400px'</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> div_color </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> '#e89393'</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 对象调用的数据</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> span </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  width: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'200px'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  height: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'200px'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  color: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'green'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 组合调用的数据</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> transition </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'cubic-bezier(0, 1.5, .6, 1)'</span></span></code></pre>
</div><p>然后这些数据直接在<code>css</code>中进行使用，使用<code>v-bind()</code>进行绑定</p>
<div class="language-css vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">css</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">style</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> scoped lang="css"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">></span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">.div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  /* 拼接使用 */</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: v-bind(width + </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'px'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  /* 直接使用 */</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  height</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: v-bind(div_height);</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  background</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: v-bind(div_color);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">.span</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  /* 对象调用 */</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: v-bind(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'span.width'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  height</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: v-bind(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'span.height'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  background</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: v-bind(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'span.color'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  display</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">flex</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  justify-content</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">center</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  align-items</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">center</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">.span_title</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  height</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  background</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">#000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  color</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">white</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  /* 组合使用 */</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  transition</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">all</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> .9</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">s</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> v-bind(transition);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">.span:hover</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> .span_title</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  border-radius</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">50</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">%</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  background</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">#a5f5b8</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  color</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">#ff0000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">style</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">></span></span></code></pre>
</div><p>在对应的四个方式的调用中：</p>
<p><code>直接使用</code>：完全没有问题</p>
<p><code>拼接使用</code>：这个在<code>css</code>中没有问题，不过在<code>scss</code>中会出现错误，这个在下面的<code>scss</code>中会有详细介绍</p>
<p><code>对象调用</code>：对象的调用和直接使用类似，不过不同的是，需要使用引号的包裹才能正常使用，如果直接书写会报错</p>
<p><code>组合使用</code>：完全没问题</p>
</li>
<li>
<p>在<code>less</code>中：</p>
<p>使用的数据同样是上面给出的数据，这里直接改样式的内容了</p>
<div class="language-css vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">css</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">style</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> scoped lang="less"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">// 使用变量承接</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">@height</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: v-bind(div_height);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">.div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">400</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  /* 直接使用 */</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  height</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: @height;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  background</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: v-bind(div_color);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  .</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">span</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    @</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: v-bind(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'span.width'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    /* 对象调用 */</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: @width;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    height</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: v-bind(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'span.height'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    background</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: v-bind(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'span.color'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    display</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">flex</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    justify-content</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">center</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    align-items</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">center</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    .</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">span</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">_</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">title</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      @</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">transition</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: v-bind(transition);</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      height</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      background</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">#000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      color</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">white</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">      /* 组合使用 */</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      transition</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">all</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> .9</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">s</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> @transition;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    &#x26;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">:hover</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> .span_title</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      border-radius</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">50</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">%</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      background</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">#a5f5b8</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      color</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">#ff0000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">style</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">></span></span></code></pre>
</div><p><code>直接使用</code>：没有问题</p>
<p><code>拼接使用</code>：<strong>存在问题</strong>，在下面尝试进行了解决</p>
<p><code>对象调用</code>：没问题</p>
<p><code>组合使用</code>：没问题</p>
<h3>问题：</h3>
<blockquote>
<p>在拼接使用有几种方式：</p>
<div class="language-js vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 定义使用的数据</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> width </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 400</span></span></code></pre>
</div><div class="language-css vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">css</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">// 直接拼接</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">@width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: v-bind( width + 'px');</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">width: </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">@width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">// 拿到内容后拼接</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">@width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: v-bind(width) + 'px';</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">width: </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">@width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">// 使用时拼接</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">@width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: v-bind(width);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">width: </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">@width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> + 'px';</span></span></code></pre>
</div><p>常用的拼接方法一般为这几种（如果有欠缺还请补充），这几种方式都进行了尝试，其中第二种第三种会没有效果，第一种会直接报错</p>
</blockquote>
<h3>问题分析（尝试解决）：【这部分会很长，如果不想看，可以直接跳到解决方法】</h3>
<p>首先是第一种，如果使用的话会直接报错，报错内容为：</p>
</li>
</ul>
<p><img src="./../../../public/posts/2022/08/img-1.webp" alt="在这里插入图片描述"></p>
<p>因为<code>less</code>的直接报错，导致定义的变量压根就没有被编译出来，从而报错</p>
<p>第二种和第三种错误一样：</p>
<p><img src="./../../../public/posts/2022/08/img-2.webp" alt="在这里插入图片描述"></p>
<p>在这种使用方式中，变量可以正确承接，但是不能完成拼接的操作，导致只有变量而没有单位，并且可以看出最终都被翻译为<code>var(--变量名)</code>来执行，所以顺便也对<code>var()</code>进行了拼接测试</p>
<p><img src="./../../../public/posts/2022/08/img-3.webp" alt="在这里插入图片描述"></p>
<p>这里进行调用内容的定义，并且模仿编译后的内容，进行使用，在这种情况下尝试使用拼接</p>
<blockquote>
<p>尝试的拼接方式：</p>
<p><code>直接拼接</code>：</p>
<div class="language-css vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">css</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">:root</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">  --test</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">400</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> + </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'px'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">/* 使用 */</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">width: var(--test);</span></span></code></pre>
</div><p><code>接受变量后拼接</code>：</p>
<div class="language-css vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">css</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">:root</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">  --test</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">400</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> + </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'px'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">/* 使用 */</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">width: var(--test</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> 'px');</span></span></code></pre>
</div><p><code>继承后拼接</code>：</p>
<div class="language-css vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">css</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">:root</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">  --test</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">400</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> + </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'px'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">/* 使用 */</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">width: var(--test) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> 'px';</span></span></code></pre>
</div></blockquote>
<p>结果也非常让不出意外的都不行，并且在第二种方式也是直接报错的，在寻找问题的过程中，发现了更加<code>amazing</code>的事情：</p>
<p><img src="./../../../public/posts/2022/08/img-4.webp" alt="在这里插入图片描述"></p>
<p>这个变量压根就没定义，或者说没被识别到，所以重新模仿<code>Vue</code>直接定义行内样式，并且使用拼接尝试：</p>
<p><img src="./../../../public/posts/2022/08/img-5.webp" alt="在这里插入图片描述"></p>
<p>这种直接的拼接方式直接将所有内容都进行了拼接，再换一种思路：使用<code>V-bind</code>这个V-bind指的是数据的而不是样式：</p>
<p><img src="./../../../public/posts/2022/08/img-6.webp" alt="在这里插入图片描述"></p>
<p>这次问题得到了解决，并且样式数据也是响应式的单个数据，并且也是在<code>less</code>中正确使用，应该也算解决问题吧</p>
  <h3>解决方式（思路）：</h3>
<p>将变量的内容在<code>行内样式</code>使用拼接的方式进行定义，然后在定义的<code>less或scss</code>中进行使用，因为定义的样式是行内样式，所以优先级和变量出现的位置，都是在使用之前，所以可以正常使用</p>
  <h3>完整代码：</h3>
<blockquote>
<p>使用数据的定义：</p>
<div class="language-js vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 大部分数据和预先提供的数据一样（这里只写了新增数据）</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> test </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 400</span></span></code></pre>
</div><p>页面结构：</p>
<div class="language-html vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">html</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">&#x3C;!--	改变的内容为下面这行（其他内容和原来内容保持一致）--></span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">&#x3C;!--	【在这里对要使用的数据进行单位的绑定】--></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"div"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> :style</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"{'--test' :test + 'px'}"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"span"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">   &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"span_title"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">     这是测试文字</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">   &#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> &#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span></code></pre>
</div><p>样式的使用：</p>
<div class="language-css vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">css</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">style</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> scoped lang="less"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">// 承接使用</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">@width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: var(--test);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">.div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">/* 使用 */</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: @width;</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">/* 或者直接使用 */</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">var</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">--test</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">height</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">400</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">background</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">red</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">style</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">></span></span></code></pre>
</div></blockquote>
<p>在<code>css</code>的测试中几种方式也都能完美运行，并且在<code>less</code>的特有的数据绑定中也都没有问题，对于<code>拼接使用</code>是可以正常使用的。</p>
<p>我用的工具是<code>webstorm</code>less也是唯一一个没有报错的提示的（工具内的报错提示，可能不认识新内容把）</p>
<ul>
<li>
<p>在<code>scss</code>中：</p>
<div class="language-css vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">css</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">style</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> scoped lang="scss"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">// 使用变量承接</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">$width: v-bind(width </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> 'px');</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">$height: v-bind(div_height);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">.div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  /* 拼接使用 */</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: $width;</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  /* 直接使用 */</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  height</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: $height;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  background</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: v-bind(div_color);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  .</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">span</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    $</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: v-bind(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'span.width'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    /* 对象调用 */</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: $width;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    height</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: v-bind(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'span.height'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    background</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: v-bind(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'span.color'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    display</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">flex</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    justify-content</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">center</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    align-items</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">center</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    .</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">span</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">_</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">title</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      $</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">transition</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: v-bind(transition);</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      height</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      background</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">#000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      color</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">white</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">      /* 组合使用 */</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      transition</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">all</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> .9</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">s</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> $transition;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    &#x26;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">:hover</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> .span_title</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      border-radius</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">50</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">%</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      background</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">#a5f5b8</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      color</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">#ff0000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">style</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">></span></span></code></pre>
</div><p><code>scss</code>相对<code>less</code>一些方法更加灵活，在<code>v-bind()</code>的使用中，拼接使用会出现错误，这个暂时按下不表，在原理中会详细阐述</p>
</li>
<li>
<p>执行原理：</p>
<p><code>v-bind() in css</code>并没有进行劫持或者其他操作，他主要完成的任务是将<code>v-bind()</code>中的内容通过自定义属性的方式进行了重新定义，在编译后代码中可以看到</p>
<p><img src="./../../../public/posts/2022/08/img-7.webp" alt="在这里插入图片描述"></p>
<p>所有的数据直接在自定义属性中进行，并且直接对应引用，自定义属性的内容的改变影响视图的效果，从而达到数据影响视图的效果，这个在使用中<code>less</code>,<code>css</code>中完全没有问题</p>
<p>但是，在<code>scss</code>中，因为编译之后<code>名字无法进行匹配</code>从而造成样式的丢失</p>
<p><img src="./../../../public/posts/2022/08/img-8.webp" alt="在这里插入图片描述"></p>
<p>可以看到，使用的名字和编译的名字并不匹配，从而出错，这个使用时需要注意</p>
</li>
</ul>
]]></content>
        <author>
            <name>duyl328</name>
            <uri>https://seyl.me/about</uri>
        </author>
        <category label="编程"/>
        <category label="学习"/>
        <category label="vue"/>
        <category label="Blog"/>
        <category label="原创"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[中西文混排时汉字与拉丁字母之间差异]]></title>
        <id>https://seyl.me/posts/2024/08/differences-chinese-and-latin</id>
        <link href="https://seyl.me/posts/2024/08/differences-chinese-and-latin"/>
        <updated>2024-08-07T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[<h1 id="frontmatter-title" tabindex="-1">{{ $frontmatter.title }} <a class="header-anchor" href="#frontmatter-title" aria-label="Permalink to &quot;{{ $frontmatter.title }}&quot;">&ZeroWidthSpace;</a></h1>
<blockquote>
<p>✒️ 文章摘要</p>
</blockquote>
<!-- DESC SEP -->
<p>这篇文章讨论了中英文混排时，是否应在汉字与拉丁字母之间加入空格的争议。研究和实践表明，虽然专业排版软件如Adobe InDesign通常会自动调整汉字与西文之间的间距，但许多普通用户常常手动插入半角空格以保证文本的可读性和美观。文章介绍了“空格派”在排版中的一些习惯，阐述了何时应该加空格、何时不加空格，并引用了刘昕等人关于中英文混排的标准，最后强调了空格的使用对提高文本阅读体验的重要性。</p>
<!-- DESC SEP -->
]]></summary>
        <content type="html"><![CDATA[<h1 id="frontmatter-title" tabindex="-1">{{ $frontmatter.title }} <a class="header-anchor" href="#frontmatter-title" aria-label="Permalink to &quot;{{ $frontmatter.title }}&quot;">&ZeroWidthSpace;</a></h1>
<blockquote>
<p>✒️ 文章摘要</p>
</blockquote>
<!-- DESC SEP -->
<p>这篇文章讨论了中英文混排时，是否应在汉字与拉丁字母之间加入空格的争议。研究和实践表明，虽然专业排版软件如Adobe InDesign通常会自动调整汉字与西文之间的间距，但许多普通用户常常手动插入半角空格以保证文本的可读性和美观。文章介绍了“空格派”在排版中的一些习惯，阐述了何时应该加空格、何时不加空格，并引用了刘昕等人关于中英文混排的标准，最后强调了空格的使用对提高文本阅读体验的重要性。</p>
<!-- DESC SEP -->
<hr>
<blockquote>
<p>有研究显示，打字的时候不喜欢在中文和英文之间加空格的人，感情路都走得很辛苦，有七成的比例会在 34 岁的时候跟自己不爱的人结婚，而其余三成的人最后只能把遗产留给自己的猫。毕竟爱情跟书写都需要适时地留白。与大家共勉之。</p>
<p>​	——<a href="https://github.com/vinta/pangu.js" target="_blank" rel="noreferrer">vinta/paranoid-auto-spacing</a></p>
</blockquote>
<h3 id="参考1" tabindex="-1">参考1 <a class="header-anchor" href="#参考1" aria-label="Permalink to &quot;参考1&quot;">&ZeroWidthSpace;</a></h3>
<blockquote>
<p><a href="https://www.zhihu.com/question/19587406/answer/12298128" target="_blank" rel="noreferrer">中西文混排时汉字与拉丁字母之间是否要有空格？ - 知乎 (zhihu.com)</a></p>
</blockquote>
<p>Adobe InDesign、Microsoft Word 等对中文与西文（这里用「西文」来泛指用空格分词的外文）混合排版支持较好的软件，都默认增大汉字和西文的间距。InDesign 的默认设置是 1/4 的全角空格宽度（遵从 JIS），也就是约等于一个半角空格。</p>
<p>但大多数情况下我们没有这样专业排版软件的支持，只能手动控制。这种时候，比较在意文字设计（typography，又译「字体排印」）的团队或个人往往都在操作系统界面或网站中的汉字和西文之间插入一个半角空格。</p>
<p>包括许多的</p>
<ul>
<li>公司：苹果、微软、Google、Adobe……</li>
<li>团队：Apple4us、Type is Beautiful、爱范儿……</li>
<li>个人：@刘昕、@江疆……</li>
</ul>
<p>但这些确实是绝对的少数。大多数人都不/不喜欢/不愿意在汉字和西文之间加空格。毕竟加空格要考虑的东西太多了，而且加空格也会带来一些问题（见后面给出的在 <a href="mailto:public-html-ig-zh@w3.org" target="_blank" rel="noreferrer">public-html-ig-zh@w3.org</a> 进行的讨论）。</p>
<p>总的来说，「空格派」的习惯就是在汉字和西文之间留一个半角空格。但因为在中西文关系上有一些让人不好决定的特例，他们使用空格的方式有一些变数。</p>
<p>根据一般都「加」空格到一般「不加」空格的顺序，大致可以排出来：</p>
<ul>
<li>内部有空格的西文短语（iPod touch）</li>
<li>独立的西文单词（iPhone）</li>
<li>全大写字母的西文缩写（HTML）</li>
<li>单个的西文字母（X）</li>
<li>阿拉伯数字（7）和 西文标点（/）</li>
</ul>
<p>西文和汉字和标点三者相遇的时候问题更复杂（汗……「三体」），大家的习惯也有差异。</p>
<hr>
<p>以上是现状，下面是个人观点：</p>
<p>中文与西文混排时，不一定要有空格字符，但一定要有间距。</p>
<p>使用专业排版软件时，交由软件处理间距问题（Adobe Creative Suite 把这个事归入「标点挤压」）；纯文本写作时，插入半角空格。具体在上面列出的那五种情况下合适加空格，何时不加，至今还没有什么共识。</p>
<p>关注文字设计的朋友其实可以编写自己的 Manual of Style，最终或许能在百家争鸣中诞生中文互联网的一份事实标准。</p>
<p>我的空格习惯基本上是受<a href="https://www.zhihu.com/people/455b06074c9e37df07146f86294f6373" target="_blank" rel="noreferrer">@刘昕</a></p>
<p>影响而建立的。因为这篇日志：</p>
<p>《中文 Web 阅读体验》：</p>
<p><a href="http://www.livid.cn/doc_view.php?doc_id=5332" target="_blank" rel="noreferrer">http://www.livid.cn/doc_view.php?doc_id=5332</a></p>
<p>（原站已关闭，这里是存档：</p>
<p><a href="https://web.archive.org/web/20110716090934/http://www.livid.cn/doc_view.php?doc_id=5332" target="_blank" rel="noreferrer">中文 Web 阅读体验</a></p>
<p>）</p>
<p>在看过这篇日志后，我意识到、并至今坚定维护着空格的必要性。刘昕在文中的这句话解释了基本的空格使用规则：</p>
<blockquote>
<p>中文正文及标题中出现的英文及数字应该使用半角方式输入，并且在左右各留一个半角空格。如果这些这些半角英文及数字的左边或者右边紧接着任何的中文全角括号或者其他标点符号的话，则不需要加入半角空格。</p>
</blockquote>
<h3 id="中英文混排参考规范" tabindex="-1">中英文混排参考规范 <a class="header-anchor" href="#中英文混排参考规范" aria-label="Permalink to &quot;中英文混排参考规范&quot;">&ZeroWidthSpace;</a></h3>
<ul>
<li>英文和数字使用半角字符</li>
<li>中文文字之间不加空格</li>
<li>中文文字与英文、阿拉伯数字及 @ # $ % ^ &amp; * . ( ) 等符号之间加空格</li>
<li>中文标点之间不加空格</li>
<li>中文标点与前后字符（无论全角或半角）之间不加空格</li>
<li>如果括号内有中文，则使用中文括号，如果括号中的内容全部都是英文，则使用半角英文括号</li>
<li>当半角符号 / 表示“或者”之意时，与前后的字符之间均不加空格</li>
</ul>
<h5 id="中英文之间需要增加空格" tabindex="-1">中英文之间需要增加空格 <a class="header-anchor" href="#中英文之间需要增加空格" aria-label="Permalink to &quot;中英文之间需要增加空格&quot;">&ZeroWidthSpace;</a></h5>
<p>正确：</p>
<blockquote>
<p>在 LeanCloud 上，数据存储是围绕 <code>AVObject</code> 进行的。</p>
</blockquote>
<p>错误：</p>
<blockquote>
<p>在LeanCloud上，数据存储是围绕<code>AVObject</code>进行的。</p>
<p>在 LeanCloud上，数据存储是围绕<code>AVObject</code> 进行的。</p>
</blockquote>
<p>完整的正确用法：</p>
<blockquote>
<p>在 LeanCloud 上，数据存储是围绕 <code>AVObject</code> 进行的。每个 <code>AVObject</code> 都包含了与 JSON 兼容的 key-value 对应的数据。数据是 schema-free 的，你不需要在每个 <code>AVObject</code> 上提前指定存在哪些键，只要直接设定对应的 key-value 即可。</p>
</blockquote>
<p>例外：「豆瓣FM」等产品名词，按照官方所定义的格式书写。</p>
<p>中文与数字之间需要增加空格</p>
<p>正确：</p>
<blockquote>
<p>今天出去买菜花了 5000 元。</p>
</blockquote>
<p>错误：</p>
<blockquote>
<p>今天出去买菜花了 5000元。</p>
<p>今天出去买菜花了5000元。</p>
</blockquote>
<h5 id="数字与单位之间需要增加空格" tabindex="-1">数字与单位之间需要增加空格 <a class="header-anchor" href="#数字与单位之间需要增加空格" aria-label="Permalink to &quot;数字与单位之间需要增加空格&quot;">&ZeroWidthSpace;</a></h5>
<p>正确：</p>
<blockquote>
<p>我家的光纤入屋宽带有 10 Gbps，SSD 一共有 20 TB</p>
</blockquote>
<p>错误：</p>
<blockquote>
<p>我家的光纤入屋宽带有 10Gbps，SSD 一共有 20TB</p>
</blockquote>
<p>例外：度数／百分比与数字之间不需要增加空格：</p>
<p>正确：</p>
<blockquote>
<p>角度为 90° 的角，就是直角。</p>
<p>新 MacBook Pro 有 15% 的 CPU 性能提升。</p>
</blockquote>
<p>错误：</p>
<blockquote>
<p>角度为 90 ° 的角，就是直角。</p>
<p>新 MacBook Pro 有 15 % 的 CPU 性能提升。</p>
</blockquote>
<h5 id="全角标点与其他字符之间不加空格" tabindex="-1">全角标点与其他字符之间不加空格 <a class="header-anchor" href="#全角标点与其他字符之间不加空格" aria-label="Permalink to &quot;全角标点与其他字符之间不加空格&quot;">&ZeroWidthSpace;</a></h5>
<p>正确：</p>
<blockquote>
<p>刚刚买了一部 iPhone，好开心！</p>
</blockquote>
<p>错误：</p>
<blockquote>
<p>刚刚买了一部 iPhone ，好开心！</p>
<p>刚刚买了一部 iPhone， 好开心！</p>
</blockquote>
<h5 id="用-text-spacing-来挽救" tabindex="-1">用 <code>text-spacing</code> 来挽救？ <a class="header-anchor" href="#用-text-spacing-来挽救" aria-label="Permalink to &quot;用 `text-spacing` 来挽救？&quot;">&ZeroWidthSpace;</a></h5>
<p>CSS Text Module Level 4 的 <a href="https://www.w3.org/TR/css-text-4/#text-spacing-property" target="_blank" rel="noreferrer"><code>text-spacing</code></a> 和 Microsoft 的 <a href="https://msdn.microsoft.com/library/ms531164(v=vs.85).aspx" target="_blank" rel="noreferrer"><code>-ms-text-autospace</code></a> 可以实现自动为中英文之间增加空白。不过目前并未普及，另外在其他应用场景，例如 macOS、iOS、Windows 等用户界面目前并不存在这个特性，所以请继续保持随手加空格的习惯。</p>
<h4 id="标点符号" tabindex="-1">标点符号 <a class="header-anchor" href="#标点符号" aria-label="Permalink to &quot;标点符号&quot;">&ZeroWidthSpace;</a></h4>
<h5 id="不重复使用标点符号" tabindex="-1">不重复使用标点符号 <a class="header-anchor" href="#不重复使用标点符号" aria-label="Permalink to &quot;不重复使用标点符号&quot;">&ZeroWidthSpace;</a></h5>
<p>虽然中国大陆的标点符号用法允许重复使用标点符号，但是这么做会破坏句子的美观性。</p>
<p>正确：</p>
<blockquote>
<p>德国队竟然战胜了巴西队！</p>
<p>她竟然对你说「喵」？！</p>
</blockquote>
<p>错误：</p>
<blockquote>
<p>德国队竟然战胜了巴西队！！</p>
<p>德国队竟然战胜了巴西队！！！！！！！！</p>
<p>她竟然对你说「喵」？？！！</p>
<p>她竟然对你说「喵」？！？！？？！！</p>
</blockquote>
<h4 id="全角和半角" tabindex="-1">全角和半角 <a class="header-anchor" href="#全角和半角" aria-label="Permalink to &quot;全角和半角&quot;">&ZeroWidthSpace;</a></h4>
<p>不明白什么是全角（全形）与半角（半形）符号？请查看维基百科条目『<a href="https://zh.wikipedia.org/wiki/%E5%85%A8%E5%BD%A2%E5%92%8C%E5%8D%8A%E5%BD%A2" target="_blank" rel="noreferrer">全角和半角</a>』。</p>
<h5 id="使用全角中文标点" tabindex="-1">使用全角中文标点 <a class="header-anchor" href="#使用全角中文标点" aria-label="Permalink to &quot;使用全角中文标点&quot;">&ZeroWidthSpace;</a></h5>
<p>正确：</p>
<blockquote>
<p>嗨！你知道嘛？今天前台的小妹跟我说「喵」了哎！</p>
<p>核磁共振成像（NMRI）是什么原理都不知道？JFGI！</p>
</blockquote>
<p>错误：</p>
<blockquote>
<p>嗨! 你知道嘛? 今天前台的小妹跟我说 &quot;喵&quot; 了哎！</p>
<p>嗨!你知道嘛?今天前台的小妹跟我说&quot;喵&quot;了哎！</p>
<p>核磁共振成像 (NMRI) 是什么原理都不知道? JFGI!</p>
<p>核磁共振成像(NMRI)是什么原理都不知道?JFGI!</p>
</blockquote>
<p>例外：中文句子内夹有英文书籍名、报刊名时，不应借用中文书名号，应以英文斜体表示。</p>
<h5 id="数字使用半角字符" tabindex="-1">数字使用半角字符 <a class="header-anchor" href="#数字使用半角字符" aria-label="Permalink to &quot;数字使用半角字符&quot;">&ZeroWidthSpace;</a></h5>
<p>正确：</p>
<blockquote>
<p>这个蛋糕只卖 1000 元。</p>
</blockquote>
<p>错误：</p>
<blockquote>
<p>这个蛋糕只卖 １０００ 元。</p>
</blockquote>
<p>例外：在设计稿、宣传海报中如出现极少量数字的情形时，为方便文字对齐，是可以使用全角数字的。</p>
<h4 id="遇到完整的英文整句、特殊名词-其内容使用半角标点" tabindex="-1">遇到完整的英文整句、特殊名词，其内容使用半角标点 <a class="header-anchor" href="#遇到完整的英文整句、特殊名词-其内容使用半角标点" aria-label="Permalink to &quot;遇到完整的英文整句、特殊名词，其内容使用半角标点&quot;">&ZeroWidthSpace;</a></h4>
<p>正确：</p>
<blockquote>
<p>乔布斯那句话是怎么说的？「Stay hungry, stay foolish.」</p>
<p>推荐你阅读 <em>Hackers &amp; Painters: Big Ideas from the Computer Age</em>，非常地有趣。</p>
</blockquote>
<p>错误：</p>
<blockquote>
<p>乔布斯那句话是怎么说的？「Stay hungry，stay foolish。」</p>
<p>推荐你阅读《Hackers＆Painters：Big Ideas from the Computer Age》，非常的有趣。</p>
</blockquote>
<h4 id="名词" tabindex="-1">名词 <a class="header-anchor" href="#名词" aria-label="Permalink to &quot;名词&quot;">&ZeroWidthSpace;</a></h4>
<h5 id="专有名词使用正确的大小写" tabindex="-1">专有名词使用正确的大小写 <a class="header-anchor" href="#专有名词使用正确的大小写" aria-label="Permalink to &quot;专有名词使用正确的大小写&quot;">&ZeroWidthSpace;</a></h5>
<p>大小写相关用法原属于英文书写范畴，不属于本 wiki 讨论内容，在这里只对部分易错用法进行简述。</p>
<p>正确：</p>
<blockquote>
<p>使用 GitHub 登录</p>
<p>我们的客户有 GitHub、Foursquare、Microsoft Corporation、Google、Facebook, Inc.。</p>
</blockquote>
<p>错误：</p>
<blockquote>
<p>使用 github 登录</p>
<p>使用 GITHUB 登录</p>
<p>使用 Github 登录</p>
<p>使用 gitHub 登录</p>
<p>使用 gｲんĤЦ8 登录</p>
<p>我们的客户有 github、foursquare、microsoft corporation、google、facebook, inc.。</p>
<p>我们的客户有 GITHUB、FOURSQUARE、MICROSOFT CORPORATION、GOOGLE、FACEBOOK, INC.。</p>
<p>我们的客户有 Github、FourSquare、MicroSoft Corporation、Google、FaceBook, Inc.。</p>
<p>我们的客户有 gitHub、fourSquare、microSoft Corporation、google、faceBook, Inc.。</p>
<p>我们的客户有 gｲんĤЦ8、ｷouЯƧquﾑгє、๓เςг๏ร๏Ŧt ς๏гק๏гคtเ๏ภn、900913、ƒ4ᄃëв๏๏к, IПᄃ.。</p>
</blockquote>
<p>注意：当网页中需要配合整体视觉风格而出现全部大写／小写的情形，HTML 中请使用标淮的大小写规范进行书写；并通过 <code>text-transform: uppercase;</code>／<code>text-transform: lowercase;</code> 对表现形式进行定义。</p>
<h5 id="不要使用不地道的缩写" tabindex="-1">不要使用不地道的缩写 <a class="header-anchor" href="#不要使用不地道的缩写" aria-label="Permalink to &quot;不要使用不地道的缩写&quot;">&ZeroWidthSpace;</a></h5>
<p>正确：</p>
<blockquote>
<p>我们需要一位熟悉 TypeScript、HTML5，至少理解一种框架（如 React、Next.js）的前端开发者。</p>
</blockquote>
<p>错误：</p>
<blockquote>
<p>我们需要一位熟悉 Ts、h5，至少理解一种框架（如 RJS、nextjs）的 FED。</p>
</blockquote>
]]></content>
        <author>
            <name>duyl328</name>
            <uri>https://seyl.me/about</uri>
        </author>
        <category label="编程"/>
        <category label="学习"/>
        <category label="设计"/>
        <category label="Blog"/>
        <category label="原创"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[TypeScript 应该被放弃吗]]></title>
        <id>https://seyl.me/posts/2024/08/should-typescript-be-abandoned</id>
        <link href="https://seyl.me/posts/2024/08/should-typescript-be-abandoned"/>
        <updated>2024-08-04T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[<h1 id="frontmatter-title" tabindex="-1">{{ $frontmatter.title }} <a class="header-anchor" href="#frontmatter-title" aria-label="Permalink to &quot;{{ $frontmatter.title }}&quot;">&ZeroWidthSpace;</a></h1>
<blockquote>
<p>✒️ 文章摘要</p>
</blockquote>
<!-- DESC SEP -->
<p>文章讨论了关于是否放弃 TypeScript 的问题，尤其是在一些大牛和社区项目的选择上。重点聚焦于两篇文章的观点：</p>
<p>Turbo 8 放弃 TypeScript：作者认为 TypeScript 的类型检查反而增加了开发中的负担，并且声明类型复杂化代码，减少了开发效率。这个观点在 Reddit 和知乎引发了激烈讨论，部分评论指出 Turbo 8 并不具备广泛影响力，且作者习惯发表反向意见。</p>
<p>TypeScript 的额外成本：第二篇文章提到，在某些场景下，TypeScript 的类型体操带来不必要的复杂度，尤其是对于小型项目，编写精确的类型定义可能比核心逻辑代码更为冗长。然而，TypeScript 相比于 JavaScript 在维护性和可扩展性上具有优势，尤其是对于框架和类库的开发者而言，尽管带来一些额外的维护成本。</p>
<p>总体来看，放弃 TypeScript 的选择多见于小型或开源项目的维护者，而对于大多数开发者来说，TypeScript 提供的类型系统和可维护性仍然是更受欢迎的选择。</p>
<!-- DESC SEP -->
<h3 id="typescript-应该放弃吗" tabindex="-1">TypeScript 应该放弃吗 <a class="header-anchor" href="#typescript-应该放弃吗" aria-label="Permalink to &quot;TypeScript 应该放弃吗&quot;">&ZeroWidthSpace;</a></h3>
]]></summary>
        <content type="html"><![CDATA[<h1 id="frontmatter-title" tabindex="-1">{{ $frontmatter.title }} <a class="header-anchor" href="#frontmatter-title" aria-label="Permalink to &quot;{{ $frontmatter.title }}&quot;">&ZeroWidthSpace;</a></h1>
<blockquote>
<p>✒️ 文章摘要</p>
</blockquote>
<!-- DESC SEP -->
<p>文章讨论了关于是否放弃 TypeScript 的问题，尤其是在一些大牛和社区项目的选择上。重点聚焦于两篇文章的观点：</p>
<p>Turbo 8 放弃 TypeScript：作者认为 TypeScript 的类型检查反而增加了开发中的负担，并且声明类型复杂化代码，减少了开发效率。这个观点在 Reddit 和知乎引发了激烈讨论，部分评论指出 Turbo 8 并不具备广泛影响力，且作者习惯发表反向意见。</p>
<p>TypeScript 的额外成本：第二篇文章提到，在某些场景下，TypeScript 的类型体操带来不必要的复杂度，尤其是对于小型项目，编写精确的类型定义可能比核心逻辑代码更为冗长。然而，TypeScript 相比于 JavaScript 在维护性和可扩展性上具有优势，尤其是对于框架和类库的开发者而言，尽管带来一些额外的维护成本。</p>
<p>总体来看，放弃 TypeScript 的选择多见于小型或开源项目的维护者，而对于大多数开发者来说，TypeScript 提供的类型系统和可维护性仍然是更受欢迎的选择。</p>
<!-- DESC SEP -->
<h3 id="typescript-应该放弃吗" tabindex="-1">TypeScript 应该放弃吗 <a class="header-anchor" href="#typescript-应该放弃吗" aria-label="Permalink to &quot;TypeScript 应该放弃吗&quot;">&ZeroWidthSpace;</a></h3>
<hr>
<p>抛出这个问题主要基于22年和23年发生的一些事件：</p>
<p><img src="./../../../public/posts/2024/08/10003/up-58c4155f83bbd826f4bb0ec1ab8d1e32ccd-1719469395020-15-1719469397190-17.webp" alt="image-20240627143223214"></p>
<p><img src="./../../../public/posts/2024/08/10003/eed5a2dd0f71b8b4790a1b20c708416c-1719469475131-21.webp" alt="image-20240627143223214"></p>
<p>并且Svelte 不是第一个放弃 TypeScript 的前端框架。早在 2020 年，Deno 就迁移了一部分內部 TypeScript 代码到 JavaScript，以减少构建时间。</p>
<p>并且这些大牛放弃 TypeScript 似乎还加快了工作进度，但这个选择是否应该被普通开发者所选择？</p>
<p>搜了很多文章，但是大部分都在将一些很正确的废话，目前来看只有下面两篇有参考价值。</p>
<h5 id="第一篇-turbo-8-正在放弃-typescript-hey-com" tabindex="-1">第一篇：<a href="https://world.hey.com/dhh/turbo-8-is-dropping-typescript-70165c01" target="_blank" rel="noreferrer">Turbo 8 正在放弃 TypeScript (hey.com)</a> <a class="header-anchor" href="#第一篇-turbo-8-正在放弃-typescript-hey-com" aria-label="Permalink to &quot;第一篇：[Turbo 8 正在放弃 TypeScript (hey.com)](https://world.hey.com/dhh/turbo-8-is-dropping-typescript-70165c01)&quot;">&ZeroWidthSpace;</a></h5>
<blockquote>
<p>这是原文，正是这篇文章，引来了众多讨论</p>
</blockquote>
<p>文章的主要观点如下：</p>
<blockquote>
<p>TypeScript 只是妨碍了我。不仅因为它需要显式的编译步骤，还因为它用类型体操污染了代码</p>
</blockquote>
<p>—— 多余类型判断只会降低效率</p>
<p>文章没有多长，几乎没有太多参考价值，但毕竟是原文，还是搬过来比较好。</p>
<p>并且对于这篇文章，Reddit的评论区也是活力十足</p>
<p><img src="./../../../public/posts/2024/08/10003/image-20240627144850640.webp" alt="image-20240627144850640"></p>
<p>并且在知乎对于这个问题的评价更加激进：</p>
<p><img src="./../../../public/posts/2024/08/10003/image-20240627143223214.webp" alt="image-20240627143223214"></p>
<p>以下是文字版本：</p>
<blockquote>
<p>前端届盛产大牛，整点别人看不懂的代码，硬说函数式然后猛劲宣传就能当大牛。</p>
<p>搞计算机其实有一点不好，就是你以为有些应该不在世的大师他都活着呢。</p>
<p>算法分析之父高德纳还在呢。</p>
<p>WindowsNT 内核之父 David Cuttler 也还在呢。</p>
<p>Linux 内核之父 Linus 还到处喷人呢。</p>
<p>GUI 和面向对象之父 Allen Kay 也还在呢。</p>
<p>Pascal 总架构师，Delphi 和 C# 之父，编程语言届的传奇 <strong>Anders Hejlsberg</strong> 也还在努力工作呢。</p>
<p>我不明白某些在社区当网红的不入流货色是怎么敢被封为大牛还大放厥词的。</p>
<p>对了，TypeScript 就是 Anders 搞的。</p>
</blockquote>
<p>无论是知乎还是Reddit的讨论都是相对激进，并拳拳到肉那种，只顾着输出情绪了。不过总结起来大致为以下两个观点：</p>
<ol>
<li>Turbo 8 并不是什么知名项目，没人在意他是否放弃 TypeScript</li>
<li>Turbo 8 的作者（也是文章作者），经常写类似的文章来唱反调</li>
<li>文章除了说明了类型让他更加麻烦了，并且有提出其他有力依据，所以被Reddit评论区狂怼</li>
<li>这个大牛是虚假宣传的，为了博眼球臆造出来的，而那些真正的大牛创造了TypeScript</li>
</ol>
<p>当然<strong>无意义的情绪输出不能解决任何问题</strong>，所以也有下面这个文章通过多个方面来讨论为什么那些社区项目会放弃TypeScript</p>
<h5 id="第二篇-根本不需要-typescript-js-jsdoc-够了-大佬说我想多了" tabindex="-1">第二篇：<a href="https://my.oschina.net/u/6852546/blog/10114672" target="_blank" rel="noreferrer">“根本不需要 TypeScript，JS + JSDoc 够了”，大佬说我想多了</a> <a class="header-anchor" href="#第二篇-根本不需要-typescript-js-jsdoc-够了-大佬说我想多了" aria-label="Permalink to &quot;第二篇：[“根本不需要 TypeScript，JS + JSDoc 够了”，大佬说我想多了](https://my.oschina.net/u/6852546/blog/10114672)&quot;">&ZeroWidthSpace;</a></h5>
<p>文章的主要观点如下：</p>
<blockquote>
<p>某些场景下，写 TypeScript 会带来一些额外成本。一些开源库的源码，核心逻辑可能就几十行，但为了实现准确的类型提示，写出来的类型体操反而远远多于核心源码，孰是孰非对于不同的开发者有不同的准绳，需要找到其中的平衡点。</p>
</blockquote>
<p>—— 对于特定场景，TypeScript 确实更麻烦了</p>
<blockquote>
<p>使用了 TypeScript 的项目改回使用 JavaScript 是很少见的，更多的项目是从 JavaScript 升级到 TypeScript。TypeScript 完善了 JavaScript 的类型系统，使得代码的可维护性更高了.</p>
</blockquote>
<p>—— 相对来说，TypeScript 相对于 JavaScript 是更加受欢迎的，并且被更多项目所接受</p>
<blockquote>
<p><strong>框架和类库的开发者，往往需要考虑到很多 edge case</strong>，在这种情况下，编写完善的类型是一件很费心力的事，代码量会多了不少，从而会导致维护成本的增加。</p>
</blockquote>
<p>—— 放弃 TypeScript 的更多是那些公共仓库的维护者，而他们需要考虑所有有可能出现的情况，会有非常多的边缘判断来减少异常，这也造成了如果使用 TypeScript反而会更麻烦</p>
<blockquote>
<p>TypeScript 的成功无需质疑，已经有无数的项目证明了它的成功。开发者并没有 “嫌弃” TypeScript，只是认为并不是所有项目都适合使用 TypeScript。</p>
</blockquote>
<blockquote>
<p><strong>有人认为，</strong> <strong>TypeScript</strong> <strong>的出现是因为一般人驾驭不了</strong> <strong>JavaScript</strong> <strong>，有人则觉得 “水平越差的人越喜欢自由”，你怎么看？这两个语言的选择跟程序员的水平有关吗？</strong></p>
<ul>
<li>平时可没少见有同学吐槽，<strong>好好的 TypeScript 项目，被人提交了一堆 Any</strong>。也见过很多吐槽接手了一个 TypeScript 仓库，要硬着头皮看一大堆类型定义，搞清楚这些奇奇怪怪的类型是如何工作的。我觉得语言的选择主要看团队的工程化和规范化程度，过犹不及。如果一个 TypeScript 类库写了一大堆类型，但却连一个单测都没有，那我觉得它是不合格的。</li>
<li>JavaScript 和 TypeScript 不能用来衡量程序员的水平。对于简单的项目或者个人项目而言，JavaScript 可能更加轻量和灵活，但对于需要大团队协作，复杂的项目而言，TypeScript 的类型系统就可以带来更好的代码维护性和可靠性了。</li>
</ul>
</blockquote>
<p>该文章相对来说理性了很多，通过一些采访来尽量还原更加客观的事实，并且对于 TypeScript 的选择相对来说没有那么难决断，那些仓库的作者因为繁琐的 <strong>edge case</strong> 放弃了 TS，但这并不代表他没有一点自己的用武之地，在常规的项目中，尤其是大型的多人合作项目中，TS也会是优先的选择。</p>
<p>并且无论是TS还是JS都能做出很好的产品，二者没有高低贵贱之分，如果一个TS项目写满了 <code>Any</code> 那不如直接切换为 JS 反而在某种程度还更能节约代码量了</p>
]]></content>
        <author>
            <name>duyl328</name>
            <uri>https://seyl.me/about</uri>
        </author>
        <category label="编程"/>
        <category label="思考"/>
        <category label="TypeScript"/>
        <category label="Blog"/>
        <category label="原创"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Vue还是React?]]></title>
        <id>https://seyl.me/posts/2024/08/vue-or-react</id>
        <link href="https://seyl.me/posts/2024/08/vue-or-react"/>
        <updated>2024-08-04T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[<h1 id="frontmatter-title" tabindex="-1">{{ $frontmatter.title }} <a class="header-anchor" href="#frontmatter-title" aria-label="Permalink to &quot;{{ $frontmatter.title }}&quot;">&ZeroWidthSpace;</a></h1>
<blockquote>
<p>✒️ 文章摘要</p>
</blockquote>
<!-- DESC SEP -->
<p>这篇文章探讨了 Vue、React 和 Next.js 之间的选择，并深入分析了 React 的一些优缺点。作者指出，虽然 Vue 在国内市场占据主导地位，React 在国外仍然保持强大的活力。但与此同时，React 面临不少批评，特别是其逐渐显现的技术债务和性能问题。文章引用了一些反对 React 的观点，强调 React 已显老化，且与其他框架相比，存在着难以兼容和过度依赖自定义模块的问题。同时，文章还提到其他框架如 Svelte 的优越性，认为它能提供类似 React 的功能，但更加简洁和高效。</p>
<p>如果你对前端框架的选择和 React 未来的方向感兴趣，这篇文章将为你提供一些新的视角，帮助你做出更明智的决策。</p>
<!-- DESC SEP -->
<h3 id="vue和react、nextjs如何选择" tabindex="-1">Vue和React、Nextjs如何选择 <a class="header-anchor" href="#vue和react、nextjs如何选择" aria-label="Permalink to &quot;Vue和React、Nextjs如何选择&quot;">&ZeroWidthSpace;</a></h3>
]]></summary>
        <content type="html"><![CDATA[<h1 id="frontmatter-title" tabindex="-1">{{ $frontmatter.title }} <a class="header-anchor" href="#frontmatter-title" aria-label="Permalink to &quot;{{ $frontmatter.title }}&quot;">&ZeroWidthSpace;</a></h1>
<blockquote>
<p>✒️ 文章摘要</p>
</blockquote>
<!-- DESC SEP -->
<p>这篇文章探讨了 Vue、React 和 Next.js 之间的选择，并深入分析了 React 的一些优缺点。作者指出，虽然 Vue 在国内市场占据主导地位，React 在国外仍然保持强大的活力。但与此同时，React 面临不少批评，特别是其逐渐显现的技术债务和性能问题。文章引用了一些反对 React 的观点，强调 React 已显老化，且与其他框架相比，存在着难以兼容和过度依赖自定义模块的问题。同时，文章还提到其他框架如 Svelte 的优越性，认为它能提供类似 React 的功能，但更加简洁和高效。</p>
<p>如果你对前端框架的选择和 React 未来的方向感兴趣，这篇文章将为你提供一些新的视角，帮助你做出更明智的决策。</p>
<!-- DESC SEP -->
<h3 id="vue和react、nextjs如何选择" tabindex="-1">Vue和React、Nextjs如何选择 <a class="header-anchor" href="#vue和react、nextjs如何选择" aria-label="Permalink to &quot;Vue和React、Nextjs如何选择&quot;">&ZeroWidthSpace;</a></h3>
<hr>
<p><code>Vue</code> 在大前端时代，在国内市场可谓是大杀特杀，几乎以压倒性的优势占领着国内市场，并且随着 2020 年<code>Vue3</code>的发布，以及<code>Vite</code>的推出，其生态更加完善，基本是国内市场做前端的首选语言。</p>
<p>但和国内相悖的是，在<code>JetBrains</code>与<code>StackOverflow</code>在2023年的数据报告中，在前端方面数据，<code>Node</code>和<code>React</code>以压倒性优势领先其他语言</p>
<p><img src="./../../../public/posts/2024/08/10003/image-20240626141050935-1719382253511-9.webp" alt="2023 JetBrains开发者调查报告"></p>
<p><img src="./../../../public/posts/2024/08/10003/image-20240626141144499.webp" alt="StackOverflow 2023调查报告"></p>
<p>2023JavaScript趋势报告：</p>
<p><img src="./../../../public/posts/2024/08/10003/image-20240626143412891.webp" alt="image-20240626143412891"></p>
<p>和国内不同的是，<code>React</code>在国外保持着惊人的活力</p>
<p>但也有很多反对<code>React</code>的声音，以及关于<code>React</code>辩论的文章，如：</p>
<p><a href="https://joshcollinsworth.com/blog/antiquated-react" target="_blank" rel="noreferrer">你因为 React 而忘记（或从来不知道）的事情 - Josh Collinsworth 博客</a></p>
<p><a href="https://joshcollinsworth.com/blog/self-fulfilling-prophecy-of-react" target="_blank" rel="noreferrer">React 的自我实现预言 - Josh Collinsworth 博客</a></p>
<p><a href="https://changelog.com/jsparty/244" target="_blank" rel="noreferrer">辛辣的 React 辩论秀 🌶️ （JS Party #244） (changelog.com)</a></p>
<p>如果各位有兴趣可以读原文，我这里为每篇文章简单的总结。</p>
<h4 id="第一篇-你因为-react-而忘记-或从来不知道-的事情-josh-collinsworth-博客" tabindex="-1">第一篇：<a href="https://joshcollinsworth.com/blog/antiquated-react" target="_blank" rel="noreferrer">你因为 React 而忘记（或从来不知道）的事情 - Josh Collinsworth 博客</a> <a class="header-anchor" href="#第一篇-你因为-react-而忘记-或从来不知道-的事情-josh-collinsworth-博客" aria-label="Permalink to &quot;第一篇：[你因为 React 而忘记（或从来不知道）的事情 - Josh Collinsworth 博客](https://joshcollinsworth.com/blog/antiquated-react)&quot;">&ZeroWidthSpace;</a></h4>
<blockquote>
<p>该文章也是被 <code>2023 JavaScript 行业调研报告</code> 所提到的文章，并且一些观点的确值得思考，但有的就一般了，为了准确传达原作者的意思，我这里会尽量中立的概括，也会引用部分原文进行对应部分内容的解释。</p>
</blockquote>
<ol>
<li>
<h5 id="并不是所有好的事物都会流行。" tabindex="-1">并不是所有好的事物都会流行。 <a class="header-anchor" href="#并不是所有好的事物都会流行。" aria-label="Permalink to &quot;并不是所有好的事物都会流行。&quot;">&ZeroWidthSpace;</a></h5>
<blockquote>
<p>回首往事，我意识到：我天真地相信，任何好东西都不可避免地会流行起来——因此，任何值得了解的东西最终都会自己出现。</p>
</blockquote>
<blockquote>
<p>作者开篇就提到了好的事物并不会自然的流行，自然而然的出现到你面前，也就说明了另一个意思：<strong>出现在你面前的，流行起来的可能并不是最好的选择</strong></p>
</blockquote>
</li>
<li>
<h5 id="react已经老化了" tabindex="-1"><code>React</code>已经老化了 <a class="header-anchor" href="#react已经老化了" aria-label="Permalink to &quot;`React`已经老化了&quot;">&ZeroWidthSpace;</a></h5>
<blockquote>
<p>React 从早期的框架游戏中受益匪浅;它设定了标准。但这在敏捷性和适应性方面存在严重缺陷。自 2013 年左右成立以来，React 做出的每一个决定都是另一层技术债务——它的新同时代人不受其约束。</p>
<p><a href="https://toot.cafe/@slightlyoff/110512849934452558" target="_blank" rel="noreferrer">再次引用亚历克斯的话</a>：</p>
<blockquote>
<p>React 是 '13 技术，旨在 '08 约束。在 2023 年，它没有任何创新之处;事实上，这是现代获得函数式响应式前端编程的最慢方法......</p>
</blockquote>
</blockquote>
</li>
<li>
<h5 id="react是定制的-这使其在不同框架之间很难移植-几乎不和其他平台兼容" tabindex="-1"><code>React</code>是定制的，这使其在不同框架之间很难移植，几乎不和其他平台兼容 <a class="header-anchor" href="#react是定制的-这使其在不同框架之间很难移植-几乎不和其他平台兼容" aria-label="Permalink to &quot;`React`是定制的，这使其在不同框架之间很难移植，几乎不和其他平台兼容&quot;">&ZeroWidthSpace;</a></h5>
<blockquote>
<p>使用 React，每当我们需要一个模块、一个小部件或一个库来做一些特定的事情（旋转木马、地图、手风琴或其他任何东西）时，<em>它必须是 React 的东西</em>;一个普通的 Web 东西或一个普通的 JavaScript 东西是行不通的。React 的所有规则以及对组件生命周期状态和怪癖的处理意味着任何<em>没有</em>明确为 React 编写的可用包或库都可能无法工作。</p>
<p><strong>React 训练我们，需要<em>专门为某个框架</em>构建东西。但这已经不是真的了，可以说永远不应该是这样。</strong></p>
</blockquote>
<p>作者在这里举了个例子，通过框架之间的对比衬托<code>React</code>的独断专行</p>
<blockquote>
<p><a href="https://preactjs.com/guide/v10/signals/" target="_blank" rel="noreferrer">Preact Signals</a> 就是一个非凡的例子：虽然它是为使用 Preact 而构建的，但它可以在<em>任何</em>框架中导入和使用，甚至可以在普通的 JavaScript 中使用。Web 组件也与几乎任何现代非 React 框架兼容。</p>
</blockquote>
</li>
<li>
<h5 id="react-钩子实际上有点过时了" tabindex="-1">React 钩子实际上有点过时了 <a class="header-anchor" href="#react-钩子实际上有点过时了" aria-label="Permalink to &quot;React 钩子实际上有点过时了&quot;">&ZeroWidthSpace;</a></h5>
<blockquote>
<p>钩子是一种极好的模式，React 的普及值得称赞。但几乎所有其他框架都做得更好，规则更少，样板更少。</p>
</blockquote>
</li>
<li>
<h5 id="react相对更加不智能" tabindex="-1"><code>React</code>相对更加不智能 <a class="header-anchor" href="#react相对更加不智能" aria-label="Permalink to &quot;`React`相对更加不智能&quot;">&ZeroWidthSpace;</a></h5>
<blockquote>
<p>如今，框架足够聪明，可以处理这种事情，而不需要你握住他们的手并解释他们应该做什么。</p>
</blockquote>
<p>&quot;但React还是需要你做这些精细化管理&quot;</p>
</li>
<li>
<h5 id="服务器端渲染不再特别" tabindex="-1">服务器端渲染不再特别 <a class="header-anchor" href="#服务器端渲染不再特别" aria-label="Permalink to &quot;服务器端渲染不再特别&quot;">&ZeroWidthSpace;</a></h5>
<blockquote>
<p>几年前，曾经有一段时间，当涉及到服务器渲染的内容（主要是通过Next JS）时，React几乎是唯一的选择。人们理所当然地对 React 可以在服务器上以 HTML 形式呈现的想法感到兴奋，而不是在客户端上作为单页应用程序 （SPA） 呈现。速度和SEO的收益是不容忽视的，最初，其他框架需要一点时间才能赶上。不过选择更多框架都做到了。</p>
</blockquote>
</li>
<li>
<h5 id="react-是由-facebook-创建的-目的是解决-facebook-独特的一系列问题" tabindex="-1">React 是由 Facebook 创建的，目的是解决 Facebook 独特的一系列问题 <a class="header-anchor" href="#react-是由-facebook-创建的-目的是解决-facebook-独特的一系列问题" aria-label="Permalink to &quot;React 是由 Facebook 创建的，目的是解决 Facebook 独特的一系列问题&quot;">&ZeroWidthSpace;</a></h5>
<blockquote>
<p>在 React 中使用表单是出了名的麻烦，因为每个用户击键都是一个两步过程：从输入中获取值;然后设置状态以匹配它（这反过来又不必要地重新渲染输入，以包含它已经完成的确切值，但与 React 状态同步）。当然，它通常太快而无法注意到，但这是很多额外的工作。</p>
<p>这就是为什么 React 的表单库激增的原因</p>
</blockquote>
</li>
<li>
<h5 id="react-在性能上远远落后" tabindex="-1">React 在性能上远远落后 <a class="header-anchor" href="#react-在性能上远远落后" aria-label="Permalink to &quot;React 在性能上远远落后&quot;">&ZeroWidthSpace;</a></h5>
<blockquote>
<p>在许多情况下，React 在性能方面（这里我指的是捆绑包大小和执行速度）落后 2 倍或更多。（捆绑包本身可以是 10 倍或更多。最新一轮<a href="https://github.com/krausest/js-framework-benchmark" target="_blank" rel="noreferrer">的 JS Web 框架基准测试</a>显示，React 的性能平均比 Solid 慢近 50%，比 Vue 慢 25%，比 Svelte 慢 40%，比 Preact 慢 35%。（其他框架在此特定测试中不可用。</p>
</blockquote>
</li>
<li>
<h5 id="svelte-是没有废话的-react" tabindex="-1">Svelte 是没有废话的 React <a class="header-anchor" href="#svelte-是没有废话的-react" aria-label="Permalink to &quot;Svelte 是没有废话的 React&quot;">&ZeroWidthSpace;</a></h5>
<blockquote>
<p>Svelte 使用起来非常简单，相对容易学习（特别是如果你已经来自 React 世界，甚至语法通常也很相似），在几乎所有情况下都表现得更好，并且能够做任何 React 的事情，甚至更多</p>
</blockquote>
</li>
</ol>
<p>​	这也是作者留下的解决方案，并且根据作者本人所说，他本人的所有博客和网站都是有此完成.</p>
<h4 id="第二篇-react-的自我实现预言-josh-collinsworth-博客" tabindex="-1">第二篇：<a href="https://joshcollinsworth.com/blog/self-fulfilling-prophecy-of-react" target="_blank" rel="noreferrer">React 的自我实现预言 - Josh Collinsworth 博客</a> <a class="header-anchor" href="#第二篇-react-的自我实现预言-josh-collinsworth-博客" aria-label="Permalink to &quot;第二篇：[React 的自我实现预言 - Josh Collinsworth 博客](https://joshcollinsworth.com/blog/self-fulfilling-prophecy-of-react)&quot;">&ZeroWidthSpace;</a></h4>
<blockquote>
<p>该篇文章是同一个作者在不同时期写的，本文完成时间更早，同样是对<code>React</code>的批评</p>
</blockquote>
<ol>
<li>
<h5 id="react-除了受欢迎之外-什么都不擅长。" tabindex="-1">React 除了受欢迎之外，什么都不擅长。 <a class="header-anchor" href="#react-除了受欢迎之外-什么都不擅长。" aria-label="Permalink to &quot;React 除了受欢迎之外，什么都不擅长。&quot;">&ZeroWidthSpace;</a></h5>
<blockquote>
<p>让我在 React 和根本没有前端框架之间做出选择，并且给定任何足够大小或复杂度的项目，我很乐意接受 React，非常感谢。</p>
<p>React 为其他框架正在做和已经做的很多事情奠定了基础。<a href="https://vuejs.org/guide/introduction.html" target="_blank" rel="noreferrer">Vue 3</a> 及其组合 API 显然受到了 React hooks 的启发。<a href="https://svelte.dev/" target="_blank" rel="noreferrer">Svelte</a> 的许多约定都来自 React。<a href="https://nuxtjs.org/" target="_blank" rel="noreferrer">Nuxt</a> 是我使用过并喜欢的 Vue 框架，它的许多想法（以及 75% 的名称）都来自 <a href="https://nextjs.org/" target="_blank" rel="noreferrer">Next</a>，一个 React 元框架。就此而言，整个基于组件的前端设计和开发模型的当前状态（哈）很大程度上归功于 React——尽管应该指出的是，其他人也帮助铺平了道路。</p>
<p><strong>React 做了它擅长的事情，但它并没有比其他<em>框架做得更好。</em></strong></p>
</blockquote>
</li>
<li>
<h5 id="更多的社区和支持并不代表他是一个更好的选择" tabindex="-1">更多的社区和支持并不代表他是一个更好的选择 <a class="header-anchor" href="#更多的社区和支持并不代表他是一个更好的选择" aria-label="Permalink to &quot;更多的社区和支持并不代表他是一个更好的选择&quot;">&ZeroWidthSpace;</a></h5>
<blockquote>
<p>一个大的社区也可能是一个缺点，尤其是在所谓的“无主见”框架的情况下，比如 React。<strong>这可能意味着有太多的套餐可供选择，以及太多不同的、相互竞争的意见，你必须在两者之间做出决定并采取立场。</strong></p>
</blockquote>
</li>
<li>
<h5 id="多年来-react-的满意度和兴趣一直在稳步下降-而其使用率却持平" tabindex="-1">多年来，React 的满意度和兴趣一直在稳步下降，而其使用率却持平 <a class="header-anchor" href="#多年来-react-的满意度和兴趣一直在稳步下降-而其使用率却持平" aria-label="Permalink to &quot;多年来，React 的满意度和兴趣一直在稳步下降，而其使用率却持平&quot;">&ZeroWidthSpace;</a></h5>
<blockquote>
<p>React 很容易成为最常用的前端框架，也是知名度最高的前端框架，但在今年的 <a href="https://2021.stateofjs.com/en-US/libraries/front-end-frameworks/" target="_blank" rel="noreferrer">JS 现状调查结果</a>中，React 在满意度方面落后于 Solid 和 Svelte。React 在兴趣方面也排在 Svelte、Solid 和 Vue 之后（对于 React 来说，兴趣<em>低于 50%）</em>。</p>
<p>React 在 <a href="https://insights.stackoverflow.com/survey/2021#technology-most-popular-technologies" target="_blank" rel="noreferrer">StackOverflow 调查</a>中远远落后于 Svelte，也仅略微领先于 Vue。</p>
</blockquote>
</li>
<li>
<h5 id="为什么-react-会保持领先地位呢" tabindex="-1">为什么 React 会保持领先地位呢？ <a class="header-anchor" href="#为什么-react-会保持领先地位呢" aria-label="Permalink to &quot;为什么 React 会保持领先地位呢？&quot;">&ZeroWidthSpace;</a></h5>
<blockquote>
<p>“从来没有人因为选择 React 而被解雇”</p>
<p>这是安全的选择。它可能不是每个人的最爱，但不一定是。它可能也不会是任何人最不喜欢的。它会完成工作。</p>
</blockquote>
<p>像<code>Vue</code>一样，因为市场需要所以企业招聘，因为企业招聘，所以更多人学习，同样的，因为会的人多，所以企业招聘。他们完成了各自的闭环，但<strong>这个选择可能不是最明智的，但绝对是最安全的。</strong></p>
</li>
</ol>
<h4 id="第三篇-辛辣的-react-辩论秀-🌶️-js-party-244-changelog-com" tabindex="-1">第三篇：<a href="https://changelog.com/jsparty/244" target="_blank" rel="noreferrer">辛辣的 React 辩论秀 🌶️ （JS Party #244） (changelog.com)</a> <a class="header-anchor" href="#第三篇-辛辣的-react-辩论秀-🌶️-js-party-244-changelog-com" aria-label="Permalink to &quot;第三篇：[辛辣的 React 辩论秀 🌶️ （JS Party #244） (changelog.com)](https://changelog.com/jsparty/244)&quot;">&ZeroWidthSpace;</a></h4>
<blockquote>
<p>本篇文章主要是关于是否应该放弃<code>React</code>而投身其他框架，以及<code>React</code>自身存在问题的讨论</p>
<p>本篇文章是对一个讨论节目的翻译版本，会有很多观点，本文只总结，不站队</p>
</blockquote>
<h5 id="观点一-react赢被放弃" tabindex="-1">观点一：React赢被放弃 <a class="header-anchor" href="#观点一-react赢被放弃" aria-label="Permalink to &quot;观点一：React赢被放弃&quot;">&ZeroWidthSpace;</a></h5>
<blockquote>
<ul>
<li>
<p>React 或多或少是任何给定项目的默认选择。它已经达到了临界质量，感觉就像是一切的安全默认值.</p>
</li>
<li>
<p>从性能到捆绑包大小，到入职，再到复杂性、开发体验......一般来说，所有这些事情都是 React 本身并不能真正获胜的领域，在这些领域有更好的选择</p>
</li>
<li>
<p>当你缩小并查看大局时，你会意识到 React 在几乎每个给定的类别中都非常平庸，它真正擅长的唯一类别就是成为流行的东西。</p>
</li>
</ul>
</blockquote>
<h5 id="观点二-react有自己的难处-他不完美但已经做的很好了-并且也被很多人所接受" tabindex="-1">观点二：React有自己的难处，他不完美但已经做的很好了，并且也被很多人所接受 <a class="header-anchor" href="#观点二-react有自己的难处-他不完美但已经做的很好了-并且也被很多人所接受" aria-label="Permalink to &quot;观点二：React有自己的难处，他不完美但已经做的很好了，并且也被很多人所接受&quot;">&ZeroWidthSpace;</a></h5>
<blockquote>
<ul>
<li>当你流行时，你必须处理所有不同的情况。所以你不能只关注一件事而忽略其他。</li>
<li>如果我只关心绝对性能，我会发布静态 HTML。</li>
<li>Stack Overflow 调查，我注意到 React 的满意度为 84%，高于 Vue，几乎是 Angular 的两倍，紧随 Svelte 之后，使用率更高。如果React被很多人使用，如果他不被大多数人满意，那他的满意度将会低很多，但事实上这并没有</li>
</ul>
</blockquote>
<h5 id="观点三-react更像一个仁慈的君主" tabindex="-1">观点三：React更像一个仁慈的君主 <a class="header-anchor" href="#观点三-react更像一个仁慈的君主" aria-label="Permalink to &quot;观点三：React更像一个仁慈的君主&quot;">&ZeroWidthSpace;</a></h5>
<blockquote>
<ul>
<li>拥有一个几乎可以在任何地方使用的框架不是很好吗？我想要一个带有线条的 3D 旋转地球仪的库。你知道吗？你只需谷歌一下，它就在那里。你把它拉进来。很简单。生活很美好。（作为 2015 年框架战争的老兵，我只想说我们不想回到那个时代。每周都要面对一个新的框架，这让人筋疲力尽。）</li>
<li>如果我们要有一个统治框架，难道我们不希望它没有主见吗？所以 React 真的很好，因为它基本上只是一个带有最小状态管理解决方案的渲染库。有许多其他东西建立在 React 之上，这使得它与其他框架相当。所以即使你考虑元框架，也有很多流行的框架。</li>
<li>如果你了解 JavaScript，你几乎了解 React 的所有内容。他不会像Angular那样有很多新的“魔法”（这里指的是Angular引入的新的改变增加了学习成本，如管道，过滤器等）</li>
</ul>
</blockquote>
<p><img src="./../../../public/posts/2024/08/10003/image-20240627133055166-1719466257222-11.webp" alt="image-20240627133055166"></p>
<h5 id="观点四-从公司架构思考问题" tabindex="-1">观点四：从公司架构思考问题 <a class="header-anchor" href="#观点四-从公司架构思考问题" aria-label="Permalink to &quot;观点四：从公司架构思考问题&quot;">&ZeroWidthSpace;</a></h5>
<blockquote>
<p>React 的优势和我们遇到的摩擦都与它仍然由 Facebook 构建的事实有关，而 Facebook 的重点和优化选择都是为了解决 Facebook 所面临的问题。这些问题与许多公司在构建 JavaScript 应用程序时遇到的问题相当吻合，但一方面它们肯定是错的。</p>
<p>实际上，我认为你会在 Angular 中遇到一些相同的问题。Angular 仍然主要由 Google 想要什么和 Google 需要什么驱动。所以我认为，如果 Angular 达到这个水平——那么，早期的 Angular 确实很受欢迎，然后经历了很多这样的事情。</p>
<p>现在，如果你看看满意度，你会发现人们对 Angular 非常不满意，尽管有很多人在使用它。React 也可能会走这个老路……</p>
<p>Vue 目前感觉更像是社区驱动。我觉得 Svelte 也在朝这个方向发展，尽管它们都是从仁慈独裁者的方式开始的。它们都拥抱了更广泛的社区，而不是只满足一家公司的需求</p>
</blockquote>
<p>这几篇是一些影响力比较大的文章，相对来说观点已经比较全面了，大致分为以下几点：</p>
<ol>
<li>React 因为时代原因已经有些过时了，因为使用的人很多，所以他每一次新功能的增加都将非常谨慎像现在的Java一样，虽然版本号一路突飞猛进，但是变化依然不大</li>
<li>React 的除了流行外别无优点，整体的性能，包大小，等都不够拔</li>
</ol>
<p>但React也有其自己的优点：</p>
<ol>
<li>最强大的社区支持，你几乎能找到你想要的所有库</li>
<li>React不是一个框架，而是一个库，你多了解 JavaScript 就有多了解 React。他可以让你进行最大限度的定制</li>
</ol>
<blockquote>
<p>本文参考的文章如下：
<a href="https://www.jetbrains.com/zh-cn/" target="_blank" rel="noreferrer">JetBrains2023行业状况调研</a></p>
<p><a href="https://survey.stackoverflow.co/2023/" target="_blank" rel="noreferrer">StackOverflow2023行业调查问卷</a></p>
<p><a href="https://joshcollinsworth.com/blog/antiquated-react" target="_blank" rel="noreferrer">你因为 React 而忘记（或从来不知道）的事情 - Josh Collinsworth 博客</a></p>
<p><a href="https://joshcollinsworth.com/blog/self-fulfilling-prophecy-of-react" target="_blank" rel="noreferrer">React 的自我实现预言 - Josh Collinsworth 博客</a></p>
<p><a href="https://changelog.com/jsparty/244" target="_blank" rel="noreferrer">辛辣的 React 辩论秀 🌶️ （JS Party #244） (changelog.com)</a></p>
</blockquote>
]]></content>
        <author>
            <name>duyl328</name>
            <uri>https://seyl.me/about</uri>
        </author>
        <category label="编程"/>
        <category label="思考"/>
        <category label="vue"/>
        <category label="React"/>
        <category label="Blog"/>
        <category label="原创"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[VitePress 链接使用]]></title>
        <id>https://seyl.me/posts/2025/01/vitepress-link-jump</id>
        <link href="https://seyl.me/posts/2025/01/vitepress-link-jump"/>
        <updated>2024-01-21T00:00:00.000Z</updated>
        <content type="html"><![CDATA[<h1 id="完成跳转-可以点击返回" tabindex="-1">完成跳转 ，可以点击返回 <a class="header-anchor" href="#完成跳转-可以点击返回" aria-label="Permalink to &quot;完成跳转 ，可以点击返回&quot;">&ZeroWidthSpace;</a></h1>
<p><a href="./vitepress-note-use.html">返回</a></p>
]]></content>
        <author>
            <name>duyl328</name>
            <uri>https://seyl.me/about</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[登录功能的思考]]></title>
        <id>https://seyl.me/posts/2024/08/thoughts-login-function</id>
        <link href="https://seyl.me/posts/2024/08/thoughts-login-function"/>
        <updated>2023-08-05T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[<h1 id="frontmatter-title" tabindex="-1">{{ $frontmatter.title }} <a class="header-anchor" href="#frontmatter-title" aria-label="Permalink to &quot;{{ $frontmatter.title }}&quot;">&ZeroWidthSpace;</a></h1>
<blockquote>
<p>✒️ 文章摘要</p>
</blockquote>
<!-- DESC SEP -->
<p>这篇文章介绍了如何安全地存储用户数据，包括用户名、密码哈希、邮箱等，强调使用 bcrypt 加密密码和唯一盐来提升安全性。它还详细解释了 HTTPS 如何通过加密、身份验证和数据完整性保护来确保通信安全，并探讨了前端加密与 HTTPS 的配合使用。此外，文章还讨论了如何管理 SSL/TLS 证书、Token 存储和安全性防护策略，如防止 XSS 和 CSRF 攻击。</p>
<!-- DESC SEP -->
<h2 id="用户信息应该保存什么数据" tabindex="-1">用户信息应该保存什么数据 <a class="header-anchor" href="#用户信息应该保存什么数据" aria-label="Permalink to &quot;用户信息应该保存什么数据&quot;">&ZeroWidthSpace;</a></h2>
<ul>
<li><code>username</code>：唯一的用户名。</li>
<li><code>password_hash</code>：使用加密算法（如 bcrypt）对密码加密后的结果。</li>
<li><code>email</code>：用户的邮箱，作为额外的联系方式和用户名的验证。</li>
<li><code>created_at</code> 和 <code>updated_at</code>：记录用户的创建时间和最后一次更新时间。</li>
</ul>
<p>其他：</p>
<ul>
<li><strong>Email</strong>：用于账户验证和找回密码。</li>
<li><strong>创建时间（created_at）</strong>：记录账户创建时间。</li>
<li><strong>更新时间（updated_at）</strong>：记录账户信息的最后更新时间。</li>
<li><strong>用户角色（role）</strong>：标识用户身份，如普通用户、管理员等，用于权限管理。</li>
<li><strong>状态（status）</strong>：标识用户状态，如活跃、锁定、禁用等，用于账户管理。</li>
<li><strong>最后登录时间（last_login_at）</strong>：记录用户最后一次登录时间。</li>
<li><strong>安全问题及答案</strong>（可选）：用于找回密码。</li>
<li><strong>登录失败次数（login_attempts）</strong>：记录用户登录失败次数，用于防止暴力破解。</li>
<li>注册时间</li>
<li>注册IP</li>
<li>上次登录时间</li>
<li>登录地址</li>
<li>用户权限</li>
<li>手机号</li>
</ul>
<h2 id="密码如何保存" tabindex="-1">密码如何保存 <a class="header-anchor" href="#密码如何保存" aria-label="Permalink to &quot;密码如何保存&quot;">&ZeroWidthSpace;</a></h2>
<p><code>bcrypt</code>是由<code>Niels Provos</code>和<code>David Mazières</code>设计的密码哈希函数，他是基于Blowfish密码而来的，并于1999年在USENIX上提出。</p>
<p>除了加盐来抵御<code>rainbow table</code> 攻击之外，<code>bcrypt</code>
的一个非常重要的特征就是自适应性，可以保证加密的速度在一个特定的范围内，即使计算机的运算能力非常高，可以通过增加迭代次数的方式，使得加密速度变慢，从而可以抵御暴力搜索攻击。</p>
<p><code>bcrypt</code>函数是<code>OpenBSD</code>和其他系统包括一些Linux发行版（如SUSE Linux）的默认密码哈希算法。</p>
<p><strong>推荐使用</strong>每个用户都拥有一个独立的、唯一的盐。这种方式可以显著提高安全性，因为即使两个用户使用相同的密码，由于盐不同，生成的哈希值也会完全不同。</p>
<h4 id="生成盐" tabindex="-1">生成盐 <a class="header-anchor" href="#生成盐" aria-label="Permalink to &quot;生成盐&quot;">&ZeroWidthSpace;</a></h4>
<ul>
<li><strong>随机生成</strong>：使用密码学安全的随机数生成器生成盐，例如使用 <code>java.security.SecureRandom</code> 生成盐。</li>
<li><strong>长度建议</strong>：一般来说，盐的长度至少为 16 字节，以增加其随机性和安全性。</li>
</ul>
<h4 id="盐的存储" tabindex="-1"><strong>盐的存储</strong> <a class="header-anchor" href="#盐的存储" aria-label="Permalink to &quot;**盐的存储**&quot;">&ZeroWidthSpace;</a></h4>
<ul>
<li><strong>单独存储</strong>：将每个用户的盐单独存储在数据库中，与用户的其他信息（例如 <code>user_id</code>、<code>hashed_password</code>）一起存储。</li>
</ul>
<h4 id="处理已有用户的密码" tabindex="-1"><strong>处理已有用户的密码</strong> <a class="header-anchor" href="#处理已有用户的密码" aria-label="Permalink to &quot;**处理已有用户的密码**&quot;">&ZeroWidthSpace;</a></h4>
<p>如果需要为已有用户的密码增加盐，可以采取以下步骤：</p>
<ol>
<li><strong>逐步迁移</strong>：在用户下次登录时，提示用户更改密码并生成新的哈希和盐（用户更改密码时应该重新生成<strong>盐</strong>）。</li>
<li><strong>批量更新</strong>：将所有用户密码通过一次性脚本批量更新为新的加盐哈希值。</li>
<li><strong>新老兼容</strong>：在验证用户密码时，首先尝试使用老的哈希方式，如果失败则使用新的加盐哈希方式。</li>
</ol>
<h4 id="注意事项" tabindex="-1"><strong>注意事项</strong> <a class="header-anchor" href="#注意事项" aria-label="Permalink to &quot;**注意事项**&quot;">&ZeroWidthSpace;</a></h4>
<ul>
<li><strong>使用安全的随机数生成器</strong>：避免使用 <code>Math.random()</code> 这样的伪随机数生成器，而是使用 <code>SecureRandom</code> 等密码学安全的随机数生成器。</li>
<li><strong>避免重复使用盐</strong>：每个用户的盐都应该是唯一的，避免不同用户之间的盐重复使用。</li>
<li><strong>保护盐的安全</strong>：尽管盐本身不需要加密，但它仍然是安全链条中的一部分，应妥善保护，避免泄露。</li>
</ul>
<h2 id="https-如何保证数据安全" tabindex="-1">HTTPS 如何保证数据安全 <a class="header-anchor" href="#https-如何保证数据安全" aria-label="Permalink to &quot;HTTPS 如何保证数据安全&quot;">&ZeroWidthSpace;</a></h2>
<p><strong>HTTPS</strong>（Hypertext Transfer Protocol Secure）是一种用于在客户端和服务器之间安全传输数据的协议。</p>
<blockquote>
<p>http是无状态的超文本传输协议，连接简单，信息是明文传输，端口为80。
https协议是由http+ssl协议构建的可进行加密传输、身份认证的具有安全性网络协议,端口是443。</p>
<p>https通过使用 SSL，HTTPS 具有了加密（防窃听）、认证（防伪装）和完整性保护（防篡改）。</p>
</blockquote>
<p><strong>加密方式</strong>：</p>
<blockquote>
<p>HTTPS 采用混合的加密机制，使用非对称密钥加密用于传输对称密钥来保证传输过程的安全性，之后使用对称密钥加密进行通信来保证信息传输过程的效率。非对称加密只作用在证书验证阶段。</p>
</blockquote>
<p><strong>HTTPS的缺点</strong>:</p>
<blockquote>
<p>1）因为需要进行加密解密等过程，因此速度会更慢；
2）需要支付证书授权的高额费用。</p>
</blockquote>
<p><strong>交互过程</strong>：</p>
<p>客户端发起 HTTPS
请求，服务端返回证书，客户端对证书进行验证，验证通过后本地生成用于改造对称加密算法的随机数，通过证书中的公钥对随机数进行加密传输到服务端，服务端接收后通过私钥解密得到随机数，之后的数据交互通过对称加密算法进行加解密。</p>
<ol>
<li>客户端向服务器发起HTTPS请求，连接到服务器的443端口。</li>
<li>服务器端有一个密钥对，即公钥和私钥，是用来进行非对称加密使用的，服务器端保存着私钥，不能将其泄露，公钥可以发送给任何人。</li>
<li>服务器将自己的公钥发送给客户端。</li>
<li>客户端收到服务器端的公钥之后，会对公钥进行检查，验证其合法性，如果发现发现公钥有问题，那么HTTPS传输就无法继续。严格的说，这里应该是验证</li>
<li>务器发送的数字证书的合法性，关于客户端如何验证数字证书的合法性，下文会进行说明。如果公钥合格，那么客户端会生成一个随机值，这个随机值就是用于进行对称加密的密钥，我们将该密钥称之为client
key，即客户端密钥，这样在概念上和服务器端的密钥容易进行区分。然后用服务器的公钥对客户端密钥进行非对称加密，这样客户端密钥就变成密文了，至此，HTTPS中的第一次HTTP请求结束。</li>
<li>客户端会发起HTTPS中的第二个HTTP请求，将加密之后的客户端密钥发送给服务器。</li>
<li>服务器接收到客户端发来的密文之后，会用自己的私钥对其进行非对称解密，解密之后的明文就是客户端密钥，然后用客户端密钥对数据进行对称加密，这样数据就变成了密文。</li>
<li>然后服务器将加密后的密文发送给客户端。</li>
<li>客户端收到服务器发送来的密文，用客户端密钥对其进行对称解密，得到服务器发送的数据。这样HTTPS中的第二个HTTP请求结束，整个HTTPS传输完成。</li>
</ol>
<p><img src="./../../../public/posts/2024/08/img-1.webp" alt="image-20240709145013421"></p>
<p>它通过以下方式保证数据的安全性：</p>
<p><strong>数据加密</strong></p>
<ul>
<li><strong>加密数据传输</strong>：HTTPS 使用 TLS（Transport Layer Security）协议对数据进行加密，确保传输中的数据无法被窃听或篡改。</li>
<li><strong>对称加密</strong>：在 TLS 连接建立后，双方使用对称加密算法（如 AES）加密传输的数据，速度快且效率高。</li>
</ul>
<p><strong>身份验证</strong></p>
<ul>
<li><strong>服务器认证</strong>：通过 SSL/TLS 证书，客户端可以验证服务器的身份，防止中间人攻击。</li>
<li><strong>防止钓鱼网站</strong>：用户可以确认访问的服务器是否为合法的服务器，避免被引导至钓鱼网站。</li>
</ul>
<p><strong>数据完整性</strong></p>
<ul>
<li><strong>防止数据篡改</strong>：通过哈希函数和 MAC（Message Authentication Code），确保数据在传输过程中未被篡改。</li>
</ul>
<h2 id="是否可以不依赖-https-仅依赖前端加密来保证安全性" tabindex="-1">是否可以不依赖 HTTPS，仅依赖前端加密来保证安全性？ <a class="header-anchor" href="#是否可以不依赖-https-仅依赖前端加密来保证安全性" aria-label="Permalink to &quot;是否可以不依赖 HTTPS，仅依赖前端加密来保证安全性？&quot;">&ZeroWidthSpace;</a></h2>
<h4 id="安全性的局限" tabindex="-1">安全性的局限 <a class="header-anchor" href="#安全性的局限" aria-label="Permalink to &quot;安全性的局限&quot;">&ZeroWidthSpace;</a></h4>
<p>即使前端使用了加密技术，如果没有 HTTPS 作为底层保护，仍然存在以下安全隐患：</p>
<ul>
<li><strong>中间人攻击（MITM）</strong>：攻击者可以拦截和修改前端与后端之间的通信内容，即使加密了密码，也可能无法防止攻击者篡改其他请求参数或注入恶意代码。</li>
<li><strong>公钥篡改</strong>：如果攻击者能够篡改你的网站或应用中的公钥，他们可以用自己的公钥替换你网站的公钥，从而获得解密私钥。</li>
<li><strong>数据完整性</strong>：没有 HTTPS 的保护，传输的数据可能被篡改，而不仅仅是密码，还包括其他敏感信息。</li>
</ul>
<h4 id="攻击者可以如何篡改公钥" tabindex="-1">攻击者可以如何篡改公钥？ <a class="header-anchor" href="#攻击者可以如何篡改公钥" aria-label="Permalink to &quot;攻击者可以如何篡改公钥？&quot;">&ZeroWidthSpace;</a></h4>
<p>公钥篡改主要涉及以下几种方式：</p>
<p><strong>中间人攻击（MITM）</strong></p>
<ul>
<li><strong>工作原理</strong>：攻击者拦截用户和服务器之间的通信，并在其间插入自己的公钥。</li>
<li><strong>实现方式</strong>：攻击者可以通过DNS劫持、网络劫持或伪造Wi-Fi热点等方式拦截流量并插入恶意公钥。</li>
</ul>
<p><strong>服务器端攻击</strong></p>
<ul>
<li><strong>访问服务器</strong>：攻击者通过漏洞或其他方式入侵你的服务器，替换服务器上的公钥。</li>
<li><strong>后果</strong>：用户使用篡改后的公钥进行加密，攻击者可以用对应的私钥解密。</li>
</ul>
<p><strong>前端代码篡改</strong></p>
<ul>
<li><strong>篡改代码</strong>：攻击者可以通过入侵 CDN、服务器或开发者的本地机器，修改前端代码，替换其中的公钥。</li>
<li><strong>发布渠道</strong>：通过不安全的渠道发布应用，导致篡改的公钥传播给用户。</li>
</ul>
<h4 id="https-与前端加密的协作" tabindex="-1">HTTPS 与前端加密的协作 <a class="header-anchor" href="#https-与前端加密的协作" aria-label="Permalink to &quot;HTTPS 与前端加密的协作&quot;">&ZeroWidthSpace;</a></h4>
<p>为了最大限度地确保数据安全，推荐将前端加密与 HTTPS 结合使用：</p>
<ul>
<li><strong>HTTPS 传输</strong>：通过 HTTPS 确保整个传输通道的安全性。</li>
<li><strong>前端加密</strong>：在前端对敏感数据（如密码）进行加密，作为额外的安全保障。</li>
<li><strong>多层保护</strong>：即使 HTTPS 被攻破，前端加密也能提供另一层保护。</li>
</ul>
<h2 id="前端如何防止公钥被篡改" tabindex="-1">前端如何防止公钥被篡改？ <a class="header-anchor" href="#前端如何防止公钥被篡改" aria-label="Permalink to &quot;前端如何防止公钥被篡改？&quot;">&ZeroWidthSpace;</a></h2>
<p><strong>使用 HTTPS 和证书验证</strong></p>
<ul>
<li><strong>确保公钥安全传输</strong>：通过 HTTPS 传输公钥，防止中间人攻击。</li>
<li><strong>使用可信证书</strong>：通过可信的 CA 签发的证书确保公钥的合法性。</li>
</ul>
<p><strong>内容安全策略（CSP）</strong></p>
<blockquote>
<p>CSP 的实质就是白名单制度，开发者明确告诉客户端，哪些外部资源可以加载和执行，等同于提供白名单。它的实现和执行全部由浏览器完成，开发者只需提供配置。</p>
</blockquote>
<ul>
<li>
<p><strong>定义内容来源</strong>：使用 CSP 限制加载的资源，防止加载恶意的脚本和公钥。</p>
</li>
<li>
<p><strong>用途</strong>
：用于检测并削弱某些特定类型的攻击，包括跨站脚本（<a href="https://developer.mozilla.org/zh-CN/docs/Glossary/Cross-site_scripting" target="_blank" rel="noreferrer">XSS</a>
）和数据注入攻击等。</p>
</li>
<li>
<p><strong>示例配置</strong>：</p>
<div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Content</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Security</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Policy</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">default-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">src </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'self'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; script</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">src </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'self'</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> https</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//trusted.cdn.com</span></span></code></pre>
</div></li>
</ul>
<p><strong>前端代码完整性校验</strong></p>
<ul>
<li>
<p><strong>Subresource Integrity (SRI)</strong>：使用 SRI 确保加载的前端资源（如 JS 脚本）未被篡改。</p>
<div class="language-html vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">html</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">script</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> src</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"https://trusted.cdn.com/script.js"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> integrity</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"sha384-..."</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">script</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span></code></pre>
</div></li>
<li>
<p><strong>代码签名</strong>：对前端代码进行签名，用户可以验证下载的代码是否被篡改。</p>
</li>
</ul>
<p><strong>前端代码加密</strong></p>
<ul>
<li><strong>代码混淆</strong>：使用代码混淆工具增加代码的复杂性，防止反编译和分析。比如，Webpack、UglifyJS 等工具可以对 JavaScript 代码进行混淆。</li>
<li><strong>加密重要数据</strong>：将敏感数据和密钥加密存储在前端，并通过运行时解密使用。</li>
</ul>
<p><strong>安全加载资源</strong></p>
<ul>
<li><strong>内容安全策略（CSP）</strong>：使用 CSP 限制加载的脚本和资源来源，防止恶意代码篡改。</li>
<li><strong>子资源完整性（SRI）</strong>：通过 SRI 验证加载资源的完整性，确保资源未被篡改。</li>
</ul>
<h2 id="前端应该如何存储公钥" tabindex="-1">前端应该如何存储公钥？ <a class="header-anchor" href="#前端应该如何存储公钥" aria-label="Permalink to &quot;前端应该如何存储公钥？&quot;">&ZeroWidthSpace;</a></h2>
<p><strong>存储在代码中</strong></p>
<ul>
<li>
<p><strong>嵌入代码</strong>：将公钥硬编码在前端代码中，这是最常见的做法，但容易被静态分析工具提取。</p>
</li>
<li>
<p><strong>示例</strong>：</p>
<div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> publicKey</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> `</span></span></code></pre>
</div></li>
</ul>
]]></summary>
        <content type="html"><![CDATA[<h1 id="frontmatter-title" tabindex="-1">{{ $frontmatter.title }} <a class="header-anchor" href="#frontmatter-title" aria-label="Permalink to &quot;{{ $frontmatter.title }}&quot;">&ZeroWidthSpace;</a></h1>
<blockquote>
<p>✒️ 文章摘要</p>
</blockquote>
<!-- DESC SEP -->
<p>这篇文章介绍了如何安全地存储用户数据，包括用户名、密码哈希、邮箱等，强调使用 bcrypt 加密密码和唯一盐来提升安全性。它还详细解释了 HTTPS 如何通过加密、身份验证和数据完整性保护来确保通信安全，并探讨了前端加密与 HTTPS 的配合使用。此外，文章还讨论了如何管理 SSL/TLS 证书、Token 存储和安全性防护策略，如防止 XSS 和 CSRF 攻击。</p>
<!-- DESC SEP -->
<h2 id="用户信息应该保存什么数据" tabindex="-1">用户信息应该保存什么数据 <a class="header-anchor" href="#用户信息应该保存什么数据" aria-label="Permalink to &quot;用户信息应该保存什么数据&quot;">&ZeroWidthSpace;</a></h2>
<ul>
<li><code>username</code>：唯一的用户名。</li>
<li><code>password_hash</code>：使用加密算法（如 bcrypt）对密码加密后的结果。</li>
<li><code>email</code>：用户的邮箱，作为额外的联系方式和用户名的验证。</li>
<li><code>created_at</code> 和 <code>updated_at</code>：记录用户的创建时间和最后一次更新时间。</li>
</ul>
<p>其他：</p>
<ul>
<li><strong>Email</strong>：用于账户验证和找回密码。</li>
<li><strong>创建时间（created_at）</strong>：记录账户创建时间。</li>
<li><strong>更新时间（updated_at）</strong>：记录账户信息的最后更新时间。</li>
<li><strong>用户角色（role）</strong>：标识用户身份，如普通用户、管理员等，用于权限管理。</li>
<li><strong>状态（status）</strong>：标识用户状态，如活跃、锁定、禁用等，用于账户管理。</li>
<li><strong>最后登录时间（last_login_at）</strong>：记录用户最后一次登录时间。</li>
<li><strong>安全问题及答案</strong>（可选）：用于找回密码。</li>
<li><strong>登录失败次数（login_attempts）</strong>：记录用户登录失败次数，用于防止暴力破解。</li>
<li>注册时间</li>
<li>注册IP</li>
<li>上次登录时间</li>
<li>登录地址</li>
<li>用户权限</li>
<li>手机号</li>
</ul>
<h2 id="密码如何保存" tabindex="-1">密码如何保存 <a class="header-anchor" href="#密码如何保存" aria-label="Permalink to &quot;密码如何保存&quot;">&ZeroWidthSpace;</a></h2>
<p><code>bcrypt</code>是由<code>Niels Provos</code>和<code>David Mazières</code>设计的密码哈希函数，他是基于Blowfish密码而来的，并于1999年在USENIX上提出。</p>
<p>除了加盐来抵御<code>rainbow table</code> 攻击之外，<code>bcrypt</code>
的一个非常重要的特征就是自适应性，可以保证加密的速度在一个特定的范围内，即使计算机的运算能力非常高，可以通过增加迭代次数的方式，使得加密速度变慢，从而可以抵御暴力搜索攻击。</p>
<p><code>bcrypt</code>函数是<code>OpenBSD</code>和其他系统包括一些Linux发行版（如SUSE Linux）的默认密码哈希算法。</p>
<p><strong>推荐使用</strong>每个用户都拥有一个独立的、唯一的盐。这种方式可以显著提高安全性，因为即使两个用户使用相同的密码，由于盐不同，生成的哈希值也会完全不同。</p>
<h4 id="生成盐" tabindex="-1">生成盐 <a class="header-anchor" href="#生成盐" aria-label="Permalink to &quot;生成盐&quot;">&ZeroWidthSpace;</a></h4>
<ul>
<li><strong>随机生成</strong>：使用密码学安全的随机数生成器生成盐，例如使用 <code>java.security.SecureRandom</code> 生成盐。</li>
<li><strong>长度建议</strong>：一般来说，盐的长度至少为 16 字节，以增加其随机性和安全性。</li>
</ul>
<h4 id="盐的存储" tabindex="-1"><strong>盐的存储</strong> <a class="header-anchor" href="#盐的存储" aria-label="Permalink to &quot;**盐的存储**&quot;">&ZeroWidthSpace;</a></h4>
<ul>
<li><strong>单独存储</strong>：将每个用户的盐单独存储在数据库中，与用户的其他信息（例如 <code>user_id</code>、<code>hashed_password</code>）一起存储。</li>
</ul>
<h4 id="处理已有用户的密码" tabindex="-1"><strong>处理已有用户的密码</strong> <a class="header-anchor" href="#处理已有用户的密码" aria-label="Permalink to &quot;**处理已有用户的密码**&quot;">&ZeroWidthSpace;</a></h4>
<p>如果需要为已有用户的密码增加盐，可以采取以下步骤：</p>
<ol>
<li><strong>逐步迁移</strong>：在用户下次登录时，提示用户更改密码并生成新的哈希和盐（用户更改密码时应该重新生成<strong>盐</strong>）。</li>
<li><strong>批量更新</strong>：将所有用户密码通过一次性脚本批量更新为新的加盐哈希值。</li>
<li><strong>新老兼容</strong>：在验证用户密码时，首先尝试使用老的哈希方式，如果失败则使用新的加盐哈希方式。</li>
</ol>
<h4 id="注意事项" tabindex="-1"><strong>注意事项</strong> <a class="header-anchor" href="#注意事项" aria-label="Permalink to &quot;**注意事项**&quot;">&ZeroWidthSpace;</a></h4>
<ul>
<li><strong>使用安全的随机数生成器</strong>：避免使用 <code>Math.random()</code> 这样的伪随机数生成器，而是使用 <code>SecureRandom</code> 等密码学安全的随机数生成器。</li>
<li><strong>避免重复使用盐</strong>：每个用户的盐都应该是唯一的，避免不同用户之间的盐重复使用。</li>
<li><strong>保护盐的安全</strong>：尽管盐本身不需要加密，但它仍然是安全链条中的一部分，应妥善保护，避免泄露。</li>
</ul>
<h2 id="https-如何保证数据安全" tabindex="-1">HTTPS 如何保证数据安全 <a class="header-anchor" href="#https-如何保证数据安全" aria-label="Permalink to &quot;HTTPS 如何保证数据安全&quot;">&ZeroWidthSpace;</a></h2>
<p><strong>HTTPS</strong>（Hypertext Transfer Protocol Secure）是一种用于在客户端和服务器之间安全传输数据的协议。</p>
<blockquote>
<p>http是无状态的超文本传输协议，连接简单，信息是明文传输，端口为80。
https协议是由http+ssl协议构建的可进行加密传输、身份认证的具有安全性网络协议,端口是443。</p>
<p>https通过使用 SSL，HTTPS 具有了加密（防窃听）、认证（防伪装）和完整性保护（防篡改）。</p>
</blockquote>
<p><strong>加密方式</strong>：</p>
<blockquote>
<p>HTTPS 采用混合的加密机制，使用非对称密钥加密用于传输对称密钥来保证传输过程的安全性，之后使用对称密钥加密进行通信来保证信息传输过程的效率。非对称加密只作用在证书验证阶段。</p>
</blockquote>
<p><strong>HTTPS的缺点</strong>:</p>
<blockquote>
<p>1）因为需要进行加密解密等过程，因此速度会更慢；
2）需要支付证书授权的高额费用。</p>
</blockquote>
<p><strong>交互过程</strong>：</p>
<p>客户端发起 HTTPS
请求，服务端返回证书，客户端对证书进行验证，验证通过后本地生成用于改造对称加密算法的随机数，通过证书中的公钥对随机数进行加密传输到服务端，服务端接收后通过私钥解密得到随机数，之后的数据交互通过对称加密算法进行加解密。</p>
<ol>
<li>客户端向服务器发起HTTPS请求，连接到服务器的443端口。</li>
<li>服务器端有一个密钥对，即公钥和私钥，是用来进行非对称加密使用的，服务器端保存着私钥，不能将其泄露，公钥可以发送给任何人。</li>
<li>服务器将自己的公钥发送给客户端。</li>
<li>客户端收到服务器端的公钥之后，会对公钥进行检查，验证其合法性，如果发现发现公钥有问题，那么HTTPS传输就无法继续。严格的说，这里应该是验证</li>
<li>务器发送的数字证书的合法性，关于客户端如何验证数字证书的合法性，下文会进行说明。如果公钥合格，那么客户端会生成一个随机值，这个随机值就是用于进行对称加密的密钥，我们将该密钥称之为client
key，即客户端密钥，这样在概念上和服务器端的密钥容易进行区分。然后用服务器的公钥对客户端密钥进行非对称加密，这样客户端密钥就变成密文了，至此，HTTPS中的第一次HTTP请求结束。</li>
<li>客户端会发起HTTPS中的第二个HTTP请求，将加密之后的客户端密钥发送给服务器。</li>
<li>服务器接收到客户端发来的密文之后，会用自己的私钥对其进行非对称解密，解密之后的明文就是客户端密钥，然后用客户端密钥对数据进行对称加密，这样数据就变成了密文。</li>
<li>然后服务器将加密后的密文发送给客户端。</li>
<li>客户端收到服务器发送来的密文，用客户端密钥对其进行对称解密，得到服务器发送的数据。这样HTTPS中的第二个HTTP请求结束，整个HTTPS传输完成。</li>
</ol>
<p><img src="./../../../public/posts/2024/08/img-1.webp" alt="image-20240709145013421"></p>
<p>它通过以下方式保证数据的安全性：</p>
<p><strong>数据加密</strong></p>
<ul>
<li><strong>加密数据传输</strong>：HTTPS 使用 TLS（Transport Layer Security）协议对数据进行加密，确保传输中的数据无法被窃听或篡改。</li>
<li><strong>对称加密</strong>：在 TLS 连接建立后，双方使用对称加密算法（如 AES）加密传输的数据，速度快且效率高。</li>
</ul>
<p><strong>身份验证</strong></p>
<ul>
<li><strong>服务器认证</strong>：通过 SSL/TLS 证书，客户端可以验证服务器的身份，防止中间人攻击。</li>
<li><strong>防止钓鱼网站</strong>：用户可以确认访问的服务器是否为合法的服务器，避免被引导至钓鱼网站。</li>
</ul>
<p><strong>数据完整性</strong></p>
<ul>
<li><strong>防止数据篡改</strong>：通过哈希函数和 MAC（Message Authentication Code），确保数据在传输过程中未被篡改。</li>
</ul>
<h2 id="是否可以不依赖-https-仅依赖前端加密来保证安全性" tabindex="-1">是否可以不依赖 HTTPS，仅依赖前端加密来保证安全性？ <a class="header-anchor" href="#是否可以不依赖-https-仅依赖前端加密来保证安全性" aria-label="Permalink to &quot;是否可以不依赖 HTTPS，仅依赖前端加密来保证安全性？&quot;">&ZeroWidthSpace;</a></h2>
<h4 id="安全性的局限" tabindex="-1">安全性的局限 <a class="header-anchor" href="#安全性的局限" aria-label="Permalink to &quot;安全性的局限&quot;">&ZeroWidthSpace;</a></h4>
<p>即使前端使用了加密技术，如果没有 HTTPS 作为底层保护，仍然存在以下安全隐患：</p>
<ul>
<li><strong>中间人攻击（MITM）</strong>：攻击者可以拦截和修改前端与后端之间的通信内容，即使加密了密码，也可能无法防止攻击者篡改其他请求参数或注入恶意代码。</li>
<li><strong>公钥篡改</strong>：如果攻击者能够篡改你的网站或应用中的公钥，他们可以用自己的公钥替换你网站的公钥，从而获得解密私钥。</li>
<li><strong>数据完整性</strong>：没有 HTTPS 的保护，传输的数据可能被篡改，而不仅仅是密码，还包括其他敏感信息。</li>
</ul>
<h4 id="攻击者可以如何篡改公钥" tabindex="-1">攻击者可以如何篡改公钥？ <a class="header-anchor" href="#攻击者可以如何篡改公钥" aria-label="Permalink to &quot;攻击者可以如何篡改公钥？&quot;">&ZeroWidthSpace;</a></h4>
<p>公钥篡改主要涉及以下几种方式：</p>
<p><strong>中间人攻击（MITM）</strong></p>
<ul>
<li><strong>工作原理</strong>：攻击者拦截用户和服务器之间的通信，并在其间插入自己的公钥。</li>
<li><strong>实现方式</strong>：攻击者可以通过DNS劫持、网络劫持或伪造Wi-Fi热点等方式拦截流量并插入恶意公钥。</li>
</ul>
<p><strong>服务器端攻击</strong></p>
<ul>
<li><strong>访问服务器</strong>：攻击者通过漏洞或其他方式入侵你的服务器，替换服务器上的公钥。</li>
<li><strong>后果</strong>：用户使用篡改后的公钥进行加密，攻击者可以用对应的私钥解密。</li>
</ul>
<p><strong>前端代码篡改</strong></p>
<ul>
<li><strong>篡改代码</strong>：攻击者可以通过入侵 CDN、服务器或开发者的本地机器，修改前端代码，替换其中的公钥。</li>
<li><strong>发布渠道</strong>：通过不安全的渠道发布应用，导致篡改的公钥传播给用户。</li>
</ul>
<h4 id="https-与前端加密的协作" tabindex="-1">HTTPS 与前端加密的协作 <a class="header-anchor" href="#https-与前端加密的协作" aria-label="Permalink to &quot;HTTPS 与前端加密的协作&quot;">&ZeroWidthSpace;</a></h4>
<p>为了最大限度地确保数据安全，推荐将前端加密与 HTTPS 结合使用：</p>
<ul>
<li><strong>HTTPS 传输</strong>：通过 HTTPS 确保整个传输通道的安全性。</li>
<li><strong>前端加密</strong>：在前端对敏感数据（如密码）进行加密，作为额外的安全保障。</li>
<li><strong>多层保护</strong>：即使 HTTPS 被攻破，前端加密也能提供另一层保护。</li>
</ul>
<h2 id="前端如何防止公钥被篡改" tabindex="-1">前端如何防止公钥被篡改？ <a class="header-anchor" href="#前端如何防止公钥被篡改" aria-label="Permalink to &quot;前端如何防止公钥被篡改？&quot;">&ZeroWidthSpace;</a></h2>
<p><strong>使用 HTTPS 和证书验证</strong></p>
<ul>
<li><strong>确保公钥安全传输</strong>：通过 HTTPS 传输公钥，防止中间人攻击。</li>
<li><strong>使用可信证书</strong>：通过可信的 CA 签发的证书确保公钥的合法性。</li>
</ul>
<p><strong>内容安全策略（CSP）</strong></p>
<blockquote>
<p>CSP 的实质就是白名单制度，开发者明确告诉客户端，哪些外部资源可以加载和执行，等同于提供白名单。它的实现和执行全部由浏览器完成，开发者只需提供配置。</p>
</blockquote>
<ul>
<li>
<p><strong>定义内容来源</strong>：使用 CSP 限制加载的资源，防止加载恶意的脚本和公钥。</p>
</li>
<li>
<p><strong>用途</strong>
：用于检测并削弱某些特定类型的攻击，包括跨站脚本（<a href="https://developer.mozilla.org/zh-CN/docs/Glossary/Cross-site_scripting" target="_blank" rel="noreferrer">XSS</a>
）和数据注入攻击等。</p>
</li>
<li>
<p><strong>示例配置</strong>：</p>
<div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Content</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Security</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Policy</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">default-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">src </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'self'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; script</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">src </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'self'</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> https</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">//trusted.cdn.com</span></span></code></pre>
</div></li>
</ul>
<p><strong>前端代码完整性校验</strong></p>
<ul>
<li>
<p><strong>Subresource Integrity (SRI)</strong>：使用 SRI 确保加载的前端资源（如 JS 脚本）未被篡改。</p>
<div class="language-html vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">html</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">script</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> src</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"https://trusted.cdn.com/script.js"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> integrity</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"sha384-..."</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">script</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span></code></pre>
</div></li>
<li>
<p><strong>代码签名</strong>：对前端代码进行签名，用户可以验证下载的代码是否被篡改。</p>
</li>
</ul>
<p><strong>前端代码加密</strong></p>
<ul>
<li><strong>代码混淆</strong>：使用代码混淆工具增加代码的复杂性，防止反编译和分析。比如，Webpack、UglifyJS 等工具可以对 JavaScript 代码进行混淆。</li>
<li><strong>加密重要数据</strong>：将敏感数据和密钥加密存储在前端，并通过运行时解密使用。</li>
</ul>
<p><strong>安全加载资源</strong></p>
<ul>
<li><strong>内容安全策略（CSP）</strong>：使用 CSP 限制加载的脚本和资源来源，防止恶意代码篡改。</li>
<li><strong>子资源完整性（SRI）</strong>：通过 SRI 验证加载资源的完整性，确保资源未被篡改。</li>
</ul>
<h2 id="前端应该如何存储公钥" tabindex="-1">前端应该如何存储公钥？ <a class="header-anchor" href="#前端应该如何存储公钥" aria-label="Permalink to &quot;前端应该如何存储公钥？&quot;">&ZeroWidthSpace;</a></h2>
<p><strong>存储在代码中</strong></p>
<ul>
<li>
<p><strong>嵌入代码</strong>：将公钥硬编码在前端代码中，这是最常见的做法，但容易被静态分析工具提取。</p>
</li>
<li>
<p><strong>示例</strong>：</p>
<div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> publicKey</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> `-----BEGIN PUBLIC KEY-----</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">...</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">-----END PUBLIC KEY-----`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span></code></pre>
</div></li>
</ul>
<p><strong>动态获取</strong></p>
<ul>
<li><strong>通过 HTTPS 获取</strong>：从服务器动态获取公钥，并通过 HTTPS 确保传输安全。</li>
<li><strong>防止缓存攻击</strong>：设置合适的缓存策略，防止恶意缓存替换公钥。</li>
</ul>
<p><strong>加密存储</strong></p>
<ul>
<li><strong>加密存储</strong>：将公钥加密存储在前端，启动时解密使用。</li>
<li><strong>密钥管理</strong>：需要安全管理用于解密公钥的密钥。</li>
</ul>
<p><strong>使用 CDN</strong>：将公钥存储在可信的 CDN 上，并通过 HTTPS 获取，确保前端的公钥安全更新。</p>
<h2 id="如何保证后端私钥的安全存储" tabindex="-1">如何保证后端私钥的安全存储？ <a class="header-anchor" href="#如何保证后端私钥的安全存储" aria-label="Permalink to &quot;如何保证后端私钥的安全存储？&quot;">&ZeroWidthSpace;</a></h2>
<p><strong>私钥存储位置</strong></p>
<ul>
<li><strong>硬编码的风险</strong>：将密钥直接硬编码在代码中非常危险，攻击者可以通过反编译或分析代码轻松获取密钥。</li>
<li><strong>硬件安全模块（HSM）</strong>：HSM 是专门设计用于存储密钥的设备，具有极高的安全性和防篡改特性。它能生成和存储密钥，并执行加密运算，极大减少私钥泄露的风险。</li>
<li><strong>云密钥管理服务</strong>：如 AWS KMS、Azure Key Vault、Google Cloud KMS 等，提供安全的密钥管理和加密服务，可以将密钥存储在云端，避免密钥管理的复杂性和潜在的安全风险。</li>
<li><strong>安全文件存储</strong>：如果无法使用 HSM 或云服务，可以将私钥存储在服务器的安全文件系统中，严格控制访问权限（如仅允许特定用户和进程访问）。</li>
<li><strong>环境变量</strong>：
<ul>
<li><strong>安全存储</strong>：将密钥或密钥文件路径存储在环境变量中，避免硬编码在代码中。</li>
<li><strong>安全读取</strong>：通过环境变量读取密钥，并确保环境变量的访问权限受控。</li>
</ul>
</li>
<li><strong>加密密钥管理库</strong>：
<ul>
<li><strong>专用库</strong>：如 JCE（Java Cryptography Extension）、OpenSSL、bcrypt 等，可以提供密钥加密、解密和存储功能。</li>
<li><strong>加密和解密流程</strong>：利用这些库，密钥可以在需要时解密使用，避免直接暴露在代码中。</li>
</ul>
</li>
<li><strong>密钥保护库</strong>：
<ul>
<li><strong>使用库和框架</strong>：使用像 HashiCorp Vault、Azure Key Vault 等专用库和框架来管理和保护密钥。</li>
<li><strong>密钥存储服务</strong>：利用操作系统或平台提供的密钥存储服务，如 macOS 的钥匙串、Windows 的 DPAPI（数据保护 API）等。</li>
</ul>
</li>
</ul>
<p><strong>安全更新和备份</strong></p>
<ul>
<li><strong>定期更新</strong>：定期更换私钥，并确保旧密钥不再使用，减少长期使用同一密钥的风险。</li>
<li><strong>安全备份</strong>：将私钥备份在安全的地方，并确保备份数据的加密和访问控制。</li>
</ul>
<h2 id="如何保证公钥和私钥的安全更新" tabindex="-1">如何保证公钥和私钥的安全更新？ <a class="header-anchor" href="#如何保证公钥和私钥的安全更新" aria-label="Permalink to &quot;如何保证公钥和私钥的安全更新？&quot;">&ZeroWidthSpace;</a></h2>
<p><strong>使用可信工具</strong>:使用 OpenSSL、Java KeyTool 等工具生成密钥，确保密钥生成过程的安全性</p>
<p><strong>密钥替换周期</strong></p>
<ul>
<li><strong>定期轮换</strong>：根据安全需求和行业标准，定期更换密钥。通常建议每 1-2 年更换一次，但对于高风险的应用，可以更频繁地更换。</li>
<li><strong>紧急更换</strong>：在检测到潜在的安全威胁或密钥泄露时，立即更换密钥。</li>
</ul>
<p><strong>自动化密钥管理</strong></p>
<ul>
<li><strong>自动化工具</strong>：使用工具和脚本自动化密钥生成、分发和更新流程，减少人为错误。</li>
<li><strong>密钥版本管理</strong>：实现密钥版本控制，每次更新都生成一个新版本，逐步替换旧版本，并确保新旧密钥的兼容性。</li>
</ul>
<p><strong>密钥更新通知</strong></p>
<ul>
<li><strong>前端同步更新</strong>：后端密钥更新后，通过安全的通知机制将新公钥分发到前端，前端在下一次更新时使用新公钥。</li>
<li><strong>密钥有效期</strong>：使用密钥的有效期管理机制，确保在旧密钥失效前及时更换新密钥。</li>
</ul>
<h2 id="登录标志-token" tabindex="-1">登录标志（Token） <a class="header-anchor" href="#登录标志-token" aria-label="Permalink to &quot;登录标志（Token）&quot;">&ZeroWidthSpace;</a></h2>
<h4 id="推荐的存储方式" tabindex="-1">推荐的存储方式 <a class="header-anchor" href="#推荐的存储方式" aria-label="Permalink to &quot;推荐的存储方式&quot;">&ZeroWidthSpace;</a></h4>
<ol>
<li>
<p><strong>使用 Cookie 存储 Token</strong></p>
<ul>
<li><strong>HttpOnly 和 Secure</strong>：设置 HttpOnly 属性，防止 JavaScript 读取。设置 Secure 属性，仅允许在 HTTPS 连接中传输。</li>
<li><strong>SameSite 属性</strong>：设置为 <code>Strict</code> 或 <code>Lax</code>，防止 CSRF 攻击。</li>
</ul>
<blockquote>
<p><strong>什么是 CSRF 攻击</strong>？</p>
<p>这一天，小明同学百无聊赖地刷着Gmail邮件。大部分都是没营养的通知、验证码、聊天记录之类。但有一封邮件引起了小明的注意：</p>
<blockquote>
<p>甩卖比特币，一个只要998！！</p>
</blockquote>
<p>聪明的小明当然知道这种肯定是骗子，但还是抱着好奇的态度点了进去（请勿模仿）。果然，这只是一个什么都没有的空白页面，小明失望的关闭了页面。一切似乎什么都没有发生……</p>
</blockquote>
<p>在这平静的外表之下，黑客的攻击已然得手。小明的Gmail中，被偷偷设置了一个过滤规则，这个规则使得所有的邮件都会被自动转发到hacker@hackermail.com。小明还在继续刷着邮件，殊不知他的邮件正在一封封地，如脱缰的野马一般地，持续不断地向着黑客的邮箱转发而去。</p>
<blockquote>
<p>不久之后的一天，小明发现自己的域名已经被转让了。懵懂的小明以为是域名到期自己忘了续费，直到有一天，对方开出了 $650
的赎回价码，小明才开始觉得不太对劲。</p>
<p>小明仔细查了下域名的转让，对方是拥有自己的验证码的，而域名的验证码只存在于自己的邮箱里面。小明回想起那天奇怪的链接，打开后重新查看了“空白页”的源码：</p>
<div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">form</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> method</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"POST"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> action</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"https://mail.google.com/mail/h/ewt1jmuj4ddv/?v=prf"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> enctype</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"multipart/form-data"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">input</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> type</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"hidden"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"cf2_emc"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> value</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"true"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">/> </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">input</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> type</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"hidden"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"cf2_email"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> value</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"hacker@hakermail.com"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">/> </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    .....</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">input</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> type</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"hidden"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"irf"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> value</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"on"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">/> </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">input</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> type</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"hidden"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"nvp_bu_cftb"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> value</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Create Filter"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">/> </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">form</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">script</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    document.forms[0].submit();</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">script</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span></code></pre>
</div><blockquote>
<p>这个页面只要打开，就会向Gmail发送一个post请求。请求中，执行了“Create Filter”命令，将所有的邮件，转发到“hacker@hackermail.com”。</p>
<p>小明由于刚刚就登陆了Gmail，所以这个请求发送时，携带着小明的登录凭证（Cookie），Gmail的后台接收到请求，验证了确实有小明的登录凭证，于是成功给小明配置了过滤器。</p>
<p>黑客可以查看小明的所有邮件，包括邮件里的域名验证码等隐私信息。拿到验证码之后，黑客就可以要求域名服务商把域名重置给自己。</p>
</blockquote>
<p>小明很快打开Gmail，找到了那条过滤器，将其删除。然而，已经泄露的邮件，已经被转让的域名，再也无法挽回了……</p>
<p>以上就是小明的悲惨遭遇。而“点开一个黑客的链接，所有邮件都被窃取”这种事情并不是杜撰的，此事件原型是2007年Gmail的CSRF漏洞：</p>
<p><a href="https://www.davidairey.com/google-gmail-security-hijack/" target="_blank" rel="noreferrer">https://www.davidairey.com/google-Gmail-security-hijack/</a></p>
<p>当然，目前此漏洞已被Gmail修复</p>
</blockquote>
</li>
<li>
<p><strong>结合使用 LocalStorage 和内存</strong></p>
<ul>
<li><strong>LocalStorage</strong>：用于存储 Token 的加密副本，用于持久化和恢复。</li>
<li><strong>内存</strong>：在运行时将 Token 加载到内存中，减少对 LocalStorage 的访问。</li>
</ul>
</li>
</ol>
<h4 id="token-存储时机" tabindex="-1">Token 存储时机 <a class="header-anchor" href="#token-存储时机" aria-label="Permalink to &quot;Token 存储时机&quot;">&ZeroWidthSpace;</a></h4>
<ol>
<li><strong>登录成功后</strong>：
<ul>
<li>在用户成功登录后，从服务器接收到 Token，并在前端存储。</li>
</ul>
</li>
<li><strong>Token 刷新时</strong>：
<ul>
<li>在 Token 即将过期时，通过刷新 Token API 获取新的 Token，并更新存储。</li>
</ul>
</li>
</ol>
<h4 id="携带-token-的时机" tabindex="-1">携带 Token 的时机 <a class="header-anchor" href="#携带-token-的时机" aria-label="Permalink to &quot;携带 Token 的时机&quot;">&ZeroWidthSpace;</a></h4>
<ol>
<li><strong>自动登录</strong>：
<ul>
<li>在页面加载时检查 Token 是否存在并有效。</li>
<li>如果有效，自动发送 Token 进行身份验证。</li>
</ul>
</li>
<li><strong>每次 API 请求</strong>：
<ul>
<li>每次向受保护的 API 发送请求时，携带 Token 进行身份验证。</li>
</ul>
</li>
<li><strong>页面重载</strong>：
<ul>
<li>当页面重载或导航时，从存储中读取 Token 并加载到内存中。</li>
</ul>
</li>
</ol>
<h4 id="token-的携带方式" tabindex="-1">Token 的携带方式 <a class="header-anchor" href="#token-的携带方式" aria-label="Permalink to &quot;Token 的携带方式&quot;">&ZeroWidthSpace;</a></h4>
<ol>
<li>
<p><strong>HTTP Header</strong></p>
<ul>
<li>
<p>最常用的方法是在请求头中携带 Token，通常使用 <code>Authorization</code> 头。</p>
</li>
<li>
<p>示例代码：</p>
<div class="language-javascript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">javascript复制代码</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 使用 Fetch API 发送请求</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'https://api.example.com/data'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    method: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'GET'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    headers: {</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">        'Authorization'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'Bearer '</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> +</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> token</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">then</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">response</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> response.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">json</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">())</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">then</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">data</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(data));</span></span></code></pre>
</div></li>
</ul>
</li>
<li>
<p><strong>URL 参数</strong></p>
<ul>
<li>一般不推荐，因为 URL 参数容易泄露和被篡改。</li>
</ul>
</li>
<li>
<p><strong>Cookie</strong></p>
<ul>
<li>在请求时，浏览器会自动携带符合条件的 Cookie。</li>
<li>需要确保 Cookie 设置了 Secure、HttpOnly 和 SameSite 属性。</li>
</ul>
</li>
</ol>
<h3 id="安全性考虑" tabindex="-1">安全性考虑 <a class="header-anchor" href="#安全性考虑" aria-label="Permalink to &quot;安全性考虑&quot;">&ZeroWidthSpace;</a></h3>
<h4 id="防范-xss-攻击" tabindex="-1">防范 XSS 攻击 <a class="header-anchor" href="#防范-xss-攻击" aria-label="Permalink to &quot;防范 XSS 攻击&quot;">&ZeroWidthSpace;</a></h4>
<ul>
<li><strong>内容安全策略（CSP）</strong>：通过 CSP 限制加载的脚本和资源来源，减少 XSS 攻击的风险。</li>
<li><strong>输入验证</strong>：对所有用户输入进行严格的验证和过滤，防止恶意代码注入。</li>
</ul>
<h4 id="防范-csrf-攻击" tabindex="-1">防范 CSRF 攻击 <a class="header-anchor" href="#防范-csrf-攻击" aria-label="Permalink to &quot;防范 CSRF 攻击&quot;">&ZeroWidthSpace;</a></h4>
<ul>
<li><strong>SameSite Cookie 属性</strong>：设置为 <code>Strict</code> 或 <code>Lax</code>，限制跨站请求。</li>
<li><strong>CSRF Token</strong>：为每个请求生成一个唯一的 CSRF Token，并验证 Token 的有效性。</li>
</ul>
<h4 id="防止-token-泄露" tabindex="-1">防止 Token 泄露 <a class="header-anchor" href="#防止-token-泄露" aria-label="Permalink to &quot;防止 Token 泄露&quot;">&ZeroWidthSpace;</a></h4>
<ul>
<li><strong>HTTPS 加密</strong>：确保所有 Token 传输都通过 HTTPS，加密传输的数据。</li>
<li><strong>限制 Token 使用</strong>：设置 Token 的作用域和权限，最小化 Token 被滥用的风险。</li>
<li><strong>定期更新 Token</strong>：定期刷新和更新 Token，减少长期暴露的风险。</li>
</ul>
<h2 id="ssl-tls-证书的设置和申请" tabindex="-1">SSL/TLS 证书的设置和申请 <a class="header-anchor" href="#ssl-tls-证书的设置和申请" aria-label="Permalink to &quot;SSL/TLS 证书的设置和申请&quot;">&ZeroWidthSpace;</a></h2>
<p><strong>什么是 SSL/TLS 证书</strong></p>
<ul>
<li><strong>SSL/TLS 证书</strong>：是一种数字证书，用于验证服务器的身份，并在客户端和服务器之间建立安全的加密连接。</li>
<li><strong>证书内容</strong>：包括服务器的公钥、服务器身份信息、证书签发机构（CA）的签名等。</li>
</ul>
<p><strong>SSL/TLS 证书的类型</strong></p>
<ul>
<li><strong>自签名证书</strong>：由自己签发的证书，适合测试或内部使用，但不适合公众访问的站点，因为它不受信任的 CA 机构的签名。</li>
<li><strong>由可信 CA 签发的证书</strong>：由公共信任的证书颁发机构（如 Let's Encrypt、DigiCert 等）签发，适合公开访问的站点。</li>
</ul>
<p><strong>如何申请 SSL/TLS 证书</strong></p>
<p><strong>申请免费证书（例如 Let's Encrypt）</strong>：</p>
<ol>
<li><strong>选择证书颁发机构（CA）</strong>：例如 Let's Encrypt，它提供免费的 SSL/TLS 证书。</li>
<li><strong>安装证书管理工具</strong>：例如 Certbot，这是一个常用的自动化工具，用于申请和管理 Let's Encrypt 证书。</li>
<li><strong>生成和配置证书</strong>：
<ul>
<li>运行 Certbot 并按照指示生成证书。</li>
<li>配置 Web 服务器（如 Apache 或 Nginx）使用生成的证书。</li>
</ul>
</li>
</ol>
]]></content>
        <author>
            <name>duyl328</name>
            <uri>https://seyl.me/about</uri>
        </author>
        <category label="编程"/>
        <category label="想法"/>
        <category label="Blog"/>
        <category label="原创"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[主流网站主页布局展示内容及渲染方式调研]]></title>
        <id>https://seyl.me/posts/2024/08/website-homepage-layout-display</id>
        <link href="https://seyl.me/posts/2024/08/website-homepage-layout-display"/>
        <updated>2023-08-03T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[<h1 id="frontmatter-title" tabindex="-1">{{ $frontmatter.title }} <a class="header-anchor" href="#frontmatter-title" aria-label="Permalink to &quot;{{ $frontmatter.title }}&quot;">&ZeroWidthSpace;</a></h1>
<p>对于大部分信息展示网站中都是通过大块的区域内容展示来展现更多信息，并且国内的对应的网站相对较老，所以UI设计以及UI风格上更加的质朴</p>
<p>如：
![[../../../public/posts/2024/08/10002/image-20240709144917869.webp]]</p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709145013421.webp" alt="image-20240709145013421"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709145115262.webp" alt="image-20240709145115262"></p>
<p>根据几个常见的网址论坛可以看出，对于信息的展示主要通过以下几种方式：</p>
<h2 id="标签-板块" tabindex="-1"><strong>标签（板块）</strong> <a class="header-anchor" href="#标签-板块" aria-label="Permalink to &quot;**标签（板块）**&quot;">&ZeroWidthSpace;</a></h2>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709150825480.webp" alt="image-20240709150825480"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709151217902.webp" alt="image-20240709151217902"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709151251709.webp" alt="image-20240709151251709"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709151345083.webp" alt="image-20240709151345083"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709151437319.webp" alt="image-20240709151437319"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709151552809.webp" alt="image-20240709151552809"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709151640633.webp" alt="image-20240709151640633"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709151839807.webp" alt="image-20240709151839807"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709151858347.webp" alt="image-20240709151858347"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709151925258.webp" alt="image-20240709151925258"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709151949506.webp" alt="image-20240709151949506"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709152145202.webp" alt="image-20240709152145202"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709152228527.webp" alt="image-20240709152228527"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709152344199.webp" alt="image-20240709152344199"></p>
<p>大多数论坛网站中在主页显眼位置，主要方便用户快速进入不同的模块或专题，将网站的主要内容和业务展示到用户最先注意到的范围内。</p>
<h2 id="轮播图" tabindex="-1">轮播图 <a class="header-anchor" href="#轮播图" aria-label="Permalink to &quot;轮播图&quot;">&ZeroWidthSpace;</a></h2>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709153709220.webp" alt="image-20240709153709220"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709153737574.webp" alt="image-20240709153737574"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709153808702.webp" alt="image-20240709153808702"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709153845136.webp" alt="image-20240709153845136"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709153901153.webp" alt="image-20240709153901153"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709153924475.webp" alt="image-20240709153924475"></p>
<p>相对于在通过标签直接进行展示，轮播图的使用在整体调研的网站中占比较低，并且多为较为老旧的UI，并且现在的大环境下用户只想了解希望得到的信息，找到目标信息后，点击查看，得到想要的信息，离开网站。</p>
<p>所以相对来说目前轮播图所能传递给用户的信息相对比较有限，可以不用于主要信息的展示</p>
<h2 id="排行-热门" tabindex="-1">排行（热门） <a class="header-anchor" href="#排行-热门" aria-label="Permalink to &quot;排行（热门）&quot;">&ZeroWidthSpace;</a></h2>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709171101927.webp" alt="image-20240709171101927"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709171148293.webp" alt="image-20240709171148293"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709171249182.webp" alt="image-20240709171249182"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709171310667.webp" alt="image-20240709171310667"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709171406819.webp" alt="image-20240709171406819"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709171423701.webp" alt="image-20240709171423701"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709171439358.webp" alt="image-20240709171439358"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709171502006.webp" alt="image-20240709171502006"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709171529013.webp" alt="image-20240709171529013"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709171610508.webp" alt="image-20240709171610508"></p>
<p>最新、最近回复、热门、精选、排行</p>
<p>这三个功能几乎是目前所有主流的信息展示平台都会具有的功能，通过用户<code>只希望获取有用信息</code>的信息，通过各种各样的排行来诱导用户点击、评论、停留</p>
<p>所以可以在模块中增加该功能</p>
<h2 id="实时新闻-信息" tabindex="-1">实时新闻（信息） <a class="header-anchor" href="#实时新闻-信息" aria-label="Permalink to &quot;实时新闻（信息）&quot;">&ZeroWidthSpace;</a></h2>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709172705194.webp" alt="image-20240709172705194"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709172741964.webp" alt="image-20240709172741964"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709182327709.webp" alt="image-20240709182327709"></p>
<p>在大多数网站中该内容反而并不常见，可能对于论坛平台，更多的是需要有效的信息，而不是新的信息</p>
<h2 id="推荐文章流" tabindex="-1">推荐文章流 <a class="header-anchor" href="#推荐文章流" aria-label="Permalink to &quot;推荐文章流&quot;">&ZeroWidthSpace;</a></h2>
<p>这几乎是所有论坛中一定会有，而且是必须要有的功能，如果要列出来的话，目前所调研的网站都有该功能，主要区别在于不同的网站对于信息展示的理解</p>
<p>主要分为以下几种展示方式：</p>
<h3 id="列表形式" tabindex="-1">列表形式 <a class="header-anchor" href="#列表形式" aria-label="Permalink to &quot;列表形式&quot;">&ZeroWidthSpace;</a></h3>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709182940316.webp" alt="image-20240709182940316"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709183028747.webp" alt="image-20240709183028747"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709183038648.webp" alt="image-20240709183038648"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709183047905.webp" alt="image-20240709183047905"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709183111554.webp" alt="image-20240709183111554"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709183434347.webp" alt="image-20240709183434347"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709183450074.webp" alt="image-20240709183450074"></p>
<h3 id="列表形式-展示更多信息" tabindex="-1">列表形式（展示更多信息） <a class="header-anchor" href="#列表形式-展示更多信息" aria-label="Permalink to &quot;列表形式（展示更多信息）&quot;">&ZeroWidthSpace;</a></h3>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709183221209.webp" alt="image-20240709183221209"></p>
]]></summary>
        <content type="html"><![CDATA[<h1 id="frontmatter-title" tabindex="-1">{{ $frontmatter.title }} <a class="header-anchor" href="#frontmatter-title" aria-label="Permalink to &quot;{{ $frontmatter.title }}&quot;">&ZeroWidthSpace;</a></h1>
<p>对于大部分信息展示网站中都是通过大块的区域内容展示来展现更多信息，并且国内的对应的网站相对较老，所以UI设计以及UI风格上更加的质朴</p>
<p>如：
![[../../../public/posts/2024/08/10002/image-20240709144917869.webp]]</p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709145013421.webp" alt="image-20240709145013421"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709145115262.webp" alt="image-20240709145115262"></p>
<p>根据几个常见的网址论坛可以看出，对于信息的展示主要通过以下几种方式：</p>
<h2 id="标签-板块" tabindex="-1"><strong>标签（板块）</strong> <a class="header-anchor" href="#标签-板块" aria-label="Permalink to &quot;**标签（板块）**&quot;">&ZeroWidthSpace;</a></h2>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709150825480.webp" alt="image-20240709150825480"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709151217902.webp" alt="image-20240709151217902"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709151251709.webp" alt="image-20240709151251709"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709151345083.webp" alt="image-20240709151345083"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709151437319.webp" alt="image-20240709151437319"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709151552809.webp" alt="image-20240709151552809"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709151640633.webp" alt="image-20240709151640633"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709151839807.webp" alt="image-20240709151839807"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709151858347.webp" alt="image-20240709151858347"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709151925258.webp" alt="image-20240709151925258"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709151949506.webp" alt="image-20240709151949506"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709152145202.webp" alt="image-20240709152145202"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709152228527.webp" alt="image-20240709152228527"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709152344199.webp" alt="image-20240709152344199"></p>
<p>大多数论坛网站中在主页显眼位置，主要方便用户快速进入不同的模块或专题，将网站的主要内容和业务展示到用户最先注意到的范围内。</p>
<h2 id="轮播图" tabindex="-1">轮播图 <a class="header-anchor" href="#轮播图" aria-label="Permalink to &quot;轮播图&quot;">&ZeroWidthSpace;</a></h2>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709153709220.webp" alt="image-20240709153709220"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709153737574.webp" alt="image-20240709153737574"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709153808702.webp" alt="image-20240709153808702"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709153845136.webp" alt="image-20240709153845136"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709153901153.webp" alt="image-20240709153901153"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709153924475.webp" alt="image-20240709153924475"></p>
<p>相对于在通过标签直接进行展示，轮播图的使用在整体调研的网站中占比较低，并且多为较为老旧的UI，并且现在的大环境下用户只想了解希望得到的信息，找到目标信息后，点击查看，得到想要的信息，离开网站。</p>
<p>所以相对来说目前轮播图所能传递给用户的信息相对比较有限，可以不用于主要信息的展示</p>
<h2 id="排行-热门" tabindex="-1">排行（热门） <a class="header-anchor" href="#排行-热门" aria-label="Permalink to &quot;排行（热门）&quot;">&ZeroWidthSpace;</a></h2>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709171101927.webp" alt="image-20240709171101927"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709171148293.webp" alt="image-20240709171148293"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709171249182.webp" alt="image-20240709171249182"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709171310667.webp" alt="image-20240709171310667"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709171406819.webp" alt="image-20240709171406819"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709171423701.webp" alt="image-20240709171423701"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709171439358.webp" alt="image-20240709171439358"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709171502006.webp" alt="image-20240709171502006"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709171529013.webp" alt="image-20240709171529013"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709171610508.webp" alt="image-20240709171610508"></p>
<p>最新、最近回复、热门、精选、排行</p>
<p>这三个功能几乎是目前所有主流的信息展示平台都会具有的功能，通过用户<code>只希望获取有用信息</code>的信息，通过各种各样的排行来诱导用户点击、评论、停留</p>
<p>所以可以在模块中增加该功能</p>
<h2 id="实时新闻-信息" tabindex="-1">实时新闻（信息） <a class="header-anchor" href="#实时新闻-信息" aria-label="Permalink to &quot;实时新闻（信息）&quot;">&ZeroWidthSpace;</a></h2>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709172705194.webp" alt="image-20240709172705194"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709172741964.webp" alt="image-20240709172741964"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709182327709.webp" alt="image-20240709182327709"></p>
<p>在大多数网站中该内容反而并不常见，可能对于论坛平台，更多的是需要有效的信息，而不是新的信息</p>
<h2 id="推荐文章流" tabindex="-1">推荐文章流 <a class="header-anchor" href="#推荐文章流" aria-label="Permalink to &quot;推荐文章流&quot;">&ZeroWidthSpace;</a></h2>
<p>这几乎是所有论坛中一定会有，而且是必须要有的功能，如果要列出来的话，目前所调研的网站都有该功能，主要区别在于不同的网站对于信息展示的理解</p>
<p>主要分为以下几种展示方式：</p>
<h3 id="列表形式" tabindex="-1">列表形式 <a class="header-anchor" href="#列表形式" aria-label="Permalink to &quot;列表形式&quot;">&ZeroWidthSpace;</a></h3>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709182940316.webp" alt="image-20240709182940316"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709183028747.webp" alt="image-20240709183028747"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709183038648.webp" alt="image-20240709183038648"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709183047905.webp" alt="image-20240709183047905"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709183111554.webp" alt="image-20240709183111554"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709183434347.webp" alt="image-20240709183434347"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709183450074.webp" alt="image-20240709183450074"></p>
<h3 id="列表形式-展示更多信息" tabindex="-1">列表形式（展示更多信息） <a class="header-anchor" href="#列表形式-展示更多信息" aria-label="Permalink to &quot;列表形式（展示更多信息）&quot;">&ZeroWidthSpace;</a></h3>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709183221209.webp" alt="image-20240709183221209"></p>
<hr>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709183238714.webp" alt="image-20240709183238714"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709183253255.webp" alt="image-20240709183253255"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709183308255.webp" alt="image-20240709183308255"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709183338467.webp" alt="image-20240709183338467"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709183348910.webp" alt="image-20240709183348910"></p>
<h3 id="问答形式" tabindex="-1">问答形式 <a class="header-anchor" href="#问答形式" aria-label="Permalink to &quot;问答形式&quot;">&ZeroWidthSpace;</a></h3>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709183409479.webp" alt="image-20240709183409479"></p>
<h3 id="卡片形式" tabindex="-1">卡片形式 <a class="header-anchor" href="#卡片形式" aria-label="Permalink to &quot;卡片形式&quot;">&ZeroWidthSpace;</a></h3>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709183321435.webp" alt="image-20240709183321435"></p>
<h3 id="预览形式" tabindex="-1">预览形式 <a class="header-anchor" href="#预览形式" aria-label="Permalink to &quot;预览形式&quot;">&ZeroWidthSpace;</a></h3>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709183144841.webp" alt="image-20240709183144841"></p>
<p><img src="./../../../public/posts/2024/08/10002/image-20240709183507358.webp" alt="image-20240709183507358"></p>
<p>综合已经搜索到的信息来看，信息的展示通过内容的不同，也有不同的展示方式，大部分使用的是列表形式，并且尽量展示少的正文，而是主要展示标题（可能这种方式可以增加点击率吧）</p>
<p>而对于文章，主要以传递信息为主，尽可能需要用户直接可以看到一个内容的主要或大致内容，增加阅读效率，所以大多采用<code>预览形式</code></p>
<p>如果对于一些问题的来说，更多的是采用问答的形式，比如比较著名的<code>StackOverflow</code>
，根据用户的回答，其他用户可以对每个回答进行评分，当新用户看到该内容是，可以更加直观了解到有多少种解决方式，并找到最推荐的解决方式。</p>
<p>对于不同的信息展示形式，我认为都可以采用，对于不同的模块采用不同的展示形式，不同的展示形式在不同的信息时可以体现出不同的优势</p>
<h2 id="这些网站所使用的技术" tabindex="-1">这些网站所使用的技术 <a class="header-anchor" href="#这些网站所使用的技术" aria-label="Permalink to &quot;这些网站所使用的技术&quot;">&ZeroWidthSpace;</a></h2>
<p>无论是对于这些论坛网站还是那些炫酷的网站，主要使用的语言包括</p>
<table>
<thead>
<tr>
<th>所使用的技术</th>
<th>使用的网站数量</th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>Vue</td>
<td>10</td>
<td></td>
</tr>
<tr>
<td>Nuxt</td>
<td>19</td>
<td></td>
</tr>
<tr>
<td>React</td>
<td>8</td>
<td></td>
</tr>
<tr>
<td>Nextjs</td>
<td>6</td>
<td></td>
</tr>
<tr>
<td>其他（Jquery，Threejs，WordPress等）</td>
<td>29</td>
<td></td>
</tr>
</tbody>
</table>
<ul>
<li>如果同时使用两种技术如：Nuxt和Vue，则认为是Nuxt，不重复统计</li>
</ul>
<p>目前来看<code>Nuxt</code>在一种开发语言中也占有一席之地，并且效果也很不错，但是在比较新的网站中如：<code>OpenAi</code>等使用Ntxtjs较多。</p>
<h2 id="总结" tabindex="-1">总结 <a class="header-anchor" href="#总结" aria-label="Permalink to &quot;总结&quot;">&ZeroWidthSpace;</a></h2>
<p>针对目前的调研来看，信息的展示形式，主页面和信息页面的展示是相对比较主要的内容，对于他们的排版都可以借鉴</p>
<p>但我们目标并不是为了一个单一的用户服务，而是保罗万象，我们无法考虑到所有的模块，所以考虑像<code>豆瓣小组</code>
那种，让用户来创建对应的板块，根据板块的不同来对每个板块进行单独的优化。</p>
<p>现在无论是大站还是小站，只有一个样式或风格，无论是教程、博客、求助等等帖子都以同一种形式渲染；游戏模块、博客模块、教程模块等同样采用单一的排版布局，同一套样式布局。</p>
<p>我们可以解决这个问题，针对不同的板块提供不同的模板：</p>
<ul>
<li>
<p>比如游戏模块可以提供背景图、轮播切换、所有元素替换为该游戏的风格；</p>
</li>
<li>
<p>对于博客模块可以对文章的渲染进行单独的优化，比如更加统一的排版、提供阅读清屏功能、屏蔽所有图片等功能；</p>
</li>
<li>
<p>对于摸鱼模块，提供每日新闻展示、热门主题展示等功能</p>
</li>
</ul>
<p><strong>板块</strong>和<strong>板块</strong>之间有用独立的配置和渲染效果，但是对于主页面，则采用更加简单更加现代化的布局展示，只有当进入不同的模块时才会有不同的渲染效果。</p>
<blockquote>
<p>就像是一个商场，有的是服装店，那么他就有他独有的海报；对于酒馆，那就可以给他加更加应景的彩虹氛围灯；对于饭店，可以提供更大的位置，让他可以容纳更多食客</p>
</blockquote>
<p>并且提供不同的模板后，在后期的维护中只需通过模板的改变就可以调整整体的功能或布局，而不用直接修改代码。但是相对的这会带来非常多的开发量。</p>
<h2 id="参考的网站列表" tabindex="-1">参考的网站列表： <a class="header-anchor" href="#参考的网站列表" aria-label="Permalink to &quot;参考的网站列表：&quot;">&ZeroWidthSpace;</a></h2>
<ul>
<li><a href="https://edifis.ca/en/" target="_blank" rel="noreferrer">https://edifis.ca/en/</a></li>
<li><a href="https://discoverybuildersllc.com/" target="_blank" rel="noreferrer">https://discoverybuildersllc.com/</a></li>
<li><a href="https://dgrees.studio/" target="_blank" rel="noreferrer">https://dgrees.studio/</a></li>
<li><a href="https://codeam.nl/" target="_blank" rel="noreferrer">https://codeam.nl/</a></li>
<li><a href="https://lefruitstudio.fr/en/" target="_blank" rel="noreferrer">https://lefruitstudio.fr/en/</a></li>
<li><a href="https://sandclock.madebyburo.com/" target="_blank" rel="noreferrer">https://sandclock.madebyburo.com/</a></li>
<li><a href="https://euphemia.com/" target="_blank" rel="noreferrer">https://euphemia.com/</a></li>
<li><a href="https://hotelodisej.com/" target="_blank" rel="noreferrer">https://hotelodisej.com/</a></li>
<li><a href="https://www.teamgeek.io/" target="_blank" rel="noreferrer">https://www.teamgeek.io/</a></li>
<li><a href="https://nicolasloureiro.com/" target="_blank" rel="noreferrer">https://nicolasloureiro.com/</a></li>
<li><a href="https://kentatoshikura.com/" target="_blank" rel="noreferrer">https://kentatoshikura.com/</a></li>
<li><a href="https://yoshikiokamura.art/" target="_blank" rel="noreferrer">https://yoshikiokamura.art/</a></li>
<li><a href="https://kacper.ch/" target="_blank" rel="noreferrer">https://kacper.ch/</a></li>
<li><a href="https://2022.ccncn.eu/" target="_blank" rel="noreferrer">https://2022.ccncn.eu/</a></li>
<li><a href="https://www.wedesigndemand.com/" target="_blank" rel="noreferrer">https://www.wedesigndemand.com/</a></li>
<li><a href="https://plantica.net/" target="_blank" rel="noreferrer">https://plantica.net/</a></li>
<li><a href="https://www.dashq.io/" target="_blank" rel="noreferrer">https://www.dashq.io/</a></li>
<li><a href="https://www.artsphere.fr/" target="_blank" rel="noreferrer">https://www.artsphere.fr/</a></li>
<li><a href="https://the-haircut.webflow.io/" target="_blank" rel="noreferrer">https://the-haircut.webflow.io/</a></li>
<li><a href="https://hub.crunchdao.com/auth/register" target="_blank" rel="noreferrer">https://hub.crunchdao.com/auth/register</a></li>
<li><a href="https://www.heights.agency/" target="_blank" rel="noreferrer">https://www.heights.agency/</a></li>
<li><a href="https://www.kirschberg.co.nz/work" target="_blank" rel="noreferrer">https://www.kirschberg.co.nz/work</a></li>
<li><a href="https://deidredriscoll.com/" target="_blank" rel="noreferrer">https://deidredriscoll.com/</a></li>
<li><a href="https://andpost.jp/" target="_blank" rel="noreferrer">https://andpost.jp/</a></li>
<li><a href="https://aoba-kaikei.net/" target="_blank" rel="noreferrer">https://aoba-kaikei.net/</a></li>
<li><a href="https://orf.sfc.keio.ac.jp/2019/" target="_blank" rel="noreferrer">https://orf.sfc.keio.ac.jp/2019/</a></li>
<li><a href="https://www.sj33.cn/digital/wysj/202003/52607.html" target="_blank" rel="noreferrer">https://www.sj33.cn/digital/wysj/202003/52607.html</a></li>
<li><a href="https://wickret.cuberto.com/" target="_blank" rel="noreferrer">https://wickret.cuberto.com/</a></li>
<li><a href="https://www.hellomonday.com/" target="_blank" rel="noreferrer">https://www.hellomonday.com/</a></li>
<li><a href="https://www.wecargo.be/" target="_blank" rel="noreferrer">https://www.wecargo.be/</a></li>
<li><a href="https://www.nikolastype.com/" target="_blank" rel="noreferrer">https://www.nikolastype.com/</a></li>
<li><a href="https://dennisberti.com/" target="_blank" rel="noreferrer">https://dennisberti.com/</a></li>
<li><a href="https://boy-coy.com/#contact" target="_blank" rel="noreferrer">https://boy-coy.com/#contact</a></li>
<li><a href="https://int.pez.com/Geschichte/" target="_blank" rel="noreferrer">https://int.pez.com/Geschichte/</a></li>
<li><a href="https://www.discourse.org/#" target="_blank" rel="noreferrer">https://www.discourse.org/#</a></li>
<li><a href="https://www.resetera.com/" target="_blank" rel="noreferrer">https://www.resetera.com/</a></li>
<li><a href="https://dribbble.com/" target="_blank" rel="noreferrer">https://dribbble.com/</a></li>
<li><a href="https://www.discourse.org/customers" target="_blank" rel="noreferrer">https://www.discourse.org/customers</a></li>
<li><a href="https://heydaystudio.fr/" target="_blank" rel="noreferrer">https://heydaystudio.fr/</a></li>
<li><a href="https://tilda.cc/cn/" target="_blank" rel="noreferrer">https://tilda.cc/cn/</a></li>
<li><a href="https://moreair.co/" target="_blank" rel="noreferrer">https://moreair.co/</a></li>
<li><a href="https://coolors.co/palettes/popular/bold" target="_blank" rel="noreferrer">https://coolors.co/palettes/popular/bold</a></li>
<li><a href="https://joshcollinsworth.com/" target="_blank" rel="noreferrer">https://joshcollinsworth.com/</a></li>
<li><a href="https://andrevv.com/" target="_blank" rel="noreferrer">Andrew McCarthy - Creative Developer &amp; Designer, San Diego ✍</a></li>
<li><a href="http://kylethacker.com/" target="_blank" rel="noreferrer">Kyle Thacker — 设计师</a></li>
<li><a href="https://jimramsden.com/" target="_blank" rel="noreferrer">Jim Ramsden - Designer of Internets</a></li>
<li><a href="https://www.thisisveryrude.com/" target="_blank" rel="noreferrer">Shannon Lim</a></li>
<li><a href="https://www.pilot-republic.space/" target="_blank" rel="noreferrer">Advanced career for pilots on a Global Scale</a></li>
<li><a href="https://ang-studio.com/" target="_blank" rel="noreferrer">Ang Studio®</a></li>
<li><a href="https://des.obys.agency/" target="_blank" rel="noreferrer">DES® | Design Education Series® by Obys®</a></li>
<li><a href="https://piloteparis.com/" target="_blank" rel="noreferrer">PILOTE PARIS</a></li>
<li><a href="https://www.outsidersfund.com/" target="_blank" rel="noreferrer">Outsiders Fund</a></li>
<li><a href="https://ddd.live/" target="_blank" rel="noreferrer">Digital Design Days - Milan - 6-8 October 2024</a></li>
<li><a href="https://bizar.ro/" target="_blank" rel="noreferrer">Luis Bizarro - Creative Technologist</a></li>
<li><a href="https://www.stormprod.fr/" target="_blank" rel="noreferrer">Accueil - Storm Prod</a></li>
<li><a href="https://spaace.io/" target="_blank" rel="noreferrer">Spaace | NFT Marketplace</a></li>
<li><a href="https://daylightcomputer.com/" target="_blank" rel="noreferrer">Daylight | A More Caring Computer</a></li>
<li><a href="https://heydaystudio.fr/" target="_blank" rel="noreferrer">Heyday Studio — Creative Studio, Branding &amp; Places, Toulouse</a></li>
<li><a href="https://evasanchez.info/" target="_blank" rel="noreferrer">Eva Sánchez - Interactive Designer</a></li>
<li><a href="https://www.justgowiththeflow.com/" target="_blank" rel="noreferrer">Flow/Digital Production House</a></li>
<li><a href="https://www.oscarpico.es/project-page/viadomo-deco" target="_blank" rel="noreferrer">Oscar Pico — Digital Designer</a></li>
<li><a href="https://augen.pro/" target="_blank" rel="noreferrer">Augen — Pro Human</a></li>
<li><a href="https://sparkk.fr/en" target="_blank" rel="noreferrer">SPARKK | Web Agency and Website Creation in Nantes</a></li>
<li><a href="https://legendary3310.tilda.ws/en" target="_blank" rel="noreferrer">诺基亚 3310 eng</a></li>
<li><a href="https://www.ronin161.com/" target="_blank" rel="noreferrer">Ronin161 - D I G I T A L . G A N G</a></li>
<li><a href="https://trionn.com/" target="_blank" rel="noreferrer">TRIONN | Crafting Award-Winning Digital Journeys.</a></li>
<li><a href="https://pontheonlinestore.com/" target="_blank" rel="noreferrer">Pon The Store</a></li>
<li><a href="https://tilda.cc/cn/" target="_blank" rel="noreferrer">创建无偿的网站. 介绍TILDA PUBLISHING网站建设者</a></li>
<li><a href="https://whoer.net/zh" target="_blank" rel="noreferrer">检查您自己的IP地址和DNS地址</a></li>
<li><a href="https://www.gamer520.com/pcgame" target="_blank" rel="noreferrer">PC游戏下载|PC破解游戏资源下载</a></li>
<li><a href="http://requestbin.cn/" target="_blank" rel="noreferrer">RequestBin — Collect, inspect and debug HTTP requests and webhooks</a></li>
<li><a href="https://osawards.com/javascript/2023" target="_blank" rel="noreferrer">JavaScript Open Source Awards - GitNation</a></li>
<li><a href="https://next.itellyou.cn/Original/Index?id=7ab5f0cb-7607-4bbe-9e88-50716dc43de6#" target="_blank" rel="noreferrer">我告诉你</a></li>
</ul>
]]></content>
        <author>
            <name>duyl328</name>
            <uri>https://seyl.me/about</uri>
        </author>
        <category label="设计"/>
        <category label="Blog"/>
        <category label="原创"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[JavaScript和Vue中实现表格(table)固定表头和首列]]></title>
        <id>https://seyl.me/posts/2022/08/fixed-table-header-and-first-column-in-javascript</id>
        <link href="https://seyl.me/posts/2022/08/fixed-table-header-and-first-column-in-javascript"/>
        <updated>2022-08-26T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[<h1 id="frontmatter-title" tabindex="-1">{{ $frontmatter.title }} <a class="header-anchor" href="#frontmatter-title" aria-label="Permalink to &quot;{{ $frontmatter.title }}&quot;">&ZeroWidthSpace;</a></h1>
<blockquote>
<p>✒️ 文章摘要</p>
</blockquote>
<!-- DESC SEP -->
<p>这篇文章介绍了如何在 JS 或 Vue 中实现表格的列和表头固定功能，适用于不同的开发环境（如原生
JavaScript、Vue、React、小程序等）。文章详细展示了实现这一功能的思路和具体步骤，包括使用 Vue3 和 TypeScript 结合 Less
来完成样式和功能的实现。</p>
<!-- DESC SEP -->
<h2 id="写在前面" tabindex="-1">写在前面 <a class="header-anchor" href="#写在前面" aria-label="Permalink to &quot;写在前面&quot;">&ZeroWidthSpace;</a></h2>
<p>本文主要介绍关于<code>JS</code>或<code>Vue</code>中如何进行表头，列固定，可以根据实际应用场景应用于<code>原生</code>，<code>Vue</code>，<code>移动端</code>，<code>小程序</code>中</p>
<p>实际效果展示：</p>
<p><img src="./../../../public/posts/2022/08/img-1.gif" alt="在这里插入图片描述"></p>
<h2 id="思路概述" tabindex="-1">思路概述 <a class="header-anchor" href="#思路概述" aria-label="Permalink to &quot;思路概述&quot;">&ZeroWidthSpace;</a></h2>
<p><code>表头，列头，表格本身，这三个内容被分为了三块元素，将这三个内容进行抽离，并且通过定位和大盒子的包裹进行样式管理。</code></p>
<p>【当要进行滚动时，只要对滚动事件进行绑定，让<code>表头和列头显示对应的内容就完成了滚动的操作</code>】</p>
<p>下面有<code>Vue</code>组件的和<code>JavaScript</code>原生的代码，可以直接运行查看逻辑和效果</p>
<h2 id="具体实现" tabindex="-1">具体实现 <a class="header-anchor" href="#具体实现" aria-label="Permalink to &quot;具体实现&quot;">&ZeroWidthSpace;</a></h2>
<p>整体代码，<code>可以直接创建组件，将代码复制到组件中使用</code>，在<code>App</code>中引用运行【基于<code>vue3+ts+less</code>实现，其他版本会在后面给出修改思路】
<code>【最下面也提供了原生写法】</code></p>
<div class="language-html vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">html</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">&#x3C;!--</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  ~ Time:2022/8/9 13:06 29</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  ~ Name:fixmeTable.vue</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  ~ Path:src/components/table</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  ~ ProjectName:element-plus</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  ~ Author:charlatan</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  ~</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  ~  Il n'ya qu'un héroïsme au monde :</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  ~     c'est de voir le monde tel qu'il est et de l'aimer.</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  --></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">script</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> lang</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"ts"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> setup</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">	import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { ref } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'vue'</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">	const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> row</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 20</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">	const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> column</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 30</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">	let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> top </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ref</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'0px'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">	let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> left </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ref</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'0px'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">	const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Scroll</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">event</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Event</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		top.value </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> -</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">event.target.scrollTop </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'px'</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		left.value </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> -</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">event.target.scrollLeft </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'px'</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">script</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">template</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">h3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		列头表头固定table</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">h3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">hr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">	&#x3C;!--  表格--></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"table"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">		&#x3C;!--    表头--></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"rowHeader"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">			&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">table</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"rowHeader-table"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">				&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">tr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">					&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">td</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"td"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> v-for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"(item,index) in row"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> :key</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"index"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">						{{ item }}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">					&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">td</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">				&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">tr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">			&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">table</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">		&#x3C;!--    列头--></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"columnHeader"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">			&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">table</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"columnHeader-table"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">				&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">tr</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> v-for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"(RootItem,index) in column"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> :key</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"index"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">					&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">td</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"td"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">						{{ String.fromCharCode(RootItem + 64) }}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">					&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">td</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">				&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">tr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">			&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">table</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">		&#x3C;!--    表格--></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"tableBody"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> @scroll</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Scroll($event)"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">			&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">table</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"tableBody-table"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">				&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">tr</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> v-for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"(RootItem,index) in column"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> :key</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"index"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">					&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">td</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">							class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"td"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> v-for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"(item,index) in row"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> :key</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"index"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">						{{ item + String.fromCharCode(RootItem + 64) }}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">					&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">td</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">				&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">tr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">			&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">table</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">template</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">style</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> scoped</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> lang</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"less"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">	.table</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		border</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> solid</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> red</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		padding</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">rem</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		border-radius</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">rem</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		position</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">absolute</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		left</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">200</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		top</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">300</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		height</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">300</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	/ / 表头 . </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">rowHeader</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		position</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">relative</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">260</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		max-width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">300</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		overflow</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">hidden</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		left</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">30</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">rowHeader-table</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			position</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">relative</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			left</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: v-bind(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">left</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">fit-content</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	} / / 列头 . columnHeader {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		position</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">relative</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		max-height</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">300</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		overflow</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">hidden</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">30</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		top</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">columnHeader-table</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			position</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">relative</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			top</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: v-bind(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">top</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	} / / 表格本体 . tableBody {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">265</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		height</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">300</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		position</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">absolute</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		top</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">55</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		left</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">50</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		overflow</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">auto</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	} / / 表格元素 </span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">tr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">fit-content</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		white-space</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">normal</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		display</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">flex</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">td</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			display</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">block</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">30</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			height</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">30</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			text-align</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">center</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			line-height</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">30</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">style</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span></code></pre>
</div><ol>
<li>
<p><code>html</code>部分：主要进行框架的设计，这里表头，列头，表格本体分为三份</p>
<div class="language-html vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">html</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">template</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">h3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    列头表头固定table</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  &#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">h3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">hr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  &#x3C;!--  表格--></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"table"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    &#x3C;!--    表头--></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"rowHeader"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">table</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"rowHeader-table"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">tr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">          &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">td</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"td"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> v-for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"(item,index) in row"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> :key</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"index"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            {{ item }}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">          &#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">td</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        &#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">tr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      &#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">table</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    &#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    &#x3C;!--    列头--></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"columnHeader"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">table</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"columnHeader-table"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">tr</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> v-for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"(RootItem,index) in column"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> :key</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"index"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">          &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">td</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"td"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            {{ String.fromCharCode(RootItem + 64) }}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">          &#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">td</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        &#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">tr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      &#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">table</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    &#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    &#x3C;!--    表格--></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"tableBody"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> @scroll</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Scroll($event)"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">table</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"tableBody-table"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">tr</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> v-for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"(RootItem,index) in column"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> :key</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"index"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">          &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">td</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">              class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"td"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> v-for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"(item,index) in row"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> :key</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"index"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            {{ item + String.fromCharCode(RootItem + 64) }}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">          &#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">td</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        &#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">tr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      &#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">table</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    &#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  &#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">template</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span></code></pre>
</div></li>
</ol>
<p>内容分为了三部分，这三部分将相互独立，通过样式的调节将三部分内容进行统一的管理。</p>
<p>这里使用的是<code>table</code>进行了内容的填充，因为表头和列头是单独的元素，所以可以使用其他内容如<code>div</code>等，通过样式上的和交互上的进行协调统一，这里不在赘述</p>
<ol start="2">
<li>
<p>样式上的内容，因为主要是功能，这里样式使用<code>less</code>进行简单绘制</p>
<div class="language-css vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">css</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">style</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> scoped lang="less"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">></span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">.table</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  border</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> solid</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> red</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  padding</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">rem</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  border-radius</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">rem</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  position</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">absolute</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  left</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">200</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  top</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">300</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  height</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">300</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  // 表头</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  .</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">rowHeader</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    position</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">relative</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">260</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    max-width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">300</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    overflow</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">hidden</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    left</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">30</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    .</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">rowHeader-table</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      position</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">relative</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      left</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: v-bind(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">left</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">fit-content</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  // 列头</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">  .columnHeader</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    position</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">relative</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    max-height</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">300</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    overflow</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">hidden</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">30</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    top</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    .</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">columnHeader-table</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      position</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">relative</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      top</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: v-bind(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">top</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  // 表格本体</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">  .tableBody</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">265</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    height</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">300</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    position</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">absolute</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    top</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">55</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    left</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">50</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    overflow</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">auto</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  // 表格元素</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  tr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">fit-content</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    white-space</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">normal</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    display</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">flex</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    .</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">td</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      display</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">block</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">30</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      height</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">30</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      text-align</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">center</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      line-height</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">30</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">style</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">></span></span></code></pre>
</div><p>内容上和定义的结构进行统一调节，这里需要主要的是：<span style='color:red;font-weight:900;'>
因为表格的宽度和表头的宽度对应，表格的高度和列头的高度固定，所以建议在定义时考虑好对应的宽高对应关系，方便调节</span></p>
<p>在定义好表头和列头时，对与展示的部分通过外部的<code>div</code>进行定位的调节进行展示，内部的表格部分通过宽度的固定来达到样式统一，使用相对定位来完成展示内容的切换</p>
<p>内部使用了Vue3提供的<code>v-bind</code>，如果你使用的时vue2或其他内容请更换为内联样式或其他方式</p>
<p><code>v-bind</code>
为Vue3中提供，主要是将绑定的内容转换为自定义标签使用，具体介绍可以看我的另一篇文章：<a href="https://blog.csdn.net/weixin_52235488/article/details/126290046?spm=1001.2014.3001.5502" target="_blank" rel="noreferrer">Vue3新属性 — v-bind in css</a>
，里面有用法和原理的详细介绍</p>
</li>
<li>
<p>逻辑部分：主要为内部的真正的表格绑定了滚动的监听，</p>
<div class="language-html vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">html</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">script</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> lang</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"ts"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> setup</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { ref } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'vue'</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 定义行和列</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> row</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 20</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> column</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 30</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 将内容进行响应式定义</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> top </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ref</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'0px'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> left </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ref</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'0px'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 绑定对应的监听事件</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Scroll</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">event</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Event</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  top.value </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> -</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">event.target.scrollTop </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'px'</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  left.value </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> -</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">event.target.scrollLeft </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'px'</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">script</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span></code></pre>
</div><p>这里使用的动态数据在<code>v-bind</code>中进行，这里直接修改即可</p>
</li>
</ol>
<h2 id="其他环境中要修改的内容" tabindex="-1">其他环境中要修改的内容 <a class="header-anchor" href="#其他环境中要修改的内容" aria-label="Permalink to &quot;其他环境中要修改的内容&quot;">&ZeroWidthSpace;</a></h2>
<p>这里对常见问题进行解决，如果没有匹配，请评论或找其他方式解决</p>
<ol>
<li>
<p><code>原生JavaScript中使用</code>：如果你完全没有使用过<code>Vue</code>，上面的代码我也改成了原生的版本，逻辑一样，这里就只放代码不做介绍了
<code>直接创建文件复制使用</code></p>
<div class="language-html vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">html</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">&#x3C;!--</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  ~ Time:2022/8/12 9:02 36</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  ~ Name:test1.html</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  ~ Path:</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  ~ ProjectName:element-plus</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  ~ Author:charlatan</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  ~</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  ~  Il n'ya qu'un héroïsme au monde :</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  ~     c'est de voir le monde tel qu'il est et de l'aimer.</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  --></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;!</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">DOCTYPE</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> html</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">html</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> lang</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"en"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">head</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">meta</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> charset</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"UTF-8"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">meta</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> content</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"IE=edge"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> http-equiv</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"X-UA-Compatible"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">meta</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> content</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"viewport"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">title</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>Title&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">title</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">style</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">		*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			margin</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			padding</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			list-style</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">none</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			font</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">500</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 15</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> YouYuan;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			text-decoration</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">none</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">		li</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			cursor</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">pointer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			position</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">relative</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">		/*</span></span></code></pre>
</div></li>
</ol>
]]></summary>
        <content type="html"><![CDATA[<h1 id="frontmatter-title" tabindex="-1">{{ $frontmatter.title }} <a class="header-anchor" href="#frontmatter-title" aria-label="Permalink to &quot;{{ $frontmatter.title }}&quot;">&ZeroWidthSpace;</a></h1>
<blockquote>
<p>✒️ 文章摘要</p>
</blockquote>
<!-- DESC SEP -->
<p>这篇文章介绍了如何在 JS 或 Vue 中实现表格的列和表头固定功能，适用于不同的开发环境（如原生
JavaScript、Vue、React、小程序等）。文章详细展示了实现这一功能的思路和具体步骤，包括使用 Vue3 和 TypeScript 结合 Less
来完成样式和功能的实现。</p>
<!-- DESC SEP -->
<h2 id="写在前面" tabindex="-1">写在前面 <a class="header-anchor" href="#写在前面" aria-label="Permalink to &quot;写在前面&quot;">&ZeroWidthSpace;</a></h2>
<p>本文主要介绍关于<code>JS</code>或<code>Vue</code>中如何进行表头，列固定，可以根据实际应用场景应用于<code>原生</code>，<code>Vue</code>，<code>移动端</code>，<code>小程序</code>中</p>
<p>实际效果展示：</p>
<p><img src="./../../../public/posts/2022/08/img-1.gif" alt="在这里插入图片描述"></p>
<h2 id="思路概述" tabindex="-1">思路概述 <a class="header-anchor" href="#思路概述" aria-label="Permalink to &quot;思路概述&quot;">&ZeroWidthSpace;</a></h2>
<p><code>表头，列头，表格本身，这三个内容被分为了三块元素，将这三个内容进行抽离，并且通过定位和大盒子的包裹进行样式管理。</code></p>
<p>【当要进行滚动时，只要对滚动事件进行绑定，让<code>表头和列头显示对应的内容就完成了滚动的操作</code>】</p>
<p>下面有<code>Vue</code>组件的和<code>JavaScript</code>原生的代码，可以直接运行查看逻辑和效果</p>
<h2 id="具体实现" tabindex="-1">具体实现 <a class="header-anchor" href="#具体实现" aria-label="Permalink to &quot;具体实现&quot;">&ZeroWidthSpace;</a></h2>
<p>整体代码，<code>可以直接创建组件，将代码复制到组件中使用</code>，在<code>App</code>中引用运行【基于<code>vue3+ts+less</code>实现，其他版本会在后面给出修改思路】
<code>【最下面也提供了原生写法】</code></p>
<div class="language-html vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">html</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">&#x3C;!--</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  ~ Time:2022/8/9 13:06 29</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  ~ Name:fixmeTable.vue</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  ~ Path:src/components/table</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  ~ ProjectName:element-plus</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  ~ Author:charlatan</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  ~</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  ~  Il n'ya qu'un héroïsme au monde :</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  ~     c'est de voir le monde tel qu'il est et de l'aimer.</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  --></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">script</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> lang</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"ts"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> setup</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">	import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { ref } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'vue'</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">	const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> row</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 20</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">	const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> column</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 30</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">	let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> top </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ref</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'0px'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">	let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> left </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ref</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'0px'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">	const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Scroll</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">event</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Event</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		top.value </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> -</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">event.target.scrollTop </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'px'</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		left.value </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> -</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">event.target.scrollLeft </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'px'</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">script</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">template</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">h3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		列头表头固定table</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">h3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">hr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">	&#x3C;!--  表格--></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"table"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">		&#x3C;!--    表头--></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"rowHeader"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">			&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">table</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"rowHeader-table"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">				&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">tr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">					&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">td</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"td"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> v-for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"(item,index) in row"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> :key</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"index"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">						{{ item }}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">					&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">td</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">				&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">tr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">			&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">table</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">		&#x3C;!--    列头--></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"columnHeader"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">			&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">table</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"columnHeader-table"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">				&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">tr</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> v-for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"(RootItem,index) in column"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> :key</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"index"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">					&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">td</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"td"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">						{{ String.fromCharCode(RootItem + 64) }}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">					&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">td</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">				&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">tr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">			&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">table</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">		&#x3C;!--    表格--></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"tableBody"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> @scroll</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Scroll($event)"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">			&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">table</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"tableBody-table"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">				&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">tr</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> v-for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"(RootItem,index) in column"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> :key</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"index"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">					&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">td</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">							class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"td"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> v-for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"(item,index) in row"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> :key</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"index"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">						{{ item + String.fromCharCode(RootItem + 64) }}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">					&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">td</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">				&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">tr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">			&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">table</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">template</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">style</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> scoped</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> lang</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"less"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">	.table</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		border</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> solid</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> red</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		padding</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">rem</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		border-radius</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">rem</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		position</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">absolute</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		left</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">200</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		top</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">300</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		height</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">300</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	/ / 表头 . </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">rowHeader</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		position</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">relative</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">260</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		max-width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">300</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		overflow</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">hidden</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		left</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">30</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">rowHeader-table</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			position</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">relative</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			left</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: v-bind(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">left</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">fit-content</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	} / / 列头 . columnHeader {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		position</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">relative</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		max-height</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">300</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		overflow</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">hidden</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">30</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		top</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">columnHeader-table</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			position</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">relative</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			top</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: v-bind(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">top</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	} / / 表格本体 . tableBody {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">265</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		height</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">300</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		position</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">absolute</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		top</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">55</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		left</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">50</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		overflow</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">auto</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	} / / 表格元素 </span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">tr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">fit-content</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		white-space</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">normal</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">		display</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">flex</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">td</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			display</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">block</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">30</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			height</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">30</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			text-align</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">center</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			line-height</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">30</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">style</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span></code></pre>
</div><ol>
<li>
<p><code>html</code>部分：主要进行框架的设计，这里表头，列头，表格本体分为三份</p>
<div class="language-html vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">html</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">template</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">h3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    列头表头固定table</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  &#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">h3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">hr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  &#x3C;!--  表格--></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"table"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    &#x3C;!--    表头--></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"rowHeader"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">table</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"rowHeader-table"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">tr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">          &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">td</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"td"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> v-for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"(item,index) in row"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> :key</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"index"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            {{ item }}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">          &#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">td</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        &#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">tr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      &#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">table</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    &#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    &#x3C;!--    列头--></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"columnHeader"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">table</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"columnHeader-table"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">tr</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> v-for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"(RootItem,index) in column"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> :key</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"index"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">          &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">td</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"td"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            {{ String.fromCharCode(RootItem + 64) }}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">          &#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">td</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        &#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">tr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      &#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">table</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    &#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      </span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    &#x3C;!--    表格--></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"tableBody"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> @scroll</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Scroll($event)"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">table</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"tableBody-table"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">tr</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> v-for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"(RootItem,index) in column"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> :key</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"index"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">          &#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">td</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">              class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"td"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> v-for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"(item,index) in row"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> :key</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"index"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            {{ item + String.fromCharCode(RootItem + 64) }}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">          &#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">td</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        &#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">tr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      &#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">table</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    &#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  &#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">template</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span></code></pre>
</div></li>
</ol>
<p>内容分为了三部分，这三部分将相互独立，通过样式的调节将三部分内容进行统一的管理。</p>
<p>这里使用的是<code>table</code>进行了内容的填充，因为表头和列头是单独的元素，所以可以使用其他内容如<code>div</code>等，通过样式上的和交互上的进行协调统一，这里不在赘述</p>
<ol start="2">
<li>
<p>样式上的内容，因为主要是功能，这里样式使用<code>less</code>进行简单绘制</p>
<div class="language-css vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">css</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">style</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> scoped lang="less"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">></span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">.table</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  border</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> solid</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> red</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  padding</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">rem</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  border-radius</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">rem</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  position</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">absolute</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  left</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">200</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  top</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">300</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  height</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">300</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  // 表头</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  .</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">rowHeader</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    position</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">relative</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">260</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    max-width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">300</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    overflow</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">hidden</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    left</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">30</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    .</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">rowHeader-table</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      position</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">relative</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      left</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: v-bind(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">left</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">fit-content</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  // 列头</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">  .columnHeader</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    position</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">relative</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    max-height</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">300</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    overflow</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">hidden</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">30</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    top</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    .</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">columnHeader-table</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      position</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">relative</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      top</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: v-bind(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">top</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  // 表格本体</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">  .tableBody</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">265</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    height</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">300</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    position</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">absolute</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    top</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">55</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    left</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">50</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    overflow</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">auto</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  // 表格元素</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  tr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">fit-content</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    white-space</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">normal</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    display</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">flex</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    .</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">td</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      display</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">block</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">30</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      height</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">30</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      text-align</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">center</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      line-height</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">30</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">style</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">></span></span></code></pre>
</div><p>内容上和定义的结构进行统一调节，这里需要主要的是：<span style='color:red;font-weight:900;'>
因为表格的宽度和表头的宽度对应，表格的高度和列头的高度固定，所以建议在定义时考虑好对应的宽高对应关系，方便调节</span></p>
<p>在定义好表头和列头时，对与展示的部分通过外部的<code>div</code>进行定位的调节进行展示，内部的表格部分通过宽度的固定来达到样式统一，使用相对定位来完成展示内容的切换</p>
<p>内部使用了Vue3提供的<code>v-bind</code>，如果你使用的时vue2或其他内容请更换为内联样式或其他方式</p>
<p><code>v-bind</code>
为Vue3中提供，主要是将绑定的内容转换为自定义标签使用，具体介绍可以看我的另一篇文章：<a href="https://blog.csdn.net/weixin_52235488/article/details/126290046?spm=1001.2014.3001.5502" target="_blank" rel="noreferrer">Vue3新属性 — v-bind in css</a>
，里面有用法和原理的详细介绍</p>
</li>
<li>
<p>逻辑部分：主要为内部的真正的表格绑定了滚动的监听，</p>
<div class="language-html vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">html</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">script</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> lang</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"ts"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> setup</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { ref } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'vue'</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 定义行和列</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> row</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 20</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> column</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 30</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 将内容进行响应式定义</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> top </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ref</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'0px'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> left </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ref</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'0px'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 绑定对应的监听事件</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Scroll</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">event</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Event</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  top.value </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> -</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">event.target.scrollTop </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'px'</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  left.value </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> -</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">event.target.scrollLeft </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'px'</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">script</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span></code></pre>
</div><p>这里使用的动态数据在<code>v-bind</code>中进行，这里直接修改即可</p>
</li>
</ol>
<h2 id="其他环境中要修改的内容" tabindex="-1">其他环境中要修改的内容 <a class="header-anchor" href="#其他环境中要修改的内容" aria-label="Permalink to &quot;其他环境中要修改的内容&quot;">&ZeroWidthSpace;</a></h2>
<p>这里对常见问题进行解决，如果没有匹配，请评论或找其他方式解决</p>
<ol>
<li>
<p><code>原生JavaScript中使用</code>：如果你完全没有使用过<code>Vue</code>，上面的代码我也改成了原生的版本，逻辑一样，这里就只放代码不做介绍了
<code>直接创建文件复制使用</code></p>
<div class="language-html vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">html</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">&#x3C;!--</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  ~ Time:2022/8/12 9:02 36</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  ~ Name:test1.html</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  ~ Path:</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  ~ ProjectName:element-plus</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  ~ Author:charlatan</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  ~</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  ~  Il n'ya qu'un héroïsme au monde :</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  ~     c'est de voir le monde tel qu'il est et de l'aimer.</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  --></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;!</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">DOCTYPE</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> html</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">html</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> lang</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"en"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">head</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">meta</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> charset</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"UTF-8"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">meta</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> content</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"IE=edge"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> http-equiv</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"X-UA-Compatible"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">meta</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> content</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"viewport"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">title</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>Title&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">title</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">style</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">		*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			margin</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			padding</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			list-style</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">none</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			font</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">500</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 15</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> YouYuan;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			text-decoration</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">none</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">		li</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			cursor</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">pointer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			position</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">relative</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">		/*-------以上为默认设置（The above is the default setting）--------*/</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">		.table</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			border</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> solid</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> red</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			padding</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">rem</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			border-radius</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">rem</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			position</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">absolute</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			left</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">200</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			top</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">300</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			height</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">300</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">		.rowHeader</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			position</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">relative</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">260</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			max-width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">300</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			overflow</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">hidden</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			left</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">30</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">		.rowHeader-table</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			position</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">relative</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			left</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">fit-content</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">		.columnHeader</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			position</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">relative</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			max-height</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">270</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			overflow</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">hidden</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">30</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			top</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">		.columnHeader-table</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			position</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">relative</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			top</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">		.tableBody</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">265</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			height</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">270</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			position</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">absolute</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			top</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">55</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			left</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">50</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			overflow</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">auto</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">		tr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">fit-content</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			white-space</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">normal</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			display</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">flex</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">		.td</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			display</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">block</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">30</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			height</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">30</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			text-align</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">center</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">			line-height</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">30</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">px</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">style</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">head</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">body</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"table"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">	&#x3C;!--    表头--></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"rowHeader"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">table</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"rowHeader-table"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">			&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">tr</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> id</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"rowHeader-table-tr"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">tr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">table</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">	&#x3C;!--    列头--></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"columnHeader"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">table</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"columnHeader-table"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> id</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"columnHeader-table-tr"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">table</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">	&#x3C;!--    表格--></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"tableBody"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> id</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"scroll"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">table</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"tableBody-table"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> id</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"tableBody-table-tr"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">table</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">body</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">script</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">	// 定义行和列</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">	const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> row</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 30</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">	const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> column</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 30</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">	// 获取表头</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">	let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> rowHeard </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> document.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">getElementById</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'rowHeader-table-tr'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">	// 创建表头元素</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">	for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, len </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> row; i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> len; i</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">++</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">		// 获取元素</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">		let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> td </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> document.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">createElement</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'td'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">		// 添加样式</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		td.classList.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">add</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'td'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">		// 添加内容</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">		let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> testNode </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> document.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">createTextNode</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(i)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		td.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">appendChild</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(testNode)</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">		// 将表头放置到指定位置</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		rowHeard.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">appendChild</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(td)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">	// 创建表头元素</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">	let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> columnHeard </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> document.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">getElementById</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'columnHeader-table-tr'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">	// 创建元素</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">	for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, len </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> column; i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> len; i</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">++</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">		let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> tr </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> document.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">createElement</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'tr'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">		let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> td </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> document.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">createElement</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'td'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		td.classList.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">add</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'td'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		td.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">appendChild</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(document.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">createTextNode</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(String.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">fromCharCode</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 64</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)))</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		tr.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">appendChild</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(td)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		columnHeard.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">appendChild</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(tr)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">	// 创建表格元素</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">	let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> table </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> document.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">getElementById</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'tableBody-table-tr'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">	for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, len </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> column; i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> len; i</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">++</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">		let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> tr </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> document.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">createElement</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'tr'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">		for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> j </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, len </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> row; j </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> len; j</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">++</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">			let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> td </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> document.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">createElement</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'td'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">			td.classList.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">add</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'td'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">			td.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">appendChild</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(document.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">createTextNode</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> String.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">fromCharCode</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(j </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 64</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)))</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">			tr.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">appendChild</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(td)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		table.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">appendChild</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(tr)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">	// 获取表头和列头滚动元素</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">	let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> row_heard </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> document.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">getElementsByClassName</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'rowHeader-table'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">	let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> column_heard </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> document.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">getElementsByClassName</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'columnHeader-table'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">	// 绑定滚动时间</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">	let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> scroll </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> document.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">getElementById</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'scroll'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	scroll.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">onscroll</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> function</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">event</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		row_heard.style.left </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> -</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">event.target.scrollLeft </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'px'</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		column_heard.style.top </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> -</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">event.target.scrollTop </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'px'</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">script</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">html</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span></code></pre>
</div><p>主要通过的是JS的元素创建然后将元素添加至对应的内容中，然后进行事件的绑定，从而完成整体逻辑</p>
</li>
<li>
<p><code>React</code>和<code>小程序中</code>，二者都是可以进行数据的绑定，元素的循环处理更加方法，小程序中没有鼠标，可能要更换为手指滑动操作，对于这个逻辑相同，
<code>绑定元素的移动距离</code>，从而让表头和列头跟随移动从而达到同步的效果和目的</p>
</li>
</ol>
]]></content>
        <author>
            <name>duyl328</name>
            <uri>https://seyl.me/about</uri>
        </author>
        <category label="编程"/>
        <category label="学习"/>
        <category label="Html"/>
        <category label="JavaScript"/>
        <category label="vue"/>
        <category label="Blog"/>
        <category label="原创"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Vue3中的ref为何要用.value进行值的调用？]]></title>
        <id>https://seyl.me/posts/2022/08/why-use-value-for-ref-in-vue3</id>
        <link href="https://seyl.me/posts/2022/08/why-use-value-for-ref-in-vue3"/>
        <updated>2022-08-25T00:00:00.000Z</updated>
        <content type="html"><![CDATA[<h1 id="frontmatter-title" tabindex="-1">{{ $frontmatter.title }} <a class="header-anchor" href="#frontmatter-title" aria-label="Permalink to &quot;{{ $frontmatter.title }}&quot;">&ZeroWidthSpace;</a></h1>
<blockquote>
<p>✒️ 文章摘要</p>
</blockquote>
<!-- DESC SEP -->
<p>这篇文章对比了 Vue2 和 Vue3 中的数据响应式处理方式，特别是如何定义和代理数据。在 Vue2 中，所有数据都通过一个统一的 data 对象进行管理，使用 Object.defineProperty 来实现响应式绑定。而在 Vue3 中，数据定义变得更加灵活，允许直接使用单一的数据类型，通过 ref 和 reactive 来创建响应式数据。虽然 ref 看似代理了普通数据，但实际上 Vue3 使用了 Proxy 技术对数据进行处理，这使得响应式机制变得更加高效和灵活。</p>
<p>总结来说，Vue3 引入了更强大的数据代理机制，通过 Proxy 改善了响应式数据的管理，允许更复杂的数据类型和更加灵活的数据操作，而 Vue2 依赖于传统的对象代理方式。这些变化使得 Vue3 在处理响应式数据时更具优势，尤其是在开发大型项目时。</p>
<p>如果你对 Vue3 中的响应式机制和数据代理的工作原理感兴趣，这篇文章会带你深入了解背后的技术细节。</p>
<!-- DESC SEP -->
<p>在<code>Vue2</code>中，所有的数据都通过一个Data进行统一的返回，并且在data中对某个组件要用的数据进行统一的管理，常见的使用形式是这样的：</p>
<div class="language-html vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">html</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">template</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"div"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		&#x3C;</span><span style="--shiki-light:#B31D28;--shiki-dark:#FDAEB7;--shiki-light-font-style:italic;--shiki-dark-font-style:italic">todos</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> :Obj</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"tos"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> :removeObj</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"removeObj"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>&#x3C;/</span><span style="--shiki-light:#B31D28;--shiki-dark:#FDAEB7;--shiki-light-font-style:italic;--shiki-dark-font-style:italic">todos</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">template</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">script</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">	import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> search </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> '@/components/search'</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">	import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> todos </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> '@/components/todos'</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">	import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> all </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> '@/components/all'</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">	export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		name: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'App'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">		data</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> () {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">			return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">				tos: [</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">					{ id: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'001'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, value: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'第一个'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, done: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">					{ id: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'002'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, value: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'第二个'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, done: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">					{ id: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'003'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, value: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'第三个'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, done: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">					{ id: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'004'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, value: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'第四个'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, done: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">				],</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">			}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		},</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		computed: {},</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		components: {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">			search, todos, all,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		},</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		methods: {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">			removeObj</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">obj</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">				console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(obj.id)</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">				this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.tos </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.tos.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">filter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">item</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> item.id </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">!==</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> obj.id)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">				console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.tos)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">			},</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		},</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">script</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">style</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> scoped</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	/</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	/</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	样式</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">style</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">></span></span></code></pre>
</div><p>可以看出来这里定义的内容都在一个数组中进行，或者是一个函数，将要使用的数据返回出来，这里无论怎么进行操作处理，最终进行数据代理的时候得到的都是一个对象，Vue2中直接通过
<code>defineProperty</code>进行处理，并绑定对应的监听事件进行响应式的处理。</p>
<p>而Vue3中，数据的定义可以是单独的，Vue可以让我们随时需要随时定义，这也就带来了另一个问题，我需要的一个数据可能不是对象</p>
<div class="language-js vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">script</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> lang</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"ts"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> setup</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    </span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    let str = ref('响应式字符串')</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    let obj = reactive({</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    name: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'张三'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    age: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">})</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">script</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span></code></pre>
</div><p>如果要定义的数据不是对象，还需要代理会怎么样？</p>
<p>在Vue2中数据的定义都在对象中统一进行，也就不会出现这种情况，如果一定要代理一个单独的数据呢？</p>
<p>Vue2中的数据代理通过<code>defineProperty</code>进行实现，也就是说我们要让<code>defineProperty</code>代理一个普通的数据，而不是一个对象，在
<code>defineProperty</code>的MDN的文档中是这样定义的：</p>
<blockquote>
<p><strong><code>Object.defineProperty()</code></strong> 方法会直接在一个对象上定义一个新属性，或者修改一个对象的现有属性，并返回此对象。</p>
</blockquote>
<p>通过这个可以明确看出，只能进行对象的代理，不能进行普通数据的代理，如果使用普通数据类型会直接报以下错误[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p1Lm0OSJ-1661407967498)(Vue3中的ref为何要用.value进行值的调用？.assets/image-20220825094409254.webp)]</p>
<pre><code>在Vue3中数据代理可以使用单一数据了，并且也改进了数据代理的方式，使用的是`Peoxy`完成了数据代理，而MDN中对`Proxy`也进行了定义：
</code></pre>
<blockquote>
<p><strong>Proxy</strong> 对象用于创建一个对象的代理，从而实现基本操作的拦截和自定义（如属性查找、赋值、枚举、函数调用等）。</p>
</blockquote>
<p>可以看出，<code>Proxy</code>依然是为对象服务，而不是普通的内容，这样问题似乎就解决了</p>
<p>本操作的拦截和自定义（如属性查找、赋值、枚举、函数调用等）。</p>
<p>可以看出，<code>Proxy</code>依然是为对象服务，而不是普通的内容，这样问题似乎就解决了</p>
<blockquote>
<p>即使是Vue3中使用的<code>Proxy</code>的代理方式也不能进行普通数据的代理，所以当调用<code>Ref</code>的时候其实仍然创建了一个<code>Proxy</code>
对象，并且Vue帮你给这个对象了一个<code>value</code>属性，属性值就是你定义的内容，改变的时候监视的改变依然是通过<code>Proxy</code>
的数据劫持来进行响应式的处理，而模板中使用的时候<code>Vue</code>会默认调用对应的<code>value</code>属性，从而完成模板中的内容的直接调用</p>
</blockquote>
]]></content>
        <author>
            <name>duyl328</name>
            <uri>https://seyl.me/about</uri>
        </author>
        <category label="编程"/>
        <category label="学习"/>
        <category label="vue"/>
        <category label="Blog"/>
        <category label="原创"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[在JavaScript获取Promise的状态]]></title>
        <id>https://seyl.me/posts/2022/08/get-promise-status-in-javascript</id>
        <link href="https://seyl.me/posts/2022/08/get-promise-status-in-javascript"/>
        <updated>2022-08-09T00:00:00.000Z</updated>
        <content type="html"><![CDATA[<h1 id="frontmatter-title" tabindex="-1">{{ $frontmatter.title }} <a class="header-anchor" href="#frontmatter-title" aria-label="Permalink to &quot;{{ $frontmatter.title }}&quot;">&ZeroWidthSpace;</a></h1>
<blockquote>
<p>✒️ 文章摘要</p>
</blockquote>
<!-- DESC SEP -->
<p>这篇文章讨论了如何同步地获取 JavaScript Promise 对象的状态。通过一个 Stack Overflow 上的解决方案，文章介绍了如何使用
Promise.race() 方法判断 Promise 的状态。</p>
<p>关键内容总结：
问题：如何在执行过程中同步地检查一个 Promise 的状态？
解决方案：文章通过 Promise.race() 方法对 Promise 和一个额外的 target 对象进行竞赛（race）。根据返回的对象，判断 Promise 是否处于
pending（待定）、fulfilled（已完成）或 rejected（已拒绝）状态。
代码分析：
通过创建一个 target 对象，Promise.race() 在 Promise 和 target 中最先完成的会决定返回值。
如果 Promise 未完成，则返回 pending；如果已完成且无错误，则返回 fulfilled；如果发生错误，则返回 rejected。
注意事项：Promise.race() 中的顺序很重要，确保 promise 在前，否则可能会影响结果。
这个方法利用了 Promise.race() 的特性，巧妙地判断了 Promise 的状态。</p>
<!-- DESC SEP -->
<h1 id="写在前面" tabindex="-1">写在前面 <a class="header-anchor" href="#写在前面" aria-label="Permalink to &quot;写在前面&quot;">&ZeroWidthSpace;</a></h1>
<p>本文属于对<code>stackoverflow</code>中写法的解析，原文链接：<a href="https://stackoverflow.com/questions/30564053/how-can-i-synchronously-determine-a-javascript-promises-state" target="_blank" rel="noreferrer">**Stack Overflow
** </a></p>
<p>如果你在其他环境下遇到同样问题，这个<a href="https://blog.csdn.net/Lee_01/article/details/124892590" target="_blank" rel="noreferrer">文章</a>可能也会有帮助</p>
<h1 id="问题复现" tabindex="-1">问题复现 <a class="header-anchor" href="#问题复现" aria-label="Permalink to &quot;问题复现&quot;">&ZeroWidthSpace;</a></h1>
<p>如何在代码执行过程中获取到<code>promise</code>的状态？</p>
<p>如果你想寻找或尝试通过原生的属性，或者指定API进行访问，基本可以放弃了，我也是看了很多博客的确没找到，如果您找了其他方式，还望指教</p>
<h1 id="解决方式" tabindex="-1">解决方式 <a class="header-anchor" href="#解决方式" aria-label="Permalink to &quot;解决方式&quot;">&ZeroWidthSpace;</a></h1>
<p>本文中提到的解决方式主要是继续<code>stackoverflow</code>中提供的解决方式【完整代码】</p>
<div class="language-js vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">/**</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">* 传入需要测试的 Promise 对象，将对应结果返回</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">* </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">@param</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> promise</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> 需要测试的 Promise 对象</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">* </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">@return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> {Promise&#x3C;string>}</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">*/</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> promiseState</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> promise</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">      const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> target</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {}</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">      return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> Promise</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">race</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">([promise, target]).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">then</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span></span>
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">          value</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (value </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">===</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> target) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">?</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'pending'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> :</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'fulfilled'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">          () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'rejected'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      )</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 测试代码</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> a </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> Promise</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">resolve</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> b </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> Promise</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">reject</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> c </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> Promise</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {});</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">promiseState</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(a).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">then</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">state</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(state)); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// fulfilled</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">promiseState</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(b).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">then</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">state</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(state)); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// rejected</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">promiseState</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(c).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">then</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">state</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(state)); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// pending</span></span></code></pre>
</div><p>这种方式通过<code>promise</code>中的<code>race()</code>方法来进行了状态的判断，非常奇妙的一种方式</p>
<h1 id="代码分析" tabindex="-1">代码分析 <a class="header-anchor" href="#代码分析" aria-label="Permalink to &quot;代码分析&quot;">&ZeroWidthSpace;</a></h1>
<ol>
<li>
<p>在方法中会接收一个<code>promise</code>对象，开始了整个方法</p>
</li>
<li>
<p>进入方法后会先创建一个<code>target</code>对象，这个对象只用于后续的匹配，没有其他含义</p>
<div class="language-js vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> target</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {}</span></span></code></pre>
</div></li>
<li>
<p>然后开始最核心的部分，因为<code>stackoverflow</code>中对代码进行简写，可以先进行代码的还原</p>
<div class="language-js vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> Promise</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">race</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">([promise, target]).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">then</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">                // 成功回调</span></span>
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">                value</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (value </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">===</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> target) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">?</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'pending'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> :</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'fulfilled'</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                },</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">                // 失败回调</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                    return</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'rejected'</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        )</span></span></code></pre>
</div><p>可以复现出这种结构，<code>promise</code>的<code>race</code>开始后，接收两个对象，一个为刚刚创建的<code>target</code>对象，还有一个是接收到的<code>promise</code>
对象，当两个其中一个状态结束时，整个<code>Promise.race()</code>结束，这时分为三种情况</p>
<ol>
<li>当传入的<code>promise</code>为<code>pending</code>状态时，<code>Promise.race</code>会找到最先有确定状态的元素，并将其返回，因为<code>promise</code>
没有结束，那么返回值对象会接收到定义的<code>target</code>，因为<code>target</code>的状态是确定的，这时<code>value</code>接收到的值就是已经确定状态的
<code>target</code>，如果进行对比，那么他们两个一定是相等的，这时也就是返回<code>pending</code></li>
<li>当传入的<code>promise</code>为<code>fulfilled</code>状态时，相当于<code>promise</code>已经有确定的值了，<code>Promise.race</code>
匹配到第一个直接结束，并将匹配到的内容返回，返回的内容因为是一个全新的对象，对象的内存地址不可能相等，所以判断结果是
<code>false</code>，也就返回<code>fulfilled</code></li>
<li>当传入的<code>promise</code>为<code>rejected</code>状态时，<code>promise</code>状态确定，那么因为状态报错，直接进入<code>catch</code>中，走失败回调，这个回调一旦执行，就可以判定
<code>promsie</code>结束，并且内容出现报错，直接返回<code>rejected</code>即可</li>
<li>在调用的时候，因为返回的时会将对应的状态通过<code>promise</code>返回，所以直接通过调用方法之后的<code>then</code>中指定回调来完成状态的获取</li>
</ol>
<ul>
<li>
<p><strong>值得注意的是</strong>：<code>Promise.race()</code>在匹配的过程中，一定保证要判断的<code>promise</code>在前，因为只有当<code>promise</code>
状态不确定时才会判断第二个内容的状态，如果将状态已经确定的<code>target</code>放在第一个，那么将不会再进行<code>promise</code>的判断，返回结果永远为
<code>fulfilled</code></p>
</li>
<li>
<p>并且因为<code>catch</code>有两种形式，可以进行变形，这种形式可能更常见（根据个人习惯了）</p>
<div class="language-js vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> promiseState</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> promise</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> target</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {}</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> Promise</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">race</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">([promise, target]).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">then</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span></span>
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">            value</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">                return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (value </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">===</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> target) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">?</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'pending'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> :</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'fulfilled'</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    ).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">catch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 'rejected'</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    })</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div></li>
</ul>
</li>
</ol>
]]></content>
        <author>
            <name>duyl328</name>
            <uri>https://seyl.me/about</uri>
        </author>
        <category label="编程"/>
        <category label="学习"/>
        <category label="JavaScript"/>
        <category label="Blog"/>
        <category label="原创"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[如何在Vue3的Store中使用i18n]]></title>
        <id>https://seyl.me/posts/2022/06/how-to-use-i18n-in-vue3's-store</id>
        <link href="https://seyl.me/posts/2022/06/how-to-use-i18n-in-vue3's-store"/>
        <updated>2022-06-27T00:00:00.000Z</updated>
        <content type="html"><![CDATA[<h1 id="frontmatter-title" tabindex="-1">{{ $frontmatter.title }} <a class="header-anchor" href="#frontmatter-title" aria-label="Permalink to &quot;{{ $frontmatter.title }}&quot;">&ZeroWidthSpace;</a></h1>
<blockquote>
<p>✒️ 文章摘要</p>
</blockquote>
<!-- DESC SEP -->
<p>这篇文章讨论了在 Vue3 环境下使用 vue-i18n 和 element-plus 处理多语言提示时遇到的问题及解决方案。具体来说，文章描述了在使用
setup 函数的路由中，因 useI18n() 在加载时未准备好，导致无法直接使用 t、d 等翻译方法的问题。为了绕过这个问题，文章提供了解决方案，通过手动引入已配置的
i18n 方法，而不是依赖 useI18n()。</p>
<p>总结来说，Vue3 中的 setup 和 ts 环境在路由中使用多语言时会遇到时序性问题，解决方法是手动导入已配置的 i18n
实例，直接调用翻译方法，避免了在路由中使用 useI18n() 时的顺序问题。这种方法可以确保在路由和组件中都能正确地显示多语言提示信息。</p>
<!-- DESC SEP -->
<h2 id="使用环境" tabindex="-1">使用环境 <a class="header-anchor" href="#使用环境" aria-label="Permalink to &quot;使用环境&quot;">&ZeroWidthSpace;</a></h2>
<blockquote>
<p><code>Vue</code>的版本为：<code>3.2.36</code>，</p>
<p><code>vue-router</code>的版本为：<code>4.0.16</code></p>
<p><code>vue-i18n</code>的版本为：<code>9.2.0-beta.40</code></p>
</blockquote>
<p>几乎都最新版本了</p>
<p><img src="./../../../public/posts/2022/06/img-1.webp" alt="在这里插入图片描述"></p>
<h2 id="问题复现" tabindex="-1">问题复现 <a class="header-anchor" href="#问题复现" aria-label="Permalink to &quot;问题复现&quot;">&ZeroWidthSpace;</a></h2>
<p>使用的<code>element-plus</code>框架进行项目的搭建，在登陆的时候在全局路由中进行密码的校验，如果密码错误或正确使用<code>element-plus</code>
中的提示组件登录的提示，但是提示的内容要根据选择的语言进行分别的提示</p>
<p>这个似乎很正常的需求，但是因为使用的<code>vue3</code>中的<code>setup</code>，并且在路由中是使用的<code>ts</code>，所以不能使用this，并且像<code>vue</code>文件中使用的引入方式：</p>
<div class="language-js vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">t</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">d</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">n</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">locale</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> useI18n</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span></span></code></pre>
</div><p>这种方式也是不行的，因为执行顺序的前后问题，在路由加载时<code>useI18n()</code>还没有引入执行，所以这种方式的引入会直接报错的</p>
<h2 id="问题解决" tabindex="-1">问题解决 <a class="header-anchor" href="#问题解决" aria-label="Permalink to &quot;问题解决&quot;">&ZeroWidthSpace;</a></h2>
<p>因为在<code>.vue</code>文件中会使用对应的方法将对应的内容引入，但是当执行路由时这个内容并没有加载，但是这个代码一定是存在并且可以直接运行的，所以可以通过其他方式直接手动将对应需要的代码引入，而不使用提供的方法</p>
<p>当在创建对应的i18n时，会先将对应的内容进行创建和导出：</p>
<p><img src="./../../../public/posts/2022/06/img-2.webp" alt="在这里插入图片描述"></p>
<p>在这个文件中创建了i18n，并且对特定的配置项进行了指定，但是导出的这个i18n中有什么？</p>
<p><img src="./../../../public/posts/2022/06/img-3.webp" alt="在这里插入图片描述"></p>
<p>在配置的文件中已经存在了要使用的方法，也就是导出的：<code>t</code>,<code>d</code>,<code>n</code>等，要使用的方法也在这里面</p>
<p><img src="./../../../public/posts/2022/06/img-4.webp" alt="在这里插入图片描述"></p>
<p>在这个<code>global</code>中存在了对应的全局的方法，不需要通过i18n指定的方法进行引入执行，可以直接使用，所以这个就是要手动引入的内容</p>
<h2 id="解决" tabindex="-1">解决 <a class="header-anchor" href="#解决" aria-label="Permalink to &quot;解决&quot;">&ZeroWidthSpace;</a></h2>
<p><img src="./../../../public/posts/2022/06/img-5.webp" alt="在这里插入图片描述"></p>
<p>使用这种方法问题得到解决，不过在尝试过程中，这种两种方式使用的i18n也是有区别的</p>
<p>在引入的过程中，因为方式不同，所以引入的方法其实也不是同一个</p>
<p><img src="./../../../public/posts/2022/06/img-6.webp" alt="在这里插入图片描述"></p>
<p>不过在对应的注释中也能略微看出二者的区别</p>
<p><img src="./../../../public/posts/2022/06/img-7.webp" alt="在这里插入图片描述"></p>
<p>使用方法引入的‘t’应当也有特有的内容，这里只进行列举，不继续深入探讨。</p>
]]></content>
        <author>
            <name>duyl328</name>
            <uri>https://seyl.me/about</uri>
        </author>
        <category label="编程"/>
        <category label="工作"/>
        <category label="学习"/>
        <category label="vue"/>
        <category label="JavaScript"/>
        <category label="i18n"/>
        <category label="BUG"/>
        <category label="Blog"/>
        <category label="原创"/>
    </entry>
</feed>