<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>lx`Blog</title>
  
  <subtitle>水边的哲学是不舍昼夜，山地的哲学是不知日月</subtitle>
  <link href="https://www.amoit.top/atom.xml" rel="self"/>
  
  <link href="https://www.amoit.top/"/>
  <updated>2026-10-06T12:33:25.150Z</updated>
  <id>https://www.amoit.top/</id>
  
  <author>
    <name>lx</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>板绘学习</title>
    <link href="https://www.amoit.top/posts/digital-painting-notes/"/>
    <id>https://www.amoit.top/posts/digital-painting-notes/</id>
    <published>2026-08-30T09:57:27.000Z</published>
    <updated>2026-10-06T12:33:25.150Z</updated>
    
    <content type="html"><![CDATA[<h1 id="板绘学习"><a href="#板绘学习" class="headerlink" title="板绘学习"></a>板绘学习</h1><h1 id="美术人体动态结构课程笔记"><a href="#美术人体动态结构课程笔记" class="headerlink" title="美术人体动态结构课程笔记"></a>美术人体动态结构课程笔记</h1><h2 id="一、课程说明"><a href="#一、课程说明" class="headerlink" title="一、课程说明"></a>一、课程说明</h2><h3 id="1-教师自我介绍"><a href="#1-教师自我介绍" class="headerlink" title="1. 教师自我介绍"></a>1. 教师自我介绍</h3><ul><li><strong>专业背景</strong>: 美术游戏原画工作13年经验，涉及场景、角色设计和电影海报</li><li><strong>项目经验</strong>: 参与过《上古卷轴》《魂斗罗》《真龙霸业》《捕鱼达人》等项目</li><li><strong>教学专长</strong>: 现专注于人体动态结构类教学</li></ul><h3 id="2-班级学生基础情况"><a href="#2-班级学生基础情况" class="headerlink" title="2. 班级学生基础情况"></a>2. 班级学生基础情况</h3><ul><li><strong>学员构成</strong>: 57%零基础学员，部分有美术经验和工作经验</li><li><strong>学习建议</strong>:<ul><li>零基础学员避免盲目攀比</li><li>有基础学员不应轻视基础课程</li><li>所有学员都应踏实打好基础</li></ul></li></ul><h3 id="3-上课时间安排"><a href="#3-上课时间安排" class="headerlink" title="3. 上课时间安排"></a>3. 上课时间安排</h3><ul><li><strong>正课时间</strong>: 每周六下午3-5点，晚上8-10点</li><li><strong>辅导课</strong>:<ul><li>周二晚：解决作业难题</li><li>周五晚：作业问题总结与专项练习</li></ul></li></ul><h3 id="4-课程周期与作业安排"><a href="#4-课程周期与作业安排" class="headerlink" title="4. 课程周期与作业安排"></a>4. 课程周期与作业安排</h3><ul><li><strong>课程周期</strong>: 12周(6月24日-9月8日)</li><li><strong>作业截止</strong>: 9月15日</li><li><strong>加课安排</strong>: 优秀学员会有额外课程</li></ul><h3 id="5-课程录播保存政策"><a href="#5-课程录播保存政策" class="headerlink" title="5. 课程录播保存政策"></a>5. 课程录播保存政策</h3><ul><li><strong>默认保存</strong>: 1年</li><li><strong>延长条件</strong>: 全班作业完成情况良好可延长至2年</li></ul><hr><h2 id="二、软件介绍"><a href="#二、软件介绍" class="headerlink" title="二、软件介绍"></a>二、软件介绍</h2><ul><li><strong>教学软件</strong>: Photoshop CS6</li><li><strong>可选软件</strong>: Procreate或其他PS版本</li><li><strong>学习资源</strong>:<ul><li>小鹅通基础教程</li><li>B站教程(半天可掌握基础)</li></ul></li></ul><hr><h2 id="三、找参考"><a href="#三、找参考" class="headerlink" title="三、找参考"></a>三、找参考</h2><h3 id="1-找参考误区"><a href="#1-找参考误区" class="headerlink" title="1. 找参考误区"></a>1. 找参考误区</h3><ul><li><strong>错误观念</strong>:<ul><li>认为学画是为了不找参考</li><li>认为原创作品不能有参考</li><li>使用过度修图的图片作为参考</li><li>参考与创作内容关联性低</li></ul></li><li><strong>正确方法</strong>:<ul><li>参考应有清晰结构</li><li>借鉴而非照搬</li><li>参考应与创作目标相关</li></ul></li></ul><h3 id="2-怎么找参考"><a href="#2-怎么找参考" class="headerlink" title="2. 怎么找参考"></a>2. 怎么找参考</h3><ul><li><strong>专业网站</strong>:<ul><li><strong>A站</strong>: 全球专业艺术家平台</li><li><strong>P站</strong>: 智能图片推荐</li><li><strong>花瓣</strong>: 画板收集功能</li><li><strong>Sketchfab</strong>: 3D模型参考</li><li><strong>Pofi无限人偶</strong>: 动态参考</li></ul></li><li><strong>参考技巧</strong>:<ul><li>学习一流作品提升审美</li><li>建立个人素材库</li><li>使用3D模型多角度观察</li><li>参考应服务于创作目标</li></ul></li><li><strong>案例解析</strong>:<ul><li>借鉴动态而非照抄</li><li>分部位寻找参考(头部、服装等)</li><li>组合多个参考创作新作品</li></ul></li><li><strong>审美培养</strong>:<ul><li>避免学习三流作品</li><li>每日浏览专业作品”洗眼”</li><li>审美决定进步上限</li></ul></li></ul><hr><h2 id="四、上课注意事项"><a href="#四、上课注意事项" class="headerlink" title="四、上课注意事项"></a>四、上课注意事项</h2><ul><li><strong>保密要求</strong>：课程内容严禁外传或盗录售卖，已开始准备法律诉讼，保护老师知识产权。<ul><li>禁止任何形式的课程录制和传播</li><li>发现侵权行为将追究法律责任</li><li>课程设计具有完整知识产权保护</li></ul></li><li><strong>学习要求</strong>：<ul><li><strong>知识连贯性</strong>：课程前后内容具有严密逻辑关系，后期不会重复讲解前期基础（如人体动态课不会重讲火柴人）</li><li><strong>主动复习</strong>：需要自主复习前期知识，保持知识体系的连贯性</li><li><strong>互动规范</strong>：上课时可通过弹幕提问，老师会在不影响课程节奏时统一解答</li></ul></li><li><strong>班级氛围</strong>：<ul><li><strong>正向循环</strong>：积极互动的班级整体进步明显（举例：老师当年参加的培训班因积极氛围培养出多位行业大佬）</li><li><strong>负面影响</strong>：消极言论会导致集体学习动力下降（如”太难了放弃”等言论易引发连锁反应）</li><li><strong>共同维护</strong>：需要全员营造积极向上的学习环境</li></ul></li></ul><hr><h2 id="五、作业评改流程"><a href="#五、作业评改流程" class="headerlink" title="五、作业评改流程"></a>五、作业评改流程</h2><h3 id="节点式流程"><a href="#节点式流程" class="headerlink" title="节点式流程"></a>节点式流程</h3><ol><li>完成单个节点作业后提交至班级群</li><li>助教反馈修改意见（未通过需修改重交）</li><li>全部节点通过后上传最终作业至指定相册</li></ol><ul><li><strong>命名规范</strong>：学号-姓名-周次（如000-tenten-L1）</li><li><strong>最终改图截止时间</strong>：9月15日</li></ul><h3 id="1-提交作业注意事项"><a href="#1-提交作业注意事项" class="headerlink" title="1. 提交作业注意事项"></a>1. 提交作业注意事项</h3><ul><li><strong>提交规范</strong>：<ul><li><strong>图片质量</strong>：需清晰完整，避免过多空白（反例：大画布只画小图）</li><li><strong>问题说明</strong>：遇到具体问题（如手脚结构）需附参考图，否则老师难以针对性指导</li><li><strong>修改进度</strong>：每次修改需体现自身进步，禁止完全依赖助教改图（反例：四个助教接力改同一作业）</li></ul></li><li><strong>提交渠道</strong>：<ul><li>统一在群内提交，按时间顺序批改</li><li>被跳过时可能是QQbug，需重新@助教</li><li>禁止私聊助教改图以保证公平性</li><li>错误提交可私聊教务撤回</li></ul></li></ul><h3 id="2-作业评改中的学习机会"><a href="#2-作业评改中的学习机会" class="headerlink" title="2. 作业评改中的学习机会"></a>2. 作业评改中的学习机会</h3><ul><li><strong>学习机制</strong>：<ul><li><strong>周五总结课</strong>：tenten老师每周五晚分类点评典型问题</li><li><strong>共性学习</strong>：通过他人作业点评发现自身可能存在的同类问题</li><li><strong>练习延伸</strong>：课程方法可用于课外练习（但非课程作业不参与正式评改）</li></ul></li><li><strong>改图原则</strong>：<ul><li>可要求助教调整严格程度（需明确说明）</li><li>仅批改符合课程标准的作业（不批改无关练习图）</li><li>专业画家的大量作品也不参与课程批改</li></ul></li></ul><hr><h2 id="六、正课"><a href="#六、正课" class="headerlink" title="六、正课"></a>六、正课</h2><h3 id="1-人体动态与透视的建立"><a href="#1-人体动态与透视的建立" class="headerlink" title="1. 人体动态与透视的建立"></a>1. 人体动态与透视的建立</h3><h4 id="1）第一节课课程总结"><a href="#1）第一节课课程总结" class="headerlink" title="1）第一节课课程总结"></a>1）第一节课课程总结</h4><ul><li><strong>核心要素</strong>：人体绘画需要掌握三个关键要素：比例、空间关系和体积意识。</li><li><strong>练习顺序</strong>：第一步要熟悉人体比例，第二步培养空间意识，第三步理解体积与空间的区别。</li><li><strong>工具使用</strong>：课程中演示了套索工具、笔工具等Photoshop工具的使用方法。</li></ul><p><strong>人体绘画步骤分解</strong></p><ol><li><strong>步骤1-比例</strong>：确保人体各部分比例准确，这是绘画的基础。</li><li><strong>步骤2-平衡</strong>：注意画面的平衡感，避免人物显得僵硬。</li><li><strong>步骤3-剖面</strong>：理解人体各部位的剖面结构。</li><li><strong>步骤4-透视</strong>：掌握不同角度下的透视关系。</li><li><strong>步骤5-圆柱体</strong>：用圆柱体构建人体基本形态。</li><li><strong>步骤6-方块转换</strong>：将圆柱体转换为方块，确定正侧面关系。</li><li><strong>步骤7-透视强化</strong>：运用1点、2点、3点透视增强立体感。</li><li><strong>步骤8-动态表现</strong>：通过方块扭转表现动态感。</li></ol><p><strong>新手常见问题</strong></p><ul><li><strong>心理障碍</strong>：新手往往不敢下笔，容易被照片细节带偏。</li><li><strong>框架缺失</strong>：缺乏系统的绘画流程和框架。</li><li><strong>比例失调</strong>：常见问题包括手部过长、腰胯分离等。</li><li><strong>细节过度</strong>：过早关注衣褶等细节而忽略整体比例。</li></ul><p><strong>高手绘画方法</strong></p><ul><li><strong>问题分解</strong>：将复杂问题拆解为多个简单小问题。</li><li><strong>小稿准备</strong>：即使是经验丰富的画师也会先做比例小稿。</li><li><strong>流程优化</strong>：建立明确的绘画步骤，从火柴人开始逐步完善。</li><li><strong>极致细节</strong>：对每个简单问题都做到极致处理。</li></ul><h4 id="2）新手画画时容易存在的问题"><a href="#2）新手画画时容易存在的问题" class="headerlink" title="2）新手画画时容易存在的问题"></a>2）新手画画时容易存在的问题</h4><ul><li><strong>比例错误</strong>：常见如手部过长、四肢连接不当等问题。</li><li><strong>结构分离</strong>：腰胯分离、衣服与身体脱节等现象。</li><li><strong>细节迷失</strong>：过度关注衣褶等细节而忽略整体造型。</li><li><strong>步骤混乱</strong>：直接进入细节刻画而跳过基础构建阶段。</li></ul><p><strong>问题案例分析</strong></p><ul><li><strong>案例1</strong>：手部比例严重失调，长度超出正常范围。</li><li><strong>案例2</strong>：衣服表现与身体结构脱节，显得”穿哥哥的小衣服”。</li><li><strong>案例3</strong>：腰胯部位结构分离，缺乏整体连贯性。</li><li><strong>案例4</strong>：腿部比例异常，大腿与小腿关系失衡。</li></ul><p><strong>正确绘画方法示范</strong></p><ul><li><strong>小稿先行</strong>：即使是专业画师也会先绘制比例小稿。</li><li><strong>步骤明确</strong>：从火柴人开始，逐步构建形体。</li><li><strong>光影处理</strong>：专业画师的光影表现干脆利落。</li><li><strong>基础扎实</strong>：所有优秀作品都建立在准确的比例基础上。</li></ul><h4 id="3）人体基本比例"><a href="#3）人体基本比例" class="headerlink" title="3）人体基本比例"></a>3）人体基本比例</h4><p><strong>示例图解析</strong></p><ul><li><strong>二分法核心</strong>：将人体比例简化为两个关键的一比一关系<ul><li>第一组：胯部底端为分界点，上半身（胯部到头顶）与下半身（胯部到脚掌）长度相等</li><li>第二组：大腿长度与小腿长度完全相等</li></ul></li><li><strong>三分法要点</strong>：上半身分为三个等长部分<ul><li>第一段：头颈联合部分（含头部和颈部）</li><li>第二段：完整胸腔长度</li><li>第三段：腰椎联合骨盆区域</li></ul></li><li><strong>手臂定位技巧</strong>：<ul><li>上臂长度参照骨盆纵向长度</li><li>前臂与上臂保持一比一关系</li><li>手臂自然下垂时，指尖位置与骨盆底部平齐</li></ul></li><li><strong>动态捕捉方法</strong>：<ul><li>先用三个球体表示头颈、胸腔、骨盆三大体块</li><li>注意体块间角度变化（如典型站姿中头颈与胸腔约130°夹角，胸腔与骨盆约100°夹角）</li><li>通过体块倾斜角度表现人物动态感</li></ul></li><li><strong>比例验证技巧</strong>：<ul><li>手臂摆动时保持”自行车轮辐原理”：肩关节到指尖的虚拟连线应与躯干中线形成对称角度</li><li>腿部比例快速检查法：大腿长度应等于小腿长度（含脚掌厚度）</li></ul></li><li><strong>简化绘制流程</strong>：<ul><li>用三个圆形定位头颈、胸腔、骨盆</li><li>注意头颈圆最小，胸腔圆最大（需包含颈部长度）</li><li>骨盆圆需包含腰椎部分</li><li>按一比一关系延伸四肢线条</li></ul></li><li><strong>常见误区提醒</strong>：<ul><li>避免将躯干画成直线排列的体块（会导致僵硬感）</li><li>注意骨盆区域实际包含腰椎部分（约占1&#x2F;3长度）</li><li>手臂长度测量应以骨盆为基准而非胸腔</li></ul></li></ul><h4 id="4）动态趋势"><a href="#4）动态趋势" class="headerlink" title="4）动态趋势"></a>4）动态趋势</h4><p><strong>火柴人基础构建</strong></p><ul><li><strong>角度确立</strong>：先确定火柴人的动态站姿和整体角度，这是后续绘制的基础框架</li><li><strong>比例关系</strong>：手臂长度与胸腔底部面需保持一致，上臂与前臂的标准比例为1:1</li><li><strong>透视表现</strong>：当手臂剖面面向观众时会显得更短，这与剖面角度和透视程度相关</li></ul><p><strong>比例练习方法</strong></p><ul><li><strong>三圈定位法</strong>：用三个圆圈（头、胸腔、骨盆）先确定基本比例关系，保持1:1:1的基础比例</li><li><strong>动态修正</strong>：即使比例正确，若动态失衡仍会显得奇怪，需通过”Z字型”转折来增强稳定性</li><li><strong>平衡原理</strong>：参考伯里曼人体理论，稳定动态应像叠酒瓶一样形成前后交替的支撑结构</li></ul><h4 id="5）画简单结构"><a href="#5）画简单结构" class="headerlink" title="5）画简单结构"></a>5）画简单结构</h4><p><strong>身体区块划分</strong></p><ul><li><strong>三大组件</strong>：头部（可缩小）、胸腔（可调整角度）、骨盆（需注意倾斜关系）</li><li><strong>连接关系</strong>：通过腰椎连接胸腔和骨盆，形成可调节的动态曲线</li><li><strong>观察技巧</strong>：眯眼观察整体轮廓的曲折关系，培养对角度变化的敏感度</li></ul><p><strong>腿部绘制技巧</strong></p><ul><li><strong>S型曲线</strong>：大腿前1&#x2F;3处凸起→膝盖后收→小腿后1&#x2F;3处再凸起→脚踝前收</li><li><strong>比例调整</strong>：大腿略短于小腿（视觉上更美观），小腿越长人物显得越高挑</li><li><strong>错位原理</strong>：膝盖位置应使大腿和小腿形成前后错开的关系，而非直线排列</li></ul><h4 id="6）画面平衡"><a href="#6）画面平衡" class="headerlink" title="6）画面平衡"></a>6）画面平衡</h4><p><strong>锁足点原理</strong></p><ul><li><strong>重心判定</strong>：从锁骨中心点（颈窝）垂直向下到主要受力的脚部位置</li><li><strong>双足站立</strong>：当两腿均受力时，重心线在两脚之间；单腿受力时则在受力腿正上方</li><li><strong>平衡验证</strong>：若锁足点偏离受力区域（如抬腿时重心仍在两脚间），动态就会失衡</li></ul><p><strong>钟摆动态理论</strong></p><ul><li><strong>力学原理</strong>：人体动态类似钟摆运动，动作幅度越大，反向平衡力也需要越强</li><li><strong>应用示例</strong>：当胸腔前倾时，骨盆和腿部必须产生反向力矩（如后伸腿部）来维持平衡</li><li><strong>夸张处理</strong>：在保证锁足点正确的前提下，可适当夸张动态增强画面张力</li></ul><p><strong>综合绘制步骤</strong></p><ol><li><strong>定比例</strong>：用几何体概括主要身体部件</li><li><strong>抓动态</strong>：建立”S”型或”Z”型韵律线</li><li><strong>调平衡</strong>：通过锁足点验证重心稳定性</li><li><strong>做夸张</strong>：在合理范围内强化动态表现</li></ol><h4 id="7）应用案例"><a href="#7）应用案例" class="headerlink" title="7）应用案例"></a>7）应用案例</h4><p><strong>例题:人物动态平衡问题</strong></p><ul><li><strong>框选定位法</strong>：<ul><li>将人物最高点和最左右点用方框框住，中心线即为画面平衡点</li><li>适用于平视状态下的人物动态分析，如站立、行走等基础动作</li></ul></li><li><strong>锁足点原理</strong>：<ul><li>当人物双脚着地时，锁骨与足部的连线应通过重心</li><li>示例中角色因脚尖踮起几乎不受力，故锁足点判断非常准确</li></ul></li><li><strong>配饰调节技巧</strong>：<ul><li>当角色动态失衡时，可通过添加头发、背包等配饰来平衡画面</li><li>如案例中长发飘向画面左侧，有效补偿了右侧的视觉重量</li></ul></li></ul><p><strong>例题:人物动态平衡问题</strong></p><ul><li><strong>透视空间构建法</strong>：<ul><li>通过脚部与地面的接触点确定底部透视面，再向上延伸建立立体方框</li><li>适用于俯视&#x2F;仰视等非平视状态，如案例中的高跟鞋角色</li></ul></li><li><strong>十字定位技巧</strong>：<ul><li>在透视方框内打十字交叉线，中心交点即为动态平衡点</li><li>类似”穿珠子”训练，通过空间线串连找到精确重心位置</li></ul></li><li><strong>常见错误</strong>：<ul><li>忽略脚部透视关系会导致整体动态失衡</li><li>示例中角色因未考虑近大远小规律，造成重心偏移</li></ul></li></ul><p><strong>例题:人物动态稳定性问题</strong></p><ul><li><strong>稳定性判定标准</strong>：<ul><li>优秀动态应同时满足：视觉动感强、韵律感好、物理平衡合理</li><li>案例3因中心点精准落在两腿之间而成为最佳范例</li></ul></li><li><strong>修正方案</strong>：<ul><li>调整脚部位置：将支撑脚移至方框中心线下方</li><li>添加平衡元素：用飘带&#x2F;武器等道具补偿视觉重量</li></ul></li><li><strong>典型错误</strong>：<ul><li>案例1因头饰位置不当导致重心偏移</li><li>案例2脚部透视错误造成”即将倾倒”的视觉效果</li></ul></li></ul><p><strong>例题:人物动态稳定性问题</strong></p><ul><li><strong>三要素构建法</strong>：<ul><li>比例控制：保持头身比协调（如7-8头身）</li><li>重心平衡：确保支撑点位于中心线下方</li><li>透视校正：遵循近大远小原则调整肢体粗细</li></ul></li><li><strong>脚部绘制技巧</strong>：<ul><li>用两个三角形组合表示脚部结构</li><li>前三角对应脚掌，后三角对应脚跟</li></ul></li><li><strong>动态发散训练</strong>：<ul><li>先固定头部位置，用方框法确定腿部落点</li><li>在保证重心的前提下自由设计肢体动作</li></ul></li></ul><p><strong>例题:人物动态稳定性问题</strong></p><ul><li><strong>俯视处理要点</strong>：<ul><li>按透视规律缩短下肢比例（近大远小）</li><li>示例中大腿长度需调整为头部的1.5倍左右</li></ul></li><li><strong>动态线辅助</strong>：<ul><li>用”S”型曲线串联头、胸、骨盆三大体块</li><li>看似倾斜的姿势实际重心仍保持在支撑面内</li></ul></li><li><strong>常见误区</strong>：<ul><li>过度追求造型夸张而忽视物理合理性</li><li>案例显示脚部位置偏差1cm即导致明显失衡感</li></ul></li></ul><h3 id="2-动态平衡与中心点调整"><a href="#2-动态平衡与中心点调整" class="headerlink" title="2. 动态平衡与中心点调整"></a>2. 动态平衡与中心点调整</h3><h4 id="1）中心点确定方法"><a href="#1）中心点确定方法" class="headerlink" title="1）中心点确定方法"></a>1）中心点确定方法</h4><ul><li><strong>手部动态影响</strong>：当手部动态变化较大时（如伸展过长），需要重新确定中心点位置，通常需要向左偏移以保持平衡</li><li><strong>多因素综合考量</strong>：中心点调整需同时考虑头发、披风等附加物体的动态变化，不能仅看单一部位</li><li><strong>方块检测法</strong>：用虚拟框包围整个人物，取框的几何中心作为平衡点，比单纯用锁骨点更准确可靠</li></ul><h4 id="2）人体比例关系"><a href="#2）人体比例关系" class="headerlink" title="2）人体比例关系"></a>2）人体比例关系</h4><ul><li><strong>臂长基准</strong>：前臂长度(小b)与上臂长度(大b)相等，两者保持1:1比例关系</li><li><strong>腿身比例</strong>：舞蹈角色设计中常采用”上身短腿长”的夸张比例，通过拉长腿部自然缩短上身视觉效果</li><li><strong>关键转折点</strong>：大腿1&#x2F;3处和小腿1&#x2F;3处是动态曲线的重要转折点，标记这些点有助于塑造自然姿态</li></ul><h4 id="3）动态平衡检查"><a href="#3）动态平衡检查" class="headerlink" title="3）动态平衡检查"></a>3）动态平衡检查</h4><ul><li><strong>中心线作用</strong>：主要用于动态检查而非设计辅助，确保角色在画面中能”站稳”</li><li><strong>透视处理</strong>：当透视较强时，必须使用方块检测法来验证空间中的平衡关系</li><li><strong>运动状态例外</strong>：如盲僧踢腿等明显运动中的姿势，可不考虑静态平衡问题</li></ul><h3 id="3-剖面表现技法"><a href="#3-剖面表现技法" class="headerlink" title="3. 剖面表现技法"></a>3. 剖面表现技法</h3><h4 id="1）剖面核心概念"><a href="#1）剖面核心概念" class="headerlink" title="1）剖面核心概念"></a>1）剖面核心概念</h4><ul><li><strong>体积表现关键</strong>：剖面比轮廓更能准确表达物体的空间体积和透视角度</li><li><strong>完整闭环原则</strong>：剖面线应形成完整环形（包括不可见部分），不能像”瓜子壳”一样突然中断</li><li><strong>角度转换</strong>：通过改变剖面弧度，可使同一轮廓呈现仰视&#x2F;俯视等完全不同的空间效果</li></ul><h4 id="2）剖面绘制要点"><a href="#2）剖面绘制要点" class="headerlink" title="2）剖面绘制要点"></a>2）剖面绘制要点</h4><ul><li><strong>转折处理</strong>：肢体转折处必须明确表现剖面转折，避免出现生硬的直角过渡</li><li><strong>多剖面组合</strong>：完整人体需要在大腿、小腿、胸腔等多个关键部位绘制剖面</li><li><strong>虚实结合</strong>：可见部分用实线，不可见部分用虚线，共同构成完整的体积信息</li></ul><h4 id="3）常见错误"><a href="#3）常见错误" class="headerlink" title="3）常见错误"></a>3）常见错误</h4><ul><li><strong>平面化问题</strong>：仅关注轮廓准确而忽略剖面，会导致角色缺乏立体感</li><li><strong>剖面不完整</strong>：只画可见部分剖面线，使物体像被”切开”的扁平状态</li><li><strong>弧度不合理</strong>：剖面弧度与整体透视不符，造成空间关系混乱</li></ul><h3 id="4-标准人体比例构建"><a href="#4-标准人体比例构建" class="headerlink" title="4. 标准人体比例构建"></a>4. 标准人体比例构建</h3><h4 id="1）基础比例框架"><a href="#1）基础比例框架" class="headerlink" title="1）基础比例框架"></a>1）基础比例框架</h4><ul><li><strong>三大段划分</strong>：头部空间、胸腔长度、腰椎长度构成基本比例框架</li><li><strong>肩胯对应</strong>：正常情况下肩膀宽度与骨盆宽度基本一致（特殊体型除外）</li><li><strong>腿长优化</strong>：艺术处理时通常加长小腿比例（大腿:小腿≈1:1.2）使视觉效果更佳</li></ul><h4 id="2）空间定位方法"><a href="#2）空间定位方法" class="headerlink" title="2）空间定位方法"></a>2）空间定位方法</h4><ul><li><strong>十字定位法</strong>：在虚拟方块中打十字交叉线确定中心点位置</li><li><strong>渐进构建</strong>：先确定头部空间，再依次构建脖子、胸腔、腰椎等部位</li><li><strong>比例验证</strong>：手臂自然下垂时，指尖位置应在大腿中段附近</li></ul><h4 id="3）侧面表现要点"><a href="#3）侧面表现要点" class="headerlink" title="3）侧面表现要点"></a>3）侧面表现要点</h4><ul><li><strong>曲线转折</strong>：侧面视角需重点表现脊柱的S形曲线转折</li><li><strong>厚度表现</strong>：通过剖面线明确胸腔厚度、骨盆倾斜度等空间信息</li><li><strong>动态预览</strong>：在方块中预先确定动态线走向，再细化各部位比例</li></ul><hr><h2 id="七、动态趋势"><a href="#七、动态趋势" class="headerlink" title="七、动态趋势"></a>七、动态趋势</h2><ul><li><strong>S型曲线构成</strong>：从头部到脚部形成连续S型曲线，具体表现为：头部低头→胸腔挺起→骨盆回收→大腿前倾→膝盖后移→小腿前收</li><li><strong>关键节点比例</strong>：所有转折点均按1&#x2F;3比例划分，如大腿分前1&#x2F;3和后2&#x2F;3，小腿同样遵循此比例</li><li><strong>中心点定位</strong>：头部位于中心点前侧，胸腔抬升时中心点需前移，骨盆回收时重新回到原始中心位置</li></ul><h3 id="1-躯干动态"><a href="#1-躯干动态" class="headerlink" title="1. 躯干动态"></a>1. 躯干动态</h3><ul><li><strong>头部定位</strong>：头部应低于中心线，颈部连接点位于中心点前侧约1&#x2F;3处</li><li><strong>胸腔处理</strong>：需明显挺起，与头部形成反向角度，中心点需前移约15度</li><li><strong>骨盆调整</strong>：在胸腔挺起后自然下收，与胸腔形成第二个反向转折点</li></ul><h3 id="2-腿部动态"><a href="#2-腿部动态" class="headerlink" title="2. 腿部动态"></a>2. 腿部动态</h3><ul><li><strong>大腿分段</strong>：先将大腿分为两等份，再在前段取1&#x2F;3处作为转折点</li><li><strong>空间关系</strong>：大腿前1&#x2F;3→膝盖后1&#x2F;3→小腿后1&#x2F;3→脚部回正，形成连续空间转折</li><li><strong>裆部注意</strong>：需区分裆部线与腿部起始线，大腿实际起始点高于裆部线约1&#x2F;6比例</li></ul><hr><h2 id="八、趋势分析"><a href="#八、趋势分析" class="headerlink" title="八、趋势分析"></a>八、趋势分析</h2><ul><li><strong>双S结构</strong>：上半身（头-胸-盆）与下半身（大腿-膝-小腿）各自形成独立S型，最终组合成完整动态</li><li><strong>骨盆基准</strong>：以骨盆为中间分界点，上下动态最终都需回归骨盆中心线</li><li><strong>角度修正</strong>：<ul><li>四分之三侧视时，正对观众的腿部转折角度需减小30%</li><li>脚部自然呈外八字，单脚倾斜角度建议15-20度</li></ul></li><li><strong>透视处理</strong>：当肢体正对观众时，转折面会变薄，转折幅度应减少50%以符合透视原理</li></ul><hr><h2 id="九、圆柱体和火柴人的套嵌关系"><a href="#九、圆柱体和火柴人的套嵌关系" class="headerlink" title="九、圆柱体和火柴人的套嵌关系"></a>九、圆柱体和火柴人的套嵌关系</h2><h3 id="1-套嵌关系分析"><a href="#1-套嵌关系分析" class="headerlink" title="1. 套嵌关系分析"></a>1. 套嵌关系分析</h3><ul><li><strong>平行原则</strong>: 圆柱体外轮廓线必须与火柴人结构线保持平行，否则会导致套嵌失效。例如画圈时若两侧线条不平行，火柴人的结构表现就会失真。</li><li><strong>中心定位</strong>: 圆柱体剖面中心点必须与火柴人关节点重合，绿色标记点应准确位于圆柱体中心位置。</li><li><strong>比例控制</strong>: 头部圆柱体应较小，胸腔圆柱体长度略短于骨盆，需预留腰椎空间。</li></ul><h3 id="2-剖面平行"><a href="#2-剖面平行" class="headerlink" title="2. 剖面平行"></a>2. 剖面平行</h3><ul><li><strong>相对平行性</strong>: 同一圆柱体的上下剖面必须保持相对平行，若上剖面为角度A，下剖面不能突然变为B。</li><li><strong>趋势线应用</strong>: 在肢体三分之一处绘制剖面时，需遵循趋势线的走向规律，如腿部剖面应位于骨盆下方特定位置。</li><li><strong>空间包裹</strong>: 圆柱体需完整包裹火柴人线条，通过练习使圆柱体在不同角度都能准确贴合结构线。</li></ul><h3 id="3-透视与剖面弧度"><a href="#3-透视与剖面弧度" class="headerlink" title="3. 透视与剖面弧度"></a>3. 透视与剖面弧度</h3><ul><li><strong>弧度定律</strong>: 剖面弧度与肢体长度成反比关系，具体表现为：<ul><li>正圆形剖面（最大弧度）对应最短肢体</li><li>扁平剖面（最小弧度）对应最长肢体</li><li>中间状态按比例变化</li></ul></li><li><strong>透视调整</strong>: 当肢体转向观众时：<ul><li>正面视角：剖面弧度最大，视觉长度最短</li><li>侧面视角：剖面趋平，视觉长度增加</li><li>可通过0°&#x2F;45°&#x2F;90°等具体角度演示变化过程</li></ul></li><li><strong>关节处理</strong>: 将关节视为球形枢纽，其剖面弧度决定连接肢体的表现长度，需保持：<ul><li>上臂与前臂的剖面协调</li><li>大腿与小腿的弧度渐变</li><li>避免出现剖面弧度突变造成的比例失调</li></ul></li></ul><hr><h2 id="十、比例和穿插"><a href="#十、比例和穿插" class="headerlink" title="十、比例和穿插"></a>十、比例和穿插</h2><h3 id="1-俯视和仰视"><a href="#1-俯视和仰视" class="headerlink" title="1. 俯视和仰视"></a>1. 俯视和仰视</h3><h4 id="1）透视叠压关系示例"><a href="#1）透视叠压关系示例" class="headerlink" title="1）透视叠压关系示例"></a>1）透视叠压关系示例</h4><ul><li><strong>透视变形原理</strong>：通过改变裆部在画面中的比例实现透视变化，俯视时裆部比例缩短，仰视时裆部比例拉长</li><li><strong>近大远小规律</strong>：<ul><li>俯视时：头部最大 → 胸腔次之 → 骨盆最小</li><li>仰视时：骨盆最大 → 胸腔次之 → 头部最小</li></ul></li><li><strong>常见误区</strong>：仅调整比例不处理叠压关系会导致透视感缺失，画面仍显平面化</li></ul><h4 id="2）俯视透视关系分析"><a href="#2）俯视透视关系分析" class="headerlink" title="2）俯视透视关系分析"></a>2）俯视透视关系分析</h4><ul><li><strong>叠压关系三要素</strong>：<ul><li>角度越大叠压越明显（俯视角度与叠压面积成正比）</li><li>焦距变化影响叠压程度（33mm焦距为标准参考）</li><li>球体间距离随角度增大而缩短（最终完全重叠）</li></ul></li><li><strong>强化技巧</strong>：<ul><li>头部与胸腔：部分重叠</li><li>胸腔与骨盆：增加遮挡面积</li><li>腿部处理：近端粗远端细，脚部平面化</li></ul></li><li><strong>动态调整</strong>：<ul><li>俯视时上半身拉长，腿部缩短</li><li>仰视时下半身拉长，头部缩小</li></ul></li></ul><hr><h2 id="十一、内容总结"><a href="#十一、内容总结" class="headerlink" title="十一、内容总结"></a>十一、内容总结</h2><ul><li><strong>核心要点</strong>：<ul><li>透视变形需同时处理比例变化和叠压关系</li><li>火柴人关节处应加粗表现体积感</li><li>空间锚点决定肢体摆放合理性</li></ul></li><li><strong>练习建议</strong>：<ul><li>先掌握标准素体比例再尝试动态夸张</li><li>通过轮廓勾画+结构分析强化透视理解</li><li>使用方块模板辅助透视练习</li></ul></li></ul><hr><h2 id="十二、知识小结"><a href="#十二、知识小结" class="headerlink" title="十二、知识小结"></a>十二、知识小结</h2><h3 id="核心知识点总结"><a href="#核心知识点总结" class="headerlink" title="核心知识点总结"></a>核心知识点总结</h3><table><thead><tr><th align="left">知识点</th><th align="left">核心内容</th><th align="left">重点&#x2F;易混淆点</th><th align="left">难度系数</th></tr></thead><tbody><tr><td align="left">人体比例基础</td><td align="left">头、胸腔、骨盆、腿的二分法与三分法比例关系</td><td align="left">大腿与小腿长度1:1，易误判为不等长</td><td align="left">⭐⭐</td></tr><tr><td align="left">动态平衡原理</td><td align="left">锁骨中心点与受力脚的位置关系（锁足点）</td><td align="left">非对称站姿的平衡判定（如单脚受力）</td><td align="left">⭐⭐⭐</td></tr><tr><td align="left">空间剖面表达</td><td align="left">圆柱体转折处的剖面弧度与透视关系</td><td align="left">剖面弧度越大，视觉长度越短（易忽略虚线圈闭合）</td><td align="left">⭐⭐⭐⭐</td></tr><tr><td align="left">透视比例调整</td><td align="left">俯视&#x2F;仰视时躯干叠压与近大远小规律</td><td align="left">叠压程度与焦距的关系（需结合实践理解）</td><td align="left">⭐⭐⭐⭐</td></tr><tr><td align="left">参考运用方法</td><td align="left">精准找参考（结构、动态、元素）与避免抄袭</td><td align="left">常见误区：认为原创&#x3D;完全不参考</td><td align="left">⭐⭐</td></tr><tr><td align="left">作业提交规范</td><td align="left">节点式提交（火柴人→圆柱体→方块人分阶段审核）</td><td align="left">排版模糊或未附参考图会导致反馈延迟</td><td align="left">⭐</td></tr></tbody></table><h3 id="课程时间安排"><a href="#课程时间安排" class="headerlink" title="课程时间安排"></a>课程时间安排</h3><table><thead><tr><th align="left">课程类型</th><th align="left">时间</th><th align="left">内容重点</th><th align="left">关联作业</th></tr></thead><tbody><tr><td align="left">正课</td><td align="left">每周六15:00-17:00</td><td align="left">人体动态结构、透视原理</td><td align="left">临摹与原创比例图</td></tr><tr><td align="left">辅导课</td><td align="left">每周二20:00</td><td align="left">作业难题解答、动态演示</td><td align="left">提交问题截图</td></tr><tr><td align="left">总结课</td><td align="left">每周五20:00</td><td align="left">共性错误分析与专项练习</td><td align="left">修改后终版作业</td></tr></tbody></table><h3 id="工具与参考推荐"><a href="#工具与参考推荐" class="headerlink" title="工具与参考推荐"></a>工具与参考推荐</h3><table><thead><tr><th align="left">类别</th><th align="left">推荐内容</th><th align="left">关键用途</th><th align="left">注意事项</th></tr></thead><tbody><tr><td align="left">软件</td><td align="left">Photoshop CS6&#x2F;Procreate</td><td align="left">基础绘画与设计</td><td align="left">版本差异不影响核心功能</td></tr><tr><td align="left">参考网站</td><td align="left">A站、Pinterest</td><td align="left">审美提升与结构参考</td><td align="left">A站需梯子访问</td></tr><tr><td align="left">3D辅助</td><td align="left">3d.sk、无线人偶工具</td><td align="left">多角度结构观察</td><td align="left">优先用于复杂透视</td></tr></tbody></table>]]></content>
    
    
    <summary type="html">板绘学习笔记，记录数位板使用、笔刷设置与绘画基础练习的心得与技巧。</summary>
    
    
    
    <category term="生活随笔" scheme="https://www.amoit.top/categories/%E7%94%9F%E6%B4%BB%E9%9A%8F%E7%AC%94/"/>
    
    
    <category term="绘画" scheme="https://www.amoit.top/tags/%E7%BB%98%E7%94%BB/"/>
    
    <category term="数位板" scheme="https://www.amoit.top/tags/%E6%95%B0%E4%BD%8D%E6%9D%BF/"/>
    
    <category term="板绘" scheme="https://www.amoit.top/tags/%E6%9D%BF%E7%BB%98/"/>
    
  </entry>
  
  <entry>
    <title>uni-app 学习笔记</title>
    <link href="https://www.amoit.top/posts/uni-app-study-notes/"/>
    <id>https://www.amoit.top/posts/uni-app-study-notes/</id>
    <published>2024-11-03T11:39:46.300Z</published>
    <updated>2026-10-06T14:54:52.334Z</updated>
    
    <content type="html"><![CDATA[<div class="note info flat"><p>uni-app 的定位是「<strong>一套代码，多端发行</strong>」——用 Vue 语法写一次，编译到微信小程序、支付宝小程序、H5、Android &#x2F; iOS App 等十几个平台。这篇记录从环境搭建到多端发布的主线，以及踩过的坑。</p></div><h2 id="一、它凭什么能跨端"><a href="#一、它凭什么能跨端" class="headerlink" title="一、它凭什么能跨端"></a>一、它凭什么能跨端</h2><p>uni-app 在 Vue 之上做了两件事：</p><ol><li><strong>统一组件与 API</strong>：把各端原生的组件和接口抽象成一套 <code>&lt;view&gt;</code>、<code>&lt;text&gt;</code>、<code>uni.request()</code> 这样的通用写法，编译时再翻译到目标平台</li><li><strong>条件编译</strong>：遇到平台差异（比如只有微信小程序有开放能力），用注释标记让某些代码只在指定平台生效</li></ol><p>所以它<strong>不是</strong>「写一次完全不用管差异」，而是「大部分代码共用，差异处单独处理」。</p><p>可以直接对标理解：</p><table><thead><tr><th>Web 写法</th><th>uni-app 写法</th><th>说明</th></tr></thead><tbody><tr><td><code>&lt;div&gt;</code></td><td><code>&lt;view&gt;</code></td><td>块级容器</td></tr><tr><td><code>&lt;span&gt;</code></td><td><code>&lt;text&gt;</code></td><td>文字，只有它才能长按选中</td></tr><tr><td><code>&lt;img&gt;</code></td><td><code>&lt;image&gt;</code></td><td>图片，默认有尺寸，需写 mode</td></tr><tr><td><code>&lt;a&gt;</code> &#x2F; 路由跳转</td><td><code>uni.navigateTo()</code></td><td>页面跳转</td></tr><tr><td><code>axios</code> &#x2F; <code>fetch</code></td><td><code>uni.request()</code></td><td>网络请求</td></tr><tr><td><code>localStorage</code></td><td><code>uni.setStorageSync()</code></td><td>本地缓存</td></tr></tbody></table><h2 id="二、开发环境"><a href="#二、开发环境" class="headerlink" title="二、开发环境"></a>二、开发环境</h2><p>两种方式，选一个即可：</p><div class="tabs" id="环境"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#环境-1"><i class="fas fa-cube"></i>HBuilderX</button></li><li class="tab"><button type="button" data-href="#环境-2"><i class="fas fa-terminal"></i>命令行</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="环境-1"><p>官方 IDE，开箱即用、内置真机运行与云打包，适合新手和 App 开发。</p><ol><li>下载安装 HBuilderX（选 App 开发版）</li><li>文件 → 新建 → 项目 → 选择 <code>uni-app</code> → 选默认模板</li><li>运行 → 运行到浏览器 &#x2F; 小程序模拟器 &#x2F; 手机</li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="环境-2"><p>适合熟悉 Vue 生态、想用 VS Code + 自定义构建流程的开发者。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Vue3 + Vite 版（推荐新项目）</span></span><br><span class="line">npx degit dcloudio/uni-preset-vue<span class="comment">#vite my-project</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">cd</span> my-project</span><br><span class="line">npm install</span><br><span class="line">npm run dev:mp-weixin     <span class="comment"># 编译到微信小程序</span></span><br><span class="line">npm run dev:h5            <span class="comment"># 编译到 H5</span></span><br><span class="line">npm run build:mp-weixin   <span class="comment"># 生产打包</span></span><br></pre></td></tr></table></figure><p>微信小程序端还需：把 <code>dist/dev/mp-weixin</code> 用<strong>微信开发者工具</strong>打开，并在工具里开启「服务端口」。</p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="三、目录结构"><a href="#三、目录结构" class="headerlink" title="三、目录结构"></a>三、目录结构</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">my-project/</span><br><span class="line">├── pages/                  # 页面，每个页面一个目录</span><br><span class="line">│   └── index/index.vue</span><br><span class="line">├── components/             # 可复用组件</span><br><span class="line">├── static/                 # 静态资源（图片等，不会编译）</span><br><span class="line">├── App.vue                 # 应用入口，全局样式与生命周期</span><br><span class="line">├── main.js                 # 初始化</span><br><span class="line">├── pages.json              # ⭐ 页面路由与导航栏配置</span><br><span class="line">├── manifest.json           # ⭐ 各端打包配置（AppID、权限、图标）</span><br><span class="line">└── uni.scss                # 全局样式变量</span><br></pre></td></tr></table></figure><div class="note warning flat"><p><code>pages.json</code> 里的 <code>pages</code> 数组第一项就是<strong>首页</strong>，顺序别搞错；新增页面必须在这里注册，否则跳不过去。</p></div><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;pages&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">    <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;path&quot;</span><span class="punctuation">:</span> <span class="string">&quot;pages/index/index&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;style&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;navigationBarTitleText&quot;</span><span class="punctuation">:</span> <span class="string">&quot;首页&quot;</span><span class="punctuation">,</span></span><br><span class="line">        <span class="attr">&quot;enablePullDownRefresh&quot;</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">true</span></span></span><br><span class="line">      <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line">  <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;globalStyle&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;navigationBarBackgroundColor&quot;</span><span class="punctuation">:</span> <span class="string">&quot;#5b5bd6&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;navigationBarTextStyle&quot;</span><span class="punctuation">:</span> <span class="string">&quot;white&quot;</span></span><br><span class="line">  <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;tabBar&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;list&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">      <span class="punctuation">&#123;</span> <span class="attr">&quot;pagePath&quot;</span><span class="punctuation">:</span> <span class="string">&quot;pages/index/index&quot;</span><span class="punctuation">,</span> <span class="attr">&quot;text&quot;</span><span class="punctuation">:</span> <span class="string">&quot;首页&quot;</span> <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="punctuation">&#123;</span> <span class="attr">&quot;pagePath&quot;</span><span class="punctuation">:</span> <span class="string">&quot;pages/my/my&quot;</span><span class="punctuation">,</span> <span class="attr">&quot;text&quot;</span><span class="punctuation">:</span> <span class="string">&quot;我的&quot;</span> <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">]</span></span><br><span class="line">  <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><h2 id="四、生命周期"><a href="#四、生命周期" class="headerlink" title="四、生命周期"></a>四、生命周期</h2><p>分三层，别记混：</p><table><thead><tr><th>层级</th><th>常用钩子</th><th>触发时机</th></tr></thead><tbody><tr><td>应用 <code>App.vue</code></td><td><code>onLaunch</code> &#x2F; <code>onShow</code> &#x2F; <code>onHide</code></td><td>启动 &#x2F; 切前台 &#x2F; 切后台</td></tr><tr><td>页面</td><td><code>onLoad</code> &#x2F; <code>onShow</code> &#x2F; <code>onReady</code> &#x2F; <code>onHide</code> &#x2F; <code>onUnload</code></td><td>加载 &#x2F; 显示 &#x2F; 首次渲染完 &#x2F; 隐藏 &#x2F; 卸载</td></tr><tr><td>页面</td><td><code>onPullDownRefresh</code> &#x2F; <code>onReachBottom</code></td><td>下拉刷新 &#x2F; 触底加载</td></tr><tr><td>组件</td><td>Vue 原生的 <code>created</code> &#x2F; <code>mounted</code> 等</td><td>同 Vue</td></tr></tbody></table><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">  <span class="title function_">onLoad</span>(<span class="params">options</span>) &#123;</span><br><span class="line">    <span class="comment">// options 就是上个页面传来的参数（URL 上的查询串）</span></span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(options.<span class="property">id</span>)</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="title function_">onReachBottom</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="title function_">loadMore</span>()      <span class="comment">// 触底加载下一页</span></span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="title function_">onPullDownRefresh</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="title function_">reload</span>().<span class="title function_">finally</span>(<span class="function">() =&gt;</span> uni.<span class="title function_">stopPullDownRefresh</span>())</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="五、样式与单位-rpx"><a href="#五、样式与单位-rpx" class="headerlink" title="五、样式与单位 rpx"></a>五、样式与单位 rpx</h2><p>uni-app 用 <strong>rpx</strong>（responsive pixel）做自适应：设计稿按 <strong>750rpx &#x3D; 屏幕宽度</strong> 出图。</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* 750rpx 宽的屏幕上，1rpx = 0.5px；换算比例自动适配各机型 */</span></span><br><span class="line"><span class="selector-class">.box</span> &#123;</span><br><span class="line">  <span class="attribute">width</span>: <span class="number">375</span>rpx;         <span class="comment">/* 占屏幕一半 */</span></span><br><span class="line">  <span class="attribute">font-size</span>: <span class="number">28</span>rpx;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><div class="note info flat"><p>750 这个基准来自 iPhone 6（375pt × 2）。设计稿如果是 750px 宽，标注多少 px 就写多少 rpx，不用换算，这是最舒服的地方。</p></div><p>样式注意点：</p><ul><li>页面样式写在 <code>&lt;style&gt;</code> 里默认只对当前页面生效（已自动加 scope）</li><li>想写全局样式放 <code>App.vue</code></li><li>单位别混用，项目里统一 rpx</li><li>小程序端不支持 <code>*</code> 选择器、不支持部分 CSS3 高级选择器</li></ul><h2 id="六、条件编译（核心技能）"><a href="#六、条件编译（核心技能）" class="headerlink" title="六、条件编译（核心技能）"></a>六、条件编译（核心技能）</h2><p>同一份代码里为不同平台写不同逻辑，用注释包裹：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// #ifdef MP-WEIXIN</span></span><br><span class="line">wx.<span class="title function_">login</span>(&#123; <span class="attr">success</span>: <span class="function"><span class="params">res</span> =&gt;</span> <span class="variable language_">console</span>.<span class="title function_">log</span>(res.<span class="property">code</span>) &#125;)   <span class="comment">// 只有微信小程序执行</span></span><br><span class="line"><span class="comment">// #endif</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// #ifdef H5</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;这段代码只在 H5 生效&#x27;</span>)</span><br><span class="line"><span class="comment">// #endif</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// #ifndef APP-PLUS</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;除 App 端外都执行&#x27;</span>)</span><br><span class="line"><span class="comment">// #endif</span></span><br></pre></td></tr></table></figure><p>模板和样式里同样可以用：</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- #ifdef MP-WEIXIN --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">button</span> <span class="attr">open-type</span>=<span class="string">&quot;getUserInfo&quot;</span>&gt;</span>微信授权登录<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- #endif --&gt;</span></span><br></pre></td></tr></table></figure><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* #ifdef H5 */</span></span><br><span class="line"><span class="selector-class">.box</span> &#123; <span class="attribute">height</span>: <span class="built_in">calc</span>(<span class="number">100vh</span> - <span class="number">44px</span>); &#125;</span><br><span class="line"><span class="comment">/* #endif */</span></span><br></pre></td></tr></table></figure><p>常用平台标识：</p><table><thead><tr><th>标识</th><th>平台</th><th>标识</th><th>平台</th></tr></thead><tbody><tr><td><code>MP-WEIXIN</code></td><td>微信小程序</td><td><code>H5</code></td><td>网页</td></tr><tr><td><code>MP-ALIPAY</code></td><td>支付宝小程序</td><td><code>APP-PLUS</code></td><td>App</td></tr><tr><td><code>MP</code></td><td>所有小程序</td><td><code>MP-BAIDU</code></td><td>百度小程序</td></tr></tbody></table><h2 id="七、路由与页面跳转"><a href="#七、路由与页面跳转" class="headerlink" title="七、路由与页面跳转"></a>七、路由与页面跳转</h2><p>五个 API，区别在于<strong>是否保留当前页</strong>和<strong>能否跳 tabBar</strong>：</p><table><thead><tr><th>API</th><th>行为</th><th>能否跳 tabBar</th><th>页面栈</th></tr></thead><tbody><tr><td><code>uni.navigateTo</code></td><td>保留当前页，打开新页</td><td>❌</td><td>入栈</td></tr><tr><td><code>uni.redirectTo</code></td><td>关闭当前页，打开新页</td><td>❌</td><td>替换</td></tr><tr><td><code>uni.switchTab</code></td><td>切换 tabBar 页</td><td>✅</td><td>清空非 tab 页</td></tr><tr><td><code>uni.reLaunch</code></td><td>关闭所有页，打开新页</td><td>✅</td><td>清空</td></tr><tr><td><code>uni.navigateBack</code></td><td>返回上一页</td><td>—</td><td>出栈</td></tr></tbody></table><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">uni.<span class="title function_">navigateTo</span>(&#123; <span class="attr">url</span>: <span class="string">&#x27;/pages/detail/detail?id=123&#x27;</span> &#125;)</span><br><span class="line">uni.<span class="title function_">switchTab</span>(&#123; <span class="attr">url</span>: <span class="string">&#x27;/pages/index/index&#x27;</span> &#125;)</span><br><span class="line">uni.<span class="title function_">navigateBack</span>(&#123; <span class="attr">delta</span>: <span class="number">1</span> &#125;)          <span class="comment">// 返回上一页</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 目标页接收参数</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">  <span class="title function_">onLoad</span>(<span class="params">options</span>) &#123; <span class="variable language_">console</span>.<span class="title function_">log</span>(options.<span class="property">id</span>) &#125;    <span class="comment">// &quot;123&quot;</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><div class="note danger flat"><p><code>navigateTo</code> <strong>最多只能再开 9 层页面栈</strong>，层级深了会失败。表单流程这类场景改用 <code>redirectTo</code>。</p></div><h2 id="八、请求封装"><a href="#八、请求封装" class="headerlink" title="八、请求封装"></a>八、请求封装</h2><p>原生 <code>uni.request</code> 是回调风格，用起来很啰嗦，自己封一层：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// utils/request.js</span></span><br><span class="line"><span class="keyword">const</span> <span class="variable constant_">BASE_URL</span> = <span class="string">&#x27;https://api.example.com&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> <span class="title function_">request</span>(<span class="params">&#123; url, method = <span class="string">&#x27;GET&#x27;</span>, data = &#123;&#125;, header = &#123;&#125; &#125;</span>) &#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =&gt;</span> &#123;</span><br><span class="line">    uni.<span class="title function_">request</span>(&#123;</span><br><span class="line">      <span class="attr">url</span>: <span class="variable constant_">BASE_URL</span> + url,</span><br><span class="line">      method,</span><br><span class="line">      data,</span><br><span class="line">      <span class="attr">header</span>: &#123; <span class="string">&#x27;Authorization&#x27;</span>: uni.<span class="title function_">getStorageSync</span>(<span class="string">&#x27;token&#x27;</span>), ...header &#125;,</span><br><span class="line">      <span class="attr">success</span>: <span class="function"><span class="params">res</span> =&gt;</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (res.<span class="property">statusCode</span> === <span class="number">200</span>) <span class="title function_">resolve</span>(res.<span class="property">data</span>)</span><br><span class="line">        <span class="keyword">else</span> <span class="keyword">if</span> (res.<span class="property">statusCode</span> === <span class="number">401</span>) &#123; <span class="comment">/* 跳登录 */</span> <span class="title function_">reject</span>(res) &#125;</span><br><span class="line">        <span class="keyword">else</span> <span class="title function_">reject</span>(res)</span><br><span class="line">      &#125;,</span><br><span class="line">      <span class="attr">fail</span>: reject</span><br><span class="line">    &#125;)</span><br><span class="line">  &#125;)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 用起来</span></span><br><span class="line"><span class="keyword">const</span> list = <span class="keyword">await</span> <span class="title function_">request</span>(&#123; <span class="attr">url</span>: <span class="string">&#x27;/articles&#x27;</span>, <span class="attr">data</span>: &#123; <span class="attr">page</span>: <span class="number">1</span> &#125; &#125;)</span><br></pre></td></tr></table></figure><h2 id="九、数据缓存"><a href="#九、数据缓存" class="headerlink" title="九、数据缓存"></a>九、数据缓存</h2><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 同步（简单场景直接用）</span></span><br><span class="line">uni.<span class="title function_">setStorageSync</span>(<span class="string">&#x27;token&#x27;</span>, <span class="string">&#x27;abc123&#x27;</span>)</span><br><span class="line"><span class="keyword">const</span> token = uni.<span class="title function_">getStorageSync</span>(<span class="string">&#x27;token&#x27;</span>)</span><br><span class="line">uni.<span class="title function_">removeStorageSync</span>(<span class="string">&#x27;token&#x27;</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 异步</span></span><br><span class="line">uni.<span class="title function_">setStorage</span>(&#123; <span class="attr">key</span>: <span class="string">&#x27;token&#x27;</span>, <span class="attr">data</span>: <span class="string">&#x27;abc123&#x27;</span> &#125;)</span><br></pre></td></tr></table></figure><div class="note warning flat"><p>小程序端单个 key 上限 1MB、总容量约 10MB，别往里塞大对象。<strong>图片路径、长列表这类数据不要缓存</strong>，token 和用户信息这类小数据可以。</p></div><h2 id="十、组件库推荐"><a href="#十、组件库推荐" class="headerlink" title="十、组件库推荐"></a>十、组件库推荐</h2><table><thead><tr><th>库</th><th>特点</th><th>适用</th></tr></thead><tbody><tr><td><strong>uni-ui</strong></td><td>官方出品，按需引入，跨端一致</td><td>求稳、官方项目</td></tr><tr><td><strong>uView Plus</strong></td><td>组件丰富、文档友好（Vue3 版）</td><td>业务系统、后台类</td></tr><tr><td><strong>uv-ui</strong></td><td>uView 的 Vue3 兼容分支</td><td>老项目迁移</td></tr></tbody></table><p>按需引入（uni_modules 方式）直接在插件市场导入即可，不用手动配置。</p><h2 id="十一、打包发布"><a href="#十一、打包发布" class="headerlink" title="十一、打包发布"></a>十一、打包发布</h2><table><thead><tr><th>目标端</th><th>操作</th></tr></thead><tbody><tr><td>微信小程序</td><td><code>npm run build:mp-weixin</code> → 微信开发者工具打开 <code>dist/build/mp-weixin</code> → 上传 → 后台提交审核</td></tr><tr><td>H5</td><td><code>npm run build:h5</code> → 把 <code>dist/build/h5</code> 传到服务器&#x2F;CDN（<strong>注意路由 history 模式需配置重定向</strong>）</td></tr><tr><td>App</td><td>HBuilderX → 发行 → 云打包（无需 Mac 也能出 iOS 包）</td></tr></tbody></table><p>发行前检查清单：</p><ul><li><input disabled="" type="checkbox"> <code>manifest.json</code> 里填好各端 AppID</li><li><input disabled="" type="checkbox"> 关闭 debug、移除 console</li><li><input disabled="" type="checkbox"> 接口域名已加入小程序后台的<strong>服务器域名白名单</strong>（必须是 https）</li><li><input disabled="" type="checkbox"> 隐私协议已配置（现在审核必查）</li></ul><h2 id="十二、常见坑速查"><a href="#十二、常见坑速查" class="headerlink" title="十二、常见坑速查"></a>十二、常见坑速查</h2><table><thead><tr><th>现象</th><th>原因</th><th>解法</th></tr></thead><tbody><tr><td>页面白屏 &#x2F; 找不到</td><td>没在 <code>pages.json</code> 注册</td><td>补上路由配置</td></tr><tr><td>跳转 tabBar 页失败</td><td>用了 <code>navigateTo</code></td><td>改用 <code>switchTab</code></td></tr><tr><td>网络请求失败</td><td>域名未在小程序后台配置</td><td>加白名单，开发时可勾选「不校验合法域名」</td></tr><tr><td>图片不显示</td><td><code>static</code> 路径写错，或用了本地绝对路径</td><td>用 <code>/static/xxx.png</code>，网络图要配白名单</td></tr><tr><td>样式不生效</td><td>用了一端不支持的选择器</td><td>避免 <code>*</code> 选择器、简化选择器</td></tr><tr><td>真机正常但模拟器报错</td><td>部分 API 模拟器不支持</td><td>以真机为准</td></tr><tr><td>scroll-view 无法滚动</td><td>没设固定高度</td><td>给它设明确 height（如 <code>100vh</code> 减去头部）</td></tr></tbody></table><hr><div class="note success flat"><p><strong>一句话总结</strong>：uni-app 的核心成本不在语法（就是 Vue），而在<strong>各端差异处理</strong>。把条件编译和平台 API 差异摸清，剩下的就是普通 Vue 开发。</p></div>]]></content>
    
    
    <summary type="html">uni-app 跨平台开发学习笔记，记录 Vue 语法与小程序端开发中遇到的问题及解决方案。</summary>
    
    
    
    <category term="前端开发" scheme="https://www.amoit.top/categories/%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91/"/>
    
    
    <category term="前端" scheme="https://www.amoit.top/tags/%E5%89%8D%E7%AB%AF/"/>
    
    <category term="uni-app" scheme="https://www.amoit.top/tags/uni-app/"/>
    
    <category term="小程序" scheme="https://www.amoit.top/tags/%E5%B0%8F%E7%A8%8B%E5%BA%8F/"/>
    
  </entry>
  
  <entry>
    <title>Ajax、Node.js 与 webpack 学习笔记</title>
    <link href="https://www.amoit.top/posts/ajax-nodejs-webpack-notes/"/>
    <id>https://www.amoit.top/posts/ajax-nodejs-webpack-notes/</id>
    <published>2024-04-07T14:47:01.000Z</published>
    <updated>2026-10-06T15:02:40.953Z</updated>
    
    <content type="html"><![CDATA[<div class="note info flat"><p>这三样是前端从「会写页面」到「能做项目」的必经之路：<strong>Ajax 负责跟服务器说话，Node.js 让 JS 能跑在服务端，webpack 把源码变成浏览器能高效加载的产物</strong>。一篇记完三块。</p></div><h1 id="一、Ajax-篇"><a href="#一、Ajax-篇" class="headerlink" title="一、Ajax 篇"></a>一、Ajax 篇</h1><h2 id="什么是-Ajax"><a href="#什么是-Ajax" class="headerlink" title="什么是 Ajax"></a>什么是 Ajax</h2><p>Ajax（Asynchronous JavaScript and XML）&#x3D; <strong>在不刷新页面的情况下与服务器交换数据并更新页面</strong>的技术。</p><p>核心就是浏览器提供的 <code>XMLHttpRequest</code> 对象（现在也有 <code>fetch</code>）。名字里带 XML，但实际用得最多的是 JSON。</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 原生 XHR 写法（了解原理即可，项目中很少手写）</span></span><br><span class="line"><span class="keyword">const</span> xhr = <span class="keyword">new</span> <span class="title class_">XMLHttpRequest</span>()</span><br><span class="line">xhr.<span class="title function_">open</span>(<span class="string">&#x27;GET&#x27;</span>, <span class="string">&#x27;https://api.example.com/users&#x27;</span>)</span><br><span class="line">xhr.<span class="property">onload</span> = <span class="function">() =&gt;</span> &#123;</span><br><span class="line">  <span class="keyword">if</span> (xhr.<span class="property">status</span> === <span class="number">200</span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> data = <span class="title class_">JSON</span>.<span class="title function_">parse</span>(xhr.<span class="property">responseText</span>)</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(data)</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line">xhr.<span class="title function_">send</span>()</span><br></pre></td></tr></table></figure><h2 id="axios（实际项目首选）"><a href="#axios（实际项目首选）" class="headerlink" title="axios（实际项目首选）"></a>axios（实际项目首选）</h2><p>学习路径建议：<strong>先会用 axios，再回头看 XHR 理解底层原理</strong>。</p><h3 id="引入"><a href="#引入" class="headerlink" title="引入"></a>引入</h3><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install axios</span><br></pre></td></tr></table></figure><h3 id="基本用法"><a href="#基本用法" class="headerlink" title="基本用法"></a>基本用法</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 1. 传入配置对象，用 .then 接收结果</span></span><br><span class="line"><span class="title function_">axios</span>(&#123;</span><br><span class="line">  <span class="attr">url</span>: <span class="string">&#x27;目标资源地址&#x27;</span>,</span><br><span class="line">  <span class="attr">method</span>: <span class="string">&#x27;GET&#x27;</span>,</span><br><span class="line">  <span class="attr">params</span>: &#123; <span class="attr">page</span>: <span class="number">1</span> &#125;        <span class="comment">// 查询参数</span></span><br><span class="line">&#125;).<span class="title function_">then</span>(<span class="function"><span class="params">result</span> =&gt;</span> &#123;</span><br><span class="line">  <span class="comment">// 对服务器返回的数据做后续处理</span></span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(result.<span class="property">data</span>)   <span class="comment">// ⭐ 数据在 result.data 里</span></span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 2. 语法糖</span></span><br><span class="line">axios.<span class="title function_">get</span>(<span class="string">&#x27;/api/users&#x27;</span>, &#123; <span class="attr">params</span>: &#123; <span class="attr">page</span>: <span class="number">1</span> &#125; &#125;)</span><br><span class="line">axios.<span class="title function_">post</span>(<span class="string">&#x27;/api/users&#x27;</span>, &#123; <span class="attr">name</span>: <span class="string">&#x27;张三&#x27;</span> &#125;)</span><br></pre></td></tr></table></figure><p>把数据渲染到页面：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable language_">document</span>.<span class="title function_">querySelector</span>(<span class="string">&#x27;.list&#x27;</span>).<span class="property">innerHTML</span> = htmlString   <span class="comment">// 以 HTML 格式显示</span></span><br></pre></td></tr></table></figure><h3 id="async-await-写法（更推荐）"><a href="#async-await-写法（更推荐）" class="headerlink" title="async&#x2F;await 写法（更推荐）"></a>async&#x2F;await 写法（更推荐）</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">getUsers</span>(<span class="params"></span>) &#123;</span><br><span class="line">  <span class="keyword">try</span> &#123;</span><br><span class="line">    <span class="keyword">const</span> &#123; data &#125; = <span class="keyword">await</span> axios.<span class="title function_">get</span>(<span class="string">&#x27;/api/users&#x27;</span>)</span><br><span class="line">    <span class="keyword">return</span> data</span><br><span class="line">  &#125; <span class="keyword">catch</span> (err) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">error</span>(<span class="string">&#x27;请求失败：&#x27;</span>, err.<span class="property">message</span>)</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="常用配置"><a href="#常用配置" class="headerlink" title="常用配置"></a>常用配置</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> request = axios.<span class="title function_">create</span>(&#123;</span><br><span class="line">  <span class="attr">baseURL</span>: <span class="string">&#x27;https://api.example.com&#x27;</span>,</span><br><span class="line">  <span class="attr">timeout</span>: <span class="number">10000</span>,</span><br><span class="line">  <span class="attr">headers</span>: &#123; <span class="string">&#x27;Content-Type&#x27;</span>: <span class="string">&#x27;application/json&#x27;</span> &#125;</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 拦截器：统一加 token、统一处理错误</span></span><br><span class="line">request.<span class="property">interceptors</span>.<span class="property">request</span>.<span class="title function_">use</span>(<span class="function"><span class="params">config</span> =&gt;</span> &#123;</span><br><span class="line">  config.<span class="property">headers</span>.<span class="property">Authorization</span> = <span class="variable language_">localStorage</span>.<span class="title function_">getItem</span>(<span class="string">&#x27;token&#x27;</span>)</span><br><span class="line">  <span class="keyword">return</span> config</span><br><span class="line">&#125;)</span><br><span class="line">request.<span class="property">interceptors</span>.<span class="property">response</span>.<span class="title function_">use</span>(</span><br><span class="line">  <span class="function"><span class="params">res</span> =&gt;</span> res.<span class="property">data</span>,</span><br><span class="line">  <span class="function"><span class="params">err</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">if</span> (err.<span class="property">response</span>?.<span class="property">status</span> === <span class="number">401</span>) location.<span class="property">href</span> = <span class="string">&#x27;/login&#x27;</span></span><br><span class="line">    <span class="keyword">return</span> <span class="title class_">Promise</span>.<span class="title function_">reject</span>(err)</span><br><span class="line">  &#125;</span><br><span class="line">)</span><br></pre></td></tr></table></figure><h2 id="认识-URL"><a href="#认识-URL" class="headerlink" title="认识 URL"></a>认识 URL</h2><p><strong>URL</strong>（Uniform Resource Locator）&#x3D; 统一资源定位符，就是网址。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">https://api.example.com:443/users?id=1&amp;page=2#top</span><br><span class="line">└─┬──┘ └──────┬──────┘└┬┘└───┬────┘└──┬──┘</span><br><span class="line"> 协议        域名      端口  资源路径   查询参数</span><br></pre></td></tr></table></figure><ul><li><strong>协议</strong>：<code>http</code> &#x2F; <code>https</code>。HTTP 是超文本传输协议，规定浏览器与服务器之间传输数据的格式</li><li><strong>域名</strong>：服务器的地址（会被 DNS 解析成 IP）</li><li><strong>资源路径</strong>：服务器上资源的位置</li><li><strong>查询参数</strong>：浏览器提供给服务器的<strong>额外信息</strong>，让服务器返回想要的数据</li></ul><h3 id="查询参数"><a href="#查询参数" class="headerlink" title="查询参数"></a>查询参数</h3><p>写法是在 URL 后加 <code>?</code>，多个参数用 <code>&amp;</code> 连接：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">?参数名1=值1&amp;参数名2=值2</span><br></pre></td></tr></table></figure><p>用 axios 时不用手动拼字符串，写在 <code>params</code> 里即可：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="title function_">axios</span>(&#123;</span><br><span class="line">  <span class="attr">url</span>: <span class="string">&#x27;/api/list&#x27;</span>,</span><br><span class="line">  <span class="attr">params</span>: &#123;</span><br><span class="line">    参数名: 值,</span><br><span class="line">    <span class="attr">page</span>: <span class="number">1</span>,</span><br><span class="line">    <span class="attr">size</span>: <span class="number">20</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;)</span><br><span class="line"><span class="comment">// 最终请求：/api/list?page=1&amp;size=20</span></span><br></pre></td></tr></table></figure><h2 id="HTTP-状态码与请求方法"><a href="#HTTP-状态码与请求方法" class="headerlink" title="HTTP 状态码与请求方法"></a>HTTP 状态码与请求方法</h2><p>常用方法：</p><table><thead><tr><th>方法</th><th>用途</th><th>是否有请求体</th></tr></thead><tbody><tr><td>GET</td><td>查询数据</td><td>否</td></tr><tr><td>POST</td><td>新增数据</td><td>是</td></tr><tr><td>PUT</td><td>整体更新</td><td>是</td></tr><tr><td>PATCH</td><td>局部更新</td><td>是</td></tr><tr><td>DELETE</td><td>删除</td><td>通常无</td></tr></tbody></table><p>常见状态码：</p><table><thead><tr><th>码</th><th>含义</th><th>典型原因</th></tr></thead><tbody><tr><td>200</td><td>成功</td><td>—</td></tr><tr><td>201</td><td>创建成功</td><td>POST 成功的常见响应</td></tr><tr><td>301 &#x2F; 302</td><td>重定向</td><td>资源已迁移</td></tr><tr><td>304</td><td>未修改，走缓存</td><td>命中协商缓存</td></tr><tr><td>400</td><td>请求参数错误</td><td>前端传参不对</td></tr><tr><td>401</td><td>未授权</td><td>token 缺失或过期</td></tr><tr><td>403</td><td>禁止访问</td><td>权限不足</td></tr><tr><td>404</td><td>资源不存在</td><td>URL 写错</td></tr><tr><td>500</td><td>服务器内部错误</td><td>后端 bug</td></tr></tbody></table><h2 id="跨域（必踩的坑）"><a href="#跨域（必踩的坑）" class="headerlink" title="跨域（必踩的坑）"></a>跨域（必踩的坑）</h2><p>浏览器有<strong>同源策略</strong>：协议、域名、端口三者任一不同就是跨域，默认会被拦。</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 前端在 http://localhost:5173，请求 http://api.example.com → 跨域了</span></span><br></pre></td></tr></table></figure><table><thead><tr><th>方案</th><th>做法</th><th>场景</th></tr></thead><tbody><tr><td><strong>CORS</strong>（最常用）</td><td>后端响应头加 <code>Access-Control-Allow-Origin</code></td><td>前后端分离项目</td></tr><tr><td><strong>开发代理</strong></td><td>Vite &#x2F; webpack devServer 配置 proxy</td><td>仅解决开发环境</td></tr><tr><td>JSONP</td><td>利用 <code>&lt;script&gt;</code> 不受同源限制</td><td>老方案，只支持 GET</td></tr><tr><td>Nginx 反向代理</td><td>运维层面转发</td><td>生产环境</td></tr></tbody></table><p>Vite 代理配置示例：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// vite.config.js</span></span><br><span class="line"><span class="attr">server</span>: &#123;</span><br><span class="line">  <span class="attr">proxy</span>: &#123;</span><br><span class="line">    <span class="string">&#x27;/api&#x27;</span>: &#123;</span><br><span class="line">      <span class="attr">target</span>: <span class="string">&#x27;https://api.example.com&#x27;</span>,</span><br><span class="line">      <span class="attr">changeOrigin</span>: <span class="literal">true</span>,</span><br><span class="line">      <span class="attr">rewrite</span>: <span class="function"><span class="params">path</span> =&gt;</span> path.<span class="title function_">replace</span>(<span class="regexp">/^\/api/</span>, <span class="string">&#x27;&#x27;</span>)</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1 id="二、Node-js-篇"><a href="#二、Node-js-篇" class="headerlink" title="二、Node.js 篇"></a>二、Node.js 篇</h1><h2 id="它是什么"><a href="#它是什么" class="headerlink" title="它是什么"></a>它是什么</h2><p>Node.js 让 JavaScript <strong>跑在服务端</strong>（基于 Chrome V8 引擎）。前端学它主要有三个用途：</p><ol><li>写接口 &#x2F; 中间层（BFF）</li><li>跑构建工具（webpack、Vite 都依赖它）</li><li>写脚本处理文件、自动化</li></ol><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">node -v          <span class="comment"># 查看版本</span></span><br><span class="line">npm -v           <span class="comment"># 包管理器</span></span><br><span class="line">node app.js      <span class="comment"># 运行脚本</span></span><br></pre></td></tr></table></figure><h2 id="模块化"><a href="#模块化" class="headerlink" title="模块化"></a>模块化</h2><table><thead><tr><th>规范</th><th>引入</th><th>导出</th><th>使用环境</th></tr></thead><tbody><tr><td>CommonJS（CJS）</td><td><code>require()</code></td><td><code>module.exports</code></td><td>Node 传统方式</td></tr><tr><td>ES Module（ESM）</td><td><code>import</code></td><td><code>export</code></td><td>现代标准，浏览器原生支持</td></tr></tbody></table><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// CommonJS</span></span><br><span class="line"><span class="keyword">const</span> fs = <span class="built_in">require</span>(<span class="string">&#x27;fs&#x27;</span>)</span><br><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = &#123; add &#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// ESM（package.json 里加 &quot;type&quot;: &quot;module&quot;，或用 .mjs 后缀）</span></span><br><span class="line"><span class="keyword">import</span> fs <span class="keyword">from</span> <span class="string">&#x27;fs&#x27;</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> <span class="title function_">add</span>(<span class="params">a, b</span>) &#123; <span class="keyword">return</span> a + b &#125;</span><br></pre></td></tr></table></figure><h2 id="常用内置模块"><a href="#常用内置模块" class="headerlink" title="常用内置模块"></a>常用内置模块</h2><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// fs：读写文件</span></span><br><span class="line"><span class="keyword">const</span> fs = <span class="built_in">require</span>(<span class="string">&#x27;fs&#x27;</span>)</span><br><span class="line">fs.<span class="title function_">readFileSync</span>(<span class="string">&#x27;a.txt&#x27;</span>, <span class="string">&#x27;utf-8&#x27;</span>)                    <span class="comment">// 同步读</span></span><br><span class="line">fs.<span class="title function_">writeFileSync</span>(<span class="string">&#x27;b.txt&#x27;</span>, <span class="string">&#x27;hello&#x27;</span>)                   <span class="comment">// 写</span></span><br><span class="line">fs.<span class="title function_">existsSync</span>(<span class="string">&#x27;a.txt&#x27;</span>)                               <span class="comment">// 是否存在</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// path：处理路径（避免 Windows / macOS 分隔符差异）</span></span><br><span class="line"><span class="keyword">const</span> path = <span class="built_in">require</span>(<span class="string">&#x27;path&#x27;</span>)</span><br><span class="line">path.<span class="title function_">join</span>(__dirname, <span class="string">&#x27;public&#x27;</span>, <span class="string">&#x27;index.html&#x27;</span>)         <span class="comment">// ⭐ 拼接路径</span></span><br><span class="line">path.<span class="title function_">resolve</span>(<span class="string">&#x27;src/index.js&#x27;</span>)                         <span class="comment">// 转绝对路径</span></span><br><span class="line">path.<span class="title function_">extname</span>(<span class="string">&#x27;a.png&#x27;</span>)                                <span class="comment">// &#x27;.png&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// http：起一个原生服务</span></span><br><span class="line"><span class="keyword">const</span> http = <span class="built_in">require</span>(<span class="string">&#x27;http&#x27;</span>)</span><br><span class="line">http.<span class="title function_">createServer</span>(<span class="function">(<span class="params">req, res</span>) =&gt;</span> &#123;</span><br><span class="line">  res.<span class="title function_">writeHead</span>(<span class="number">200</span>, &#123; <span class="string">&#x27;Content-Type&#x27;</span>: <span class="string">&#x27;text/plain; charset=utf-8&#x27;</span> &#125;)</span><br><span class="line">  res.<span class="title function_">end</span>(<span class="string">&#x27;Hello Node.js&#x27;</span>)</span><br><span class="line">&#125;).<span class="title function_">listen</span>(<span class="number">3000</span>)</span><br></pre></td></tr></table></figure><h2 id="npm-常用命令"><a href="#npm-常用命令" class="headerlink" title="npm 常用命令"></a>npm 常用命令</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">npm init -y                 <span class="comment"># 生成 package.json</span></span><br><span class="line">npm install axios           <span class="comment"># 安装依赖（写入 dependencies）</span></span><br><span class="line">npm install webpack -D      <span class="comment"># 安装开发依赖（写入 devDependencies）</span></span><br><span class="line">npm uninstall axios         <span class="comment"># 卸载</span></span><br><span class="line">npm update                  <span class="comment"># 更新</span></span><br><span class="line">npm run dev                 <span class="comment"># 执行 package.json 里 scripts 定义的命令</span></span><br><span class="line">npx webpack                 <span class="comment"># 临时执行，不用全局安装</span></span><br><span class="line">npm config <span class="built_in">set</span> registry https://registry.npmmirror.com    <span class="comment"># 换国内镜像，提速</span></span><br></pre></td></tr></table></figure><h2 id="Express-起个接口"><a href="#Express-起个接口" class="headerlink" title="Express 起个接口"></a>Express 起个接口</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install express</span><br></pre></td></tr></table></figure><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> express = <span class="built_in">require</span>(<span class="string">&#x27;express&#x27;</span>)</span><br><span class="line"><span class="keyword">const</span> app = <span class="title function_">express</span>()</span><br><span class="line"></span><br><span class="line">app.<span class="title function_">use</span>(express.<span class="title function_">json</span>())                  <span class="comment">// 解析 JSON 请求体</span></span><br><span class="line">app.<span class="title function_">use</span>(express.<span class="title function_">static</span>(<span class="string">&#x27;public&#x27;</span>))        <span class="comment">// 托管静态文件</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 定义一个 GET 接口</span></span><br><span class="line">app.<span class="title function_">get</span>(<span class="string">&#x27;/api/users&#x27;</span>, <span class="function">(<span class="params">req, res</span>) =&gt;</span> &#123;</span><br><span class="line">  res.<span class="title function_">json</span>(&#123; <span class="attr">code</span>: <span class="number">200</span>, <span class="attr">data</span>: [&#123; <span class="attr">id</span>: <span class="number">1</span>, <span class="attr">name</span>: <span class="string">&#x27;张三&#x27;</span> &#125;] &#125;)</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 带路径参数：/api/users/123 → req.params.id = &#x27;123&#x27;</span></span><br><span class="line">app.<span class="title function_">get</span>(<span class="string">&#x27;/api/users/:id&#x27;</span>, <span class="function">(<span class="params">req, res</span>) =&gt;</span> &#123;</span><br><span class="line">  res.<span class="title function_">json</span>(&#123; <span class="attr">id</span>: req.<span class="property">params</span>.<span class="property">id</span> &#125;)</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="comment">// POST：数据在 req.body</span></span><br><span class="line">app.<span class="title function_">post</span>(<span class="string">&#x27;/api/users&#x27;</span>, <span class="function">(<span class="params">req, res</span>) =&gt;</span> &#123;</span><br><span class="line">  res.<span class="title function_">status</span>(<span class="number">201</span>).<span class="title function_">json</span>(&#123; <span class="attr">msg</span>: <span class="string">&#x27;创建成功&#x27;</span>, <span class="attr">data</span>: req.<span class="property">body</span> &#125;)</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line">app.<span class="title function_">listen</span>(<span class="number">3000</span>, <span class="function">() =&gt;</span> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;服务已启动：http://localhost:3000&#x27;</span>))</span><br></pre></td></tr></table></figure><div class="note info flat"><p>中间件（middleware）是 Express 的核心概念：<code>app.use(fn)</code> 注册的函数会按顺序处理每个请求，可以做日志、鉴权、解析 body 等。调用 <code>next()</code> 交给下一个中间件，不调用则请求到此为止。</p></div><h1 id="三、webpack-篇"><a href="#三、webpack-篇" class="headerlink" title="三、webpack 篇"></a>三、webpack 篇</h1><h2 id="为什么需要它"><a href="#为什么需要它" class="headerlink" title="为什么需要它"></a>为什么需要它</h2><p>浏览器原生只认识 HTML&#x2F;CSS&#x2F;JS，而现代开发会用到 ES6+ 语法、TypeScript、Sass、Vue 单文件组件、模块化 import……webpack 的作用就是<strong>把这些源码转换、打包成浏览器可直接运行的静态资源</strong>，顺带做压缩、分割、加 hash 缓存等优化。</p><h2 id="五个核心概念"><a href="#五个核心概念" class="headerlink" title="五个核心概念"></a>五个核心概念</h2><table><thead><tr><th>概念</th><th>作用</th></tr></thead><tbody><tr><td><strong>entry</strong></td><td>入口，从哪个文件开始分析依赖</td></tr><tr><td><strong>output</strong></td><td>输出，打包后放哪、叫什么</td></tr><tr><td><strong>loader</strong></td><td>转换器，让 webpack 能处理非 JS 文件（CSS、图片、TS…）</td></tr><tr><td><strong>plugin</strong></td><td>插件，做 loader 做不了的事（生成 HTML、抽离 CSS、压缩…）</td></tr><tr><td><strong>mode</strong></td><td><code>development</code> &#x2F; <code>production</code>，决定内置优化策略</td></tr></tbody></table><h2 id="最小可用配置"><a href="#最小可用配置" class="headerlink" title="最小可用配置"></a>最小可用配置</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install webpack webpack-cli -D</span><br></pre></td></tr></table></figure><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// webpack.config.js</span></span><br><span class="line"><span class="keyword">const</span> path = <span class="built_in">require</span>(<span class="string">&#x27;path&#x27;</span>)</span><br><span class="line"><span class="keyword">const</span> <span class="title class_">HtmlWebpackPlugin</span> = <span class="built_in">require</span>(<span class="string">&#x27;html-webpack-plugin&#x27;</span>)</span><br><span class="line"></span><br><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = &#123;</span><br><span class="line">  <span class="attr">mode</span>: <span class="string">&#x27;development&#x27;</span>,                       <span class="comment">// 开发模式</span></span><br><span class="line">  <span class="attr">entry</span>: <span class="string">&#x27;./src/main.js&#x27;</span>,                    <span class="comment">// 入口</span></span><br><span class="line">  <span class="attr">output</span>: &#123;</span><br><span class="line">    <span class="attr">path</span>: path.<span class="title function_">resolve</span>(__dirname, <span class="string">&#x27;dist&#x27;</span>),   <span class="comment">// 输出目录（必须是绝对路径）</span></span><br><span class="line">    <span class="attr">filename</span>: <span class="string">&#x27;js/[name].[contenthash:8].js&#x27;</span>,</span><br><span class="line">    <span class="attr">clean</span>: <span class="literal">true</span>                              <span class="comment">// 每次打包清空 dist</span></span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="attr">module</span>: &#123;</span><br><span class="line">    <span class="attr">rules</span>: [</span><br><span class="line">      <span class="comment">// 处理 CSS</span></span><br><span class="line">      &#123; <span class="attr">test</span>: <span class="regexp">/\.css$/</span>, <span class="attr">use</span>: [<span class="string">&#x27;style-loader&#x27;</span>, <span class="string">&#x27;css-loader&#x27;</span>] &#125;,</span><br><span class="line">      <span class="comment">// 处理 ES6+ 语法</span></span><br><span class="line">      &#123;</span><br><span class="line">        <span class="attr">test</span>: <span class="regexp">/\.js$/</span>,</span><br><span class="line">        <span class="attr">exclude</span>: <span class="regexp">/node_modules/</span>,</span><br><span class="line">        <span class="attr">use</span>: <span class="string">&#x27;babel-loader&#x27;</span></span><br><span class="line">      &#125;,</span><br><span class="line">      <span class="comment">// 图片（webpack 5 内置 asset 模块，不再需要 file-loader）</span></span><br><span class="line">      &#123; <span class="attr">test</span>: <span class="regexp">/\.(png|jpg|gif|svg)$/</span>, <span class="attr">type</span>: <span class="string">&#x27;asset&#x27;</span>, <span class="attr">parser</span>: &#123; <span class="attr">dataUrlCondition</span>: &#123; <span class="attr">maxSize</span>: <span class="number">8</span> * <span class="number">1024</span> &#125; &#125; &#125;</span><br><span class="line">    ]</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="attr">plugins</span>: [</span><br><span class="line">    <span class="keyword">new</span> <span class="title class_">HtmlWebpackPlugin</span>(&#123; <span class="attr">template</span>: <span class="string">&#x27;./public/index.html&#x27;</span> &#125;)</span><br><span class="line">  ],</span><br><span class="line">  <span class="attr">devServer</span>: &#123;</span><br><span class="line">    <span class="attr">port</span>: <span class="number">8080</span>,</span><br><span class="line">    <span class="attr">open</span>: <span class="literal">true</span>,</span><br><span class="line">    <span class="attr">hot</span>: <span class="literal">true</span>                                <span class="comment">// 热更新</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><code>package.json</code> 里加脚本：</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">&quot;scripts&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;dev&quot;</span><span class="punctuation">:</span> <span class="string">&quot;webpack serve --mode development&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;build&quot;</span><span class="punctuation">:</span> <span class="string">&quot;webpack --mode production&quot;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><h2 id="常用-loader"><a href="#常用-loader" class="headerlink" title="常用 loader"></a>常用 loader</h2><table><thead><tr><th>loader</th><th>作用</th></tr></thead><tbody><tr><td><code>babel-loader</code></td><td>ES6+ &#x2F; JSX 转 ES5（配合 <code>@babel/preset-env</code>）</td></tr><tr><td><code>css-loader</code></td><td>解析 CSS 中的 <code>@import</code>、<code>url()</code></td></tr><tr><td><code>style-loader</code></td><td>把 CSS 注入到 <code>&lt;style&gt;</code> 标签</td></tr><tr><td><code>sass-loader</code></td><td>编译 Sass&#x2F;SCSS</td></tr><tr><td><code>less-loader</code></td><td>编译 Less</td></tr><tr><td><code>postcss-loader</code></td><td>自动加浏览器前缀、转换新语法</td></tr><tr><td><code>vue-loader</code></td><td>处理 <code>.vue</code> 单文件组件</td></tr><tr><td><code>ts-loader</code> &#x2F; <code>babel-loader</code></td><td>处理 TypeScript</td></tr></tbody></table><div class="note warning flat"><p><code>use</code> 数组里的 loader <strong>执行顺序是从右到左（从后往前）</strong>。所以 <code>[&#39;style-loader&#39;, &#39;css-loader&#39;]</code> 是先跑 css-loader 再跑 style-loader，写反了会报错。</p></div><h2 id="常用-plugin"><a href="#常用-plugin" class="headerlink" title="常用 plugin"></a>常用 plugin</h2><table><thead><tr><th>plugin</th><th>作用</th></tr></thead><tbody><tr><td><code>html-webpack-plugin</code></td><td>自动生成 HTML 并注入打包后的 JS&#x2F;CSS</td></tr><tr><td><code>mini-css-extract-plugin</code></td><td>把 CSS 抽离成独立文件（生产环境用，替代 style-loader）</td></tr><tr><td><code>css-minimizer-webpack-plugin</code></td><td>压缩 CSS</td></tr><tr><td><code>terser-webpack-plugin</code></td><td>压缩 JS（生产模式默认启用）</td></tr><tr><td><code>clean-webpack-plugin</code></td><td>清空输出目录（也可直接用 <code>output.clean</code>）</td></tr><tr><td><code>copy-webpack-plugin</code></td><td>拷贝无需处理的静态文件</td></tr><tr><td><code>webpack-bundle-analyzer</code></td><td>可视化分析打包体积</td></tr></tbody></table><h2 id="生产环境优化"><a href="#生产环境优化" class="headerlink" title="生产环境优化"></a>生产环境优化</h2><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">optimization</span>: &#123;</span><br><span class="line">  <span class="attr">usedExports</span>: <span class="literal">true</span>,              <span class="comment">// Tree Shaking：剔除未使用的导出</span></span><br><span class="line">  <span class="attr">minimize</span>: <span class="literal">true</span>,                 <span class="comment">// 压缩</span></span><br><span class="line">  <span class="attr">splitChunks</span>: &#123;</span><br><span class="line">    <span class="attr">chunks</span>: <span class="string">&#x27;all&#x27;</span>,                <span class="comment">// 代码分割</span></span><br><span class="line">    <span class="attr">cacheGroups</span>: &#123;</span><br><span class="line">      <span class="attr">vendor</span>: &#123;                   <span class="comment">// 把 node_modules 单独打包，便于长期缓存</span></span><br><span class="line">        <span class="attr">test</span>: <span class="regexp">/[\\/]node_modules[\\/]/</span>,</span><br><span class="line">        <span class="attr">name</span>: <span class="string">&#x27;vendors&#x27;</span>,</span><br><span class="line">        <span class="attr">priority</span>: <span class="number">10</span></span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>几条实用建议：</p><ul><li><strong>文件名加 <code>[contenthash]</code></strong> —— 内容不变则文件名不变，浏览器可长期缓存</li><li><strong>路由懒加载</strong> —— 用动态 <code>import()</code> 把不同页面拆成独立 chunk</li><li><strong>按需引入</strong> —— 组件库用 <code>babel-plugin-import</code> 之类只打包用到的部分</li><li><strong>分析体积</strong> —— 用 <code>webpack-bundle-analyzer</code> 找出超大依赖</li></ul><h2 id="环境变量区分"><a href="#环境变量区分" class="headerlink" title="环境变量区分"></a>环境变量区分</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install cross-env -D</span><br></pre></td></tr></table></figure><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">&quot;scripts&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;build:prod&quot;</span><span class="punctuation">:</span> <span class="string">&quot;cross-env NODE_ENV=production webpack&quot;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">new</span> webpack.<span class="title class_">DefinePlugin</span>(&#123;</span><br><span class="line">  <span class="string">&#x27;process.env.NODE_ENV&#x27;</span>: <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(process.<span class="property">env</span>.<span class="property">NODE_ENV</span>)</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure><h2 id="webpack-vs-Vite"><a href="#webpack-vs-Vite" class="headerlink" title="webpack vs Vite"></a>webpack vs Vite</h2><table><thead><tr><th>对比</th><th>webpack</th><th>Vite</th></tr></thead><tbody><tr><td>启动方式</td><td>先整体打包再启动</td><td>原生 ESM，按需编译</td></tr><tr><td>冷启动</td><td>项目大时较慢</td><td>极快</td></tr><tr><td>热更新</td><td>随项目增大变慢</td><td>几乎恒定快</td></tr><tr><td>生态成熟度</td><td>⭐ 极高，插件齐全</td><td>已很完善，仍在追赶</td></tr><tr><td>适用场景</td><td>大型存量项目、复杂定制</td><td>新项目、追求开发体验</td></tr></tbody></table><div class="note info flat"><p>不用纠结：<strong>新项目直接用 Vite</strong>，开发体验差距明显；公司老项目继续用 webpack，迁移成本往往不划算。</p></div><h2 id="常见坑速查"><a href="#常见坑速查" class="headerlink" title="常见坑速查"></a>常见坑速查</h2><table><thead><tr><th>现象</th><th>原因</th><th>解法</th></tr></thead><tbody><tr><td>请求跨域被拦</td><td>浏览器同源策略</td><td>后端开 CORS 或配 devServer proxy</td></tr><tr><td><code>result.data</code> 是 undefined</td><td>axios 把数据包在 <code>data</code> 里</td><td>用 <code>res.data</code> 或解构 <code>const &#123; data &#125; = await ...</code></td></tr><tr><td>loader 顺序报错</td><td><code>use</code> 数组写反了</td><td>记住从右往左执行</td></tr><tr><td>打包后图片 404</td><td>路径配置问题</td><td>设置 <code>output.publicPath</code></td></tr><tr><td>样式没生效</td><td>生产环境用了 style-loader</td><td>换成 mini-css-extract-plugin</td></tr><tr><td>打包很慢</td><td>没有排除 node_modules &#x2F; 未开缓存</td><td><code>exclude: /node_modules/</code>、开启 <code>cache: &#123; type: &#39;filesystem&#39; &#125;</code></td></tr></tbody></table><hr><div class="note success flat"><p><strong>学习建议</strong>：先能用 axios 跑通一次接口 → 再用 Node 写个简单接口给自己调 → 最后用构建工具把项目跑起来。这条线走完，前后端是怎么配合的就彻底明白了。</p></div>]]></content>
    
    
    <summary type="html">Ajax、Node.js 与 webpack 学习笔记，记录前后端交互、服务端基础与打包工具的使用经验。</summary>
    
    
    
    <category term="前端开发" scheme="https://www.amoit.top/categories/%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91/"/>
    
    
    <category term="前端" scheme="https://www.amoit.top/tags/%E5%89%8D%E7%AB%AF/"/>
    
    <category term="Ajax" scheme="https://www.amoit.top/tags/Ajax/"/>
    
    <category term="Node.js" scheme="https://www.amoit.top/tags/Node-js/"/>
    
    <category term="webpack" scheme="https://www.amoit.top/tags/webpack/"/>
    
  </entry>
  
  <entry>
    <title>毕业论文</title>
    <link href="https://www.amoit.top/posts/graduation-thesis/"/>
    <id>https://www.amoit.top/posts/graduation-thesis/</id>
    <published>2024-04-07T14:47:01.000Z</published>
    <updated>2026-10-06T12:33:25.037Z</updated>
    
    <content type="html"><![CDATA[<h1 id="毕业论文"><a href="#毕业论文" class="headerlink" title="毕业论文"></a>毕业论文</h1><h2 id="AI改论文"><a href="#AI改论文" class="headerlink" title="AI改论文"></a>AI改论文</h2><p>AI论文网站<br>chatgpt写论文指令全集</p><h3 id="论文网站-2024-4-6更新"><a href="#论文网站-2024-4-6更新" class="headerlink" title="论文网站 2024.4.6更新"></a>论文网站 2024.4.6更新</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">论文全生成网站:https://gpt.chachongz.com/</span><br><span class="line">半手动:</span><br><span class="line">https://yiyan.baidu.com/</span><br><span class="line">https://tiangong.kunlun.com</span><br></pre></td></tr></table></figure><h3 id="论文写"><a href="#论文写" class="headerlink" title="论文写"></a>论文写</h3><h3 id="论文题目寻找"><a href="#论文题目寻找" class="headerlink" title="论文题目寻找"></a>论文题目寻找</h3><p>本科：Vue+SpringBoot，微信小程序，java，uni-app </p><h4 id="详细"><a href="#详细" class="headerlink" title="详细"></a>详细</h4><p>根据论文题目“***”的第**章文献综述每一节展开详细描述2千字</p><h3 id="中文润色"><a href="#中文润色" class="headerlink" title="中文润色"></a>中文润色</h3><p><code>文章改写，修正:https://xiezuocat.com/  </code><br>（本网站改写和检查错别字等问题很有用）</p><h3 id="英文润色"><a href="#英文润色" class="headerlink" title="英文润色"></a>英文润色</h3><h3 id="提升论文质量"><a href="#提升论文质量" class="headerlink" title="提升论文质量"></a>提升论文质量</h3><h4 id="国内外研究现状"><a href="#国内外研究现状" class="headerlink" title="国内外研究现状"></a>国内外研究现状</h4><p>1.筛选相应文章<br>知网-关键字搜索-相关度搜索-勾选文献-导出文献（查新格式）- doc导出<br>2.使用文心一言工具<br>选择阅览文件功能-话术提问-现在你是一个很有经验的博士，我给你发了一些参考文献列表，你要根据文档的文献写一下国内和国外研究现状（文献综述），首先要把相似研究方向的文献归为一类，先总结研究方向的内容，然后介绍这个方向涉及的文献作者姓名、发表年份时间、当时的方法或观点、主要发现贡献和不足这些内容。比如多篇论文研究方向类似就可以归为一类，这个研究方向下面的文献就可以按发表时间顺序排序依次描述。最后根据当前研究的空缺方向写一下未来的研究方向。你的回答要包括文档的所有文献，总字5千字以上</p><h3 id="格式修改问题"><a href="#格式修改问题" class="headerlink" title="格式修改问题"></a>格式修改问题</h3><p>1.目录修改<br>将文章一级标题，二级标题设定好-引用-更新全部目录（注意:不要只改页面码容易出现错误）<br>2.尾注<br>引用-插入尾注</p><h3 id="AI指令使用"><a href="#AI指令使用" class="headerlink" title="AI指令使用"></a>AI指令使用</h3><p>AI 写作指令：<br>正文写作：<br>论文课题是 《本<em>中水水中》，请帮我完成其中一小节内容：<strong>水中本</strong>〈输入需要完成课题和<br>小标题，最好一、二级标题一井输入）<br>提纲指令：<br>我的论文课题是 《<strong>本</strong></em>》，请帮我列出论文目录，细化到三级标题。（可以自行调整，<br>要求越精细，Al 输出效果越好）<br>开题报告指令：<br>我的论文课题是 《<em>本本</em><em><em>)，请帮我写下开题报告中的研究背景（可以自行更改研究背<br>景&#x2F;研究目的&#x2F;研究意义等）<br>论文致谢指令：<br>我的论文 课题是 《本中中中中</em>），我在中</em><em>大学就读本</em>专业，导师是**，请帮我写一个论<br>文致谢。300 左右即可。(可以自行调整，要求越精细，AI 输出效果越好）<br>扩写：<br>请使用学术语言，扩写以下内容：本<em>中</em><em><strong>（输入需要扩写的内容，指令可以自行修改。<br>比如对字数，内容方向等做出限定）<br>缩写：<br>请使用学术语言，缩写以下内容：</strong></em>***（输入需要缩写的内容，指令可以自行修改）<br>论文降重：<br>小幅度降重：请将这些内容进行改写，具备逻辑性和学术凤格。可以通过调換语句顺<br>序，或替换同义词来达到改写目的：*<em>來为中</em>（复制需要降重的内容）<br>大幅降重第一步：提炼以下内容的要点，内容简练一些：<strong>中本</strong>（输入需要降重的内<br>容）<br>大幅降重第二步：将以下内容进行改写加扩写，撰写（论文名）中关于（原文中小标<br>题的内容）的一段内容，要求保证原创性，学术性，字数（原文中这一段的宇数）：*<em>來中中</em><br>(复制第一步生成的内容即可，创建新对话后再进行第二步，才能达到更好的降重效果）</p><h2 id="系统设计中的业务流程图等制作"><a href="#系统设计中的业务流程图等制作" class="headerlink" title="系统设计中的业务流程图等制作"></a>系统设计中的业务流程图等制作</h2><p>网站:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">https://www.processon.com/</span><br><span class="line">https://www.zhihu.com/question/20177573</span><br></pre></td></tr></table></figure><h2 id="CSDN-中获取毕业论文源码模版方式"><a href="#CSDN-中获取毕业论文源码模版方式" class="headerlink" title="CSDN 中获取毕业论文源码模版方式"></a>CSDN 中获取毕业论文源码模版方式</h2><h3 id="1-寻找相应程序"><a href="#1-寻找相应程序" class="headerlink" title="1.寻找相应程序"></a>1.寻找相应程序</h3><h3 id="2-避雷无内容毕业论文"><a href="#2-避雷无内容毕业论文" class="headerlink" title="2.避雷无内容毕业论文"></a>2.避雷无内容毕业论文</h3><h2 id="绘图软件推荐"><a href="#绘图软件推荐" class="headerlink" title="绘图软件推荐"></a>绘图软件推荐</h2><h3 id=""><a href="#" class="headerlink" title=""></a></h3><p><code>draw.io 在线绘图（‘版本较老没有很智能，但是功能比较齐全，适合专业绘图’） https://app.diagrams.net/  ProcessON 在线绘图（‘功能较新，适合简单毕设或多人协作’） https://www.processon.com/</code></p><h2 id="Vue-前端开启时出现的问题"><a href="#Vue-前端开启时出现的问题" class="headerlink" title="Vue 前端开启时出现的问题"></a>Vue 前端开启时出现的问题</h2><h3 id="1"><a href="#1" class="headerlink" title="1."></a>1.</h3><p><code>npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR! my-vue3-vite-project@0.0.0 dev: `vite` npm ERR! Exit status 1 npm ERR!  npm ERR! Failed at the my-vue3-vite-project@0.0.0 dev script. npm ERR! This is probably not a problem with npm. There is likely additional logging output above.</code><br>解决方法 node升级<br><code>1.npm cache clean -f 2.npm install -g n 3.sudo n 18.19.0  </code></p>]]></content>
    
    
    <summary type="html">毕业论文写作过程与资料整理，包含选题、文献综述、格式排版与答辩准备的相关记录。</summary>
    
    
    
    <category term="学海拾遗" scheme="https://www.amoit.top/categories/%E5%AD%A6%E6%B5%B7%E6%8B%BE%E9%81%97/"/>
    
    
    <category term="论文" scheme="https://www.amoit.top/tags/%E8%AE%BA%E6%96%87/"/>
    
    <category term="写作" scheme="https://www.amoit.top/tags/%E5%86%99%E4%BD%9C/"/>
    
  </entry>
  
  <entry>
    <title>矢量图与图片素材网站推荐</title>
    <link href="https://www.amoit.top/posts/vector-icon-image-sites/"/>
    <id>https://www.amoit.top/posts/vector-icon-image-sites/</id>
    <published>2024-01-11T15:22:37.329Z</published>
    <updated>2026-10-06T14:56:12.701Z</updated>
    
    <content type="html"><![CDATA[<div class="note info flat"><p>做前端或写博客时，找图往往比写代码还费时间。这篇把自己常用的素材站按<strong>图标 &#x2F; 图片 &#x2F; 插画 &#x2F; 配色 &#x2F; 处理工具</strong>分类整理，标了是否免费商用和各自的特点，随取随用。</p></div><h2 id="一、图标图标库"><a href="#一、图标图标库" class="headerlink" title="一、图标图标库"></a>一、图标图标库</h2><div class="note warning flat"><p>先说结论：<strong>日常开发首选 Iconify</strong>，它聚合了 200+ 套图标集（含 Material、Lucide、Heroicons、Carbon 等），一个库解决所有需求，支持按需引入。</p></div><table><thead><tr><th>站点</th><th>特点</th><th>免费商用</th><th>备注</th></tr></thead><tbody><tr><td><a href="https://iconify.design/">Iconify</a></td><td>聚合 200+ 图标集，20 万+ 图标</td><td>✅</td><td>强烈推荐，Vue&#x2F;React 都有组件</td></tr><tr><td><a href="https://www.iconfont.cn/">iconfont 阿里巴巴矢量图标库</a></td><td>中文图标最全，可建项目打包</td><td>⚠️ 需注意</td><td>国内访问快，但商用前看清授权</td></tr><tr><td><a href="https://www.flaticon.com/">Flaticon</a> <strong>【强推】</strong></td><td>图标海量，风格统一</td><td>⚠️ 免费需署名</td><td>免署名需订阅会员</td></tr><tr><td><a href="https://lucide.dev/">Lucide</a></td><td>Feather 的续作，线性风、极简</td><td>✅</td><td>前端项目常用，体积很小</td></tr><tr><td><a href="https://heroicons.com/">Heroicons</a></td><td>Tailwind 团队出品，两种风格</td><td>✅</td><td>与 Tailwind 生态最搭</td></tr><tr><td><a href="https://remixicon.com/">Remix Icon</a></td><td>中性风格，2600+ 图标</td><td>✅</td><td>中文文档友好</td></tr><tr><td><a href="https://iconpark.oceanengine.com/">IconPark</a></td><td>字节出品，可在线调线宽&#x2F;颜色&#x2F;端点</td><td>✅</td><td>一套图标四种主题</td></tr><tr><td><a href="https://fontawesome.com/">Font Awesome</a></td><td>老牌，免费版够用</td><td>⚠️ 部分收费</td><td>生态最广</td></tr><tr><td><a href="https://icons.getbootstrap.com/">Bootstrap Icons</a></td><td>官方出品，MIT 协议</td><td>✅</td><td>不依赖 Bootstrap 也能用</td></tr><tr><td><a href="https://simpleicons.org/">Simple Icons</a></td><td>品牌 Logo 图标（微信、GitHub 等）</td><td>✅</td><td>做友链、技术栈展示很合适</td></tr></tbody></table><p>用 Iconify 在 Vue &#x2F; React 里的写法：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">npm install @iconify/vue      <span class="comment"># Vue</span></span><br><span class="line">npm install @iconify/react    <span class="comment"># React</span></span><br></pre></td></tr></table></figure><figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">Icon</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;@iconify/react&#x27;</span></span><br><span class="line">&lt;<span class="title class_">Icon</span> icon=<span class="string">&quot;mdi:home&quot;</span> width=<span class="string">&quot;24&quot;</span> /&gt;</span><br></pre></td></tr></table></figure><p>图标名可以在 <a href="https://icon-sets.iconify.design/">icon-sets.iconify.design</a> 里搜，搜到直接复制。</p><h2 id="二、免费高清图片"><a href="#二、免费高清图片" class="headerlink" title="二、免费高清图片"></a>二、免费高清图片</h2><table><thead><tr><th>站点</th><th>特点</th><th>授权</th></tr></thead><tbody><tr><td><a href="https://unsplash.com/">Unsplash</a></td><td>摄影质感最好，文艺风</td><td>✅ 可商用，无需署名</td></tr><tr><td><a href="https://www.pexels.com/">Pexels</a></td><td>图片 + 视频都有，中文界面</td><td>✅ 可商用，无需署名</td></tr><tr><td><a href="https://pixabay.com/">Pixabay</a></td><td>图多，含插画与矢量</td><td>✅ 可商用（注意肖像&#x2F;商标）</td></tr><tr><td><a href="https://stocksnap.io/">StockSnap</a></td><td>每周更新，分类清晰</td><td>✅ CC0</td></tr><tr><td><a href="https://burst.shopify.com/">Burst</a></td><td>Shopify 出品，电商场景友好</td><td>✅ 可商用</td></tr><tr><td><a href="https://www.foodiesfeed.com/">Foodiesfeed</a></td><td>美食类专用</td><td>✅ 部分免费</td></tr><tr><td><a href="https://www.51yuansu.com/">觅元素</a></td><td>中文，免抠 PNG&#x2F;背景素材多</td><td>⚠️ 有免费额度</td></tr></tbody></table><div class="note info flat"><p>配图找封面时，<strong>Unsplash + Pexels 二选一就够了</strong>，别在素材站里逛太久——挑图的时间成本远比想象中高。选定后统一裁成同一比例（如 16:9），整站观感会整齐很多。</p></div><h2 id="三、插画资源"><a href="#三、插画资源" class="headerlink" title="三、插画资源"></a>三、插画资源</h2><p>做空状态页、404 页、Banner 时特别好用：</p><table><thead><tr><th>站点</th><th>风格</th><th>特点</th></tr></thead><tbody><tr><td><a href="https://undraw.co/">unDraw</a></td><td>扁平线条、可在线改主色</td><td>⭐ 最实用，改色后直接下载 SVG</td></tr><tr><td><a href="https://storyset.com/">Storyset</a></td><td>场景插画，可编辑人物&#x2F;配色</td><td>免费版需署名</td></tr><tr><td><a href="https://www.opendoodles.com/">Open Doodles</a></td><td>手绘涂鸦风</td><td>✅ CC0</td></tr><tr><td><a href="https://openpeeps.com/">Open Peeps</a></td><td>手绘人物头像库</td><td>✅ 可拼组合</td></tr><tr><td><a href="https://blush.design/">Blush</a></td><td>可自由组合人物插画</td><td>免费版有限制</td></tr><tr><td><a href="https://iradesign.io/">IRA Design</a></td><td>渐变色插画，可配色</td><td>✅</td></tr><tr><td><a href="https://www.drawkit.com/">drawKit</a></td><td>成套插画包</td><td>部分免费</td></tr><tr><td><a href="https://www.manypixels.co/gallery">ManyPixels</a></td><td>扁平插画，风格统一</td><td>✅ 可商用</td></tr><tr><td><a href="https://www.freepik.com/">Freepik</a></td><td>素材最全（图&#x2F;矢量&#x2F;PSD）</td><td>⚠️ 免费需署名</td></tr></tbody></table><h2 id="四、背景、纹理与小元素"><a href="#四、背景、纹理与小元素" class="headerlink" title="四、背景、纹理与小元素"></a>四、背景、纹理与小元素</h2><table><thead><tr><th>站点</th><th>用途</th></tr></thead><tbody><tr><td><a href="https://heropatterns.com/">Hero Patterns</a></td><td>可配色的 SVG 背景纹理，直接复制到 CSS</td></tr><tr><td><a href="https://www.transparenttextures.com/">Transparent Textures</a></td><td>叠加型纹理，做质感背景</td></tr><tr><td><a href="https://www.shapedivider.app/">Shape Divider</a></td><td>生成波浪&#x2F;斜切分隔形状，复制 SVG</td></tr><tr><td><a href="https://www.cleanpng.com/">CleanPNG</a></td><td>免抠透明 PNG</td></tr><tr><td><a href="https://www.remove.bg/">Remove.bg</a></td><td>一键抠图去背景</td></tr><tr><td><a href="https://excalidraw.com/">Excalidraw</a></td><td>手绘风示意图，画流程图神器</td></tr></tbody></table><h2 id="五、配色与字体"><a href="#五、配色与字体" class="headerlink" title="五、配色与字体"></a>五、配色与字体</h2><table><thead><tr><th>类型</th><th>推荐</th></tr></thead><tbody><tr><td>配色方案</td><td><a href="https://coolors.co/">Coolors</a>（一键生成）、<a href="https://colorhunt.co/">Color Hunt</a>（现成搭配）</td></tr><tr><td>中国传统色</td><td><a href="https://zhongguose.com/">中国色</a>（名字好听：月白、竹青、胭脂）</td></tr><tr><td>渐变</td><td><a href="https://uigradients.com/">UI Gradients</a>、<a href="https://cssgradient.io/">CSS Gradient</a></td></tr><tr><td>对比度检查</td><td><a href="https://contrast-ratio.com/">Contrast Ratio</a>（检查文字是否可读）</td></tr><tr><td>免费字体</td><td><a href="https://fonts.google.com/">Google Fonts</a>、<a href="https://www.hellofont.cn/">字由</a>（中文商用字体）</td></tr></tbody></table><div class="note danger flat"><p><strong>字体是版权重灾区</strong>。很多「免费下载」的字体只有个人授权，商用会被追责。中文商用以思源黑体&#x2F;思源宋体（SIL 协议，可商用）最安全。</p></div><h2 id="六、图片处理工具"><a href="#六、图片处理工具" class="headerlink" title="六、图片处理工具"></a>六、图片处理工具</h2><p>下载完别直接用，压一压体积能小一个数量级：</p><table><thead><tr><th>工具</th><th>用途</th></tr></thead><tbody><tr><td><a href="https://tinypng.com/">TinyPNG</a></td><td>PNG&#x2F;JPG 有损压缩，效果好，免费每月 500 张</td></tr><tr><td><a href="https://squoosh.app/">Squoosh</a></td><td>Google 出品，可实时对比、转 WebP &#x2F; AVIF</td></tr><tr><td><a href="https://jakearchibald.github.io/svgomg">SVGOMG</a></td><td>SVG 精简，去掉编辑器留下的冗余属性</td></tr><tr><td><a href="https://www.iloveimg.com/">iLoveIMG</a></td><td>批量压缩、裁剪、格式转换</td></tr><tr><td><a href="https://convertio.co/">Convertio</a></td><td>格式互转（WebP ↔ PNG 等）</td></tr></tbody></table><div class="note success flat"><p><strong>格式怎么选</strong>：照片用 <strong>WebP</strong>（比 JPG 小 30% 左右）；图标&#x2F;Logo&#x2F;简单图形用 <strong>SVG</strong>（矢量无损、可用 CSS 改色）；需要动画的小图用 <strong>APNG 或 GIF</strong>（GIF 体积大，优先 APNG&#x2F;WebP 动图）。</p></div><h2 id="七、版权避坑（重要）"><a href="#七、版权避坑（重要）" class="headerlink" title="七、版权避坑（重要）"></a>七、版权避坑（重要）</h2><div class="note danger flat"><p>免费下载 ≠ 可以随便用。三类最常见的雷：</p></div><ol><li><strong>需署名却没署名</strong> —— Flaticon、Freepik、Storyset 的免费资源大多要求标注作者，商用前务必确认</li><li><strong>仅个人授权却商用</strong> —— 字体、部分国内素材站常见，下载页的小字才写</li><li><strong>含第三方元素</strong> —— 图片里有可识别的人物肖像、品牌 Logo、艺术品，即使图片本身免费也可能侵权</li></ol><p>安全的做法：</p><ul><li>优先用明确标注 <strong>CC0 &#x2F; 可商用</strong> 的站点（Unsplash、Pexels、Pixabay）</li><li>商业项目不留隐患就买会员（Flaticon、Freepik 年费不高）</li><li>涉及人物肖像的素材，谨慎用在商业宣传中</li></ul><h2 id="八、我的常用组合"><a href="#八、我的常用组合" class="headerlink" title="八、我的常用组合"></a>八、我的常用组合</h2><div class="tabs" id="常用组合"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#常用组合-1"><i class="fas fa-pen"></i>写博客配图</button></li><li class="tab"><button type="button" data-href="#常用组合-2"><i class="fas fa-code"></i>前端项目</button></li><li class="tab"><button type="button" data-href="#常用组合-3"><i class="fas fa-file-powerpoint"></i>PPT / 汇报</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="常用组合-1"><p>封面 → Unsplash &#x2F; Pexels<br>技术示意图 → Excalidraw 手绘<br>图标 → Iconify（Lucide 集）<br>压缩 → TinyPNG 过一遍再上传</p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="常用组合-2"><p>UI 图标 → Iconify 按需引入<br>空状态插画 → unDraw 改主色<br>背景纹理 → Hero Patterns<br>字体 → 思源黑体 &#x2F; Inter</p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="常用组合-3"><p>配图 → Pixabay（中文搜索好）<br>人物插画 → Open Peeps &#x2F; Blush<br>配色 → Color Hunt 抄一套<br>图标 → iconfont（中文图标全）</p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><hr><div class="note success flat"><p>工具不在多，在于<strong>用得顺手</strong>。上面这些挑三五个放进书签栏，比收藏几十个站然后每次都重新找要高效得多。</p></div>]]></content>
    
    
    <summary type="html">常用的免费矢量图与图片素材网站推荐，包含图标库、插画与设计资源站点，适合前端开发与平面设计取素材。</summary>
    
    
    
    <category term="工具效率" scheme="https://www.amoit.top/categories/%E5%B7%A5%E5%85%B7%E6%95%88%E7%8E%87/"/>
    
    
    <category term="设计资源" scheme="https://www.amoit.top/tags/%E8%AE%BE%E8%AE%A1%E8%B5%84%E6%BA%90/"/>
    
    <category term="素材网站" scheme="https://www.amoit.top/tags/%E7%B4%A0%E6%9D%90%E7%BD%91%E7%AB%99/"/>
    
    <category term="矢量图" scheme="https://www.amoit.top/tags/%E7%9F%A2%E9%87%8F%E5%9B%BE/"/>
    
  </entry>
  
  <entry>
    <title>Butterfly 主题更改</title>
    <link href="https://www.amoit.top/posts/hexo-butterfly-theme-tweak/"/>
    <id>https://www.amoit.top/posts/hexo-butterfly-theme-tweak/</id>
    <published>2024-01-09T12:59:01.000Z</published>
    <updated>2026-10-06T14:57:38.695Z</updated>
    
    <content type="html"><![CDATA[<div class="note info flat"><p>Butterfly 是 Hexo 里配置最细致的主题之一，好处是几乎什么都能改，代价是配置文件长得让人迷路。这篇把常用改动按「改哪里 → 改什么 → 效果」的方式记下来，配的正是本站（Butterfly 4.x）。</p></div><h2 id="一、先分清两个配置文件"><a href="#一、先分清两个配置文件" class="headerlink" title="一、先分清两个配置文件"></a>一、先分清两个配置文件</h2><p>新手最容易改错文件，先记住这张表：</p><table><thead><tr><th>文件</th><th>管什么</th><th>什么时候动</th></tr></thead><tbody><tr><td><code>_config.yml</code></td><td><strong>站点</strong>：标题、作者、URL、部署、插件</td><td>换域名、改部署、装插件时</td></tr><tr><td><code>_config.butterfly.yml</code></td><td><strong>主题外观</strong>：导航、配色、侧边栏、评论</td><td>改样式、加功能时</td></tr></tbody></table><div class="note warning flat"><p>主题配置要放在 <code>_config.butterfly.yml</code>（根目录），<strong>不要直接改 <code>themes/butterfly/_config.yml</code></strong> —— 主题一升级就会被覆盖，改动全丢。</p></div><p>改完记得重新生成：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npx hexo clean &amp;&amp; npx hexo generate &amp;&amp; npx hexo server   <span class="comment"># 本地预览 http://localhost:4000</span></span><br></pre></td></tr></table></figure><h2 id="二、搜索功能配置"><a href="#二、搜索功能配置" class="headerlink" title="二、搜索功能配置"></a>二、搜索功能配置</h2><p>Butterfly 内置三种搜索方案，按推荐度排序：</p><div class="tabs" id="搜索方案"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#搜索方案-1"><i class="fas fa-desktop"></i>本地搜索</button></li><li class="tab"><button type="button" data-href="#搜索方案-2"><i class="fas fa-bolt"></i>Algolia</button></li><li class="tab"><button type="button" data-href="#搜索方案-3"><i class="fas fa-magnifying-glass"></i>DocSearch</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="搜索方案-1"><p><strong>零依赖、最省心</strong>，文章量在几百篇以内足够用。</p><ol><li>安装生成索引的插件：</li></ol><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install hexo-generator-search --save</span><br></pre></td></tr></table></figure><ol start="2"><li>在 <code>_config.butterfly.yml</code> 里开启：</li></ol><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">local_search:</span></span><br><span class="line">  <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">preload:</span> <span class="literal">true</span>          <span class="comment"># 进入页面就预加载索引</span></span><br><span class="line">  <span class="attr">top_n_per_article:</span> <span class="number">1</span></span><br></pre></td></tr></table></figure><ol start="3"><li>站点 <code>_config.yml</code> 补上生成器配置（默认一般即可）：</li></ol><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">search:</span></span><br><span class="line">  <span class="attr">path:</span> <span class="string">search.xml</span></span><br><span class="line">  <span class="attr">field:</span> <span class="string">post</span>            <span class="comment"># 可选 post / page / all</span></span><br><span class="line">  <span class="attr">content:</span> <span class="literal">true</span></span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="搜索方案-2"><p>搜索体验最好（实时、支持高亮），但需要注册账号并每次部署上传索引，配置稍繁琐。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install hexo-algoliasearch --save</span><br></pre></td></tr></table></figure><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">algolia_search:</span></span><br><span class="line">  <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">hits:</span></span><br><span class="line">    <span class="attr">per_page:</span> <span class="number">6</span></span><br></pre></td></tr></table></figure><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 站点 _config.yml</span></span><br><span class="line"><span class="attr">algolia:</span></span><br><span class="line">  <span class="attr">appId:</span> <span class="string">&#x27;你的 appId&#x27;</span></span><br><span class="line">  <span class="attr">apiKey:</span> <span class="string">&#x27;你的 apiKey&#x27;</span></span><br><span class="line">  <span class="attr">indexName:</span> <span class="string">&#x27;你的 indexName&#x27;</span></span><br></pre></td></tr></table></figure><p>部署前需要执行 <code>hexo algolia</code> 上传索引（要配 <code>HEXO_ALGOLIA_INDEXING_KEY</code> 环境变量）。</p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="搜索方案-3"><p>Algolia 官方为开源文档提供的<strong>免费</strong>搜索服务，需申请通过（站点需公开且内容合规）。原笔记里记的就是它：</p><ol><li>在 <code>_config.butterfly.yml</code> 中加入：</li></ol><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">docsearch:</span></span><br><span class="line">  <span class="attr">enable:</span> <span class="literal">false</span></span><br><span class="line">  <span class="attr">appId:</span></span><br><span class="line">  <span class="attr">apiKey:</span></span><br><span class="line">  <span class="attr">indexName:</span></span><br><span class="line">  <span class="attr">option:</span></span><br></pre></td></tr></table></figure><ol start="2"><li>到 <a href="https://docsearch.algolia.com/apply/">DocSearch 官网</a> 提交申请，通过后 Algolia 会把 <code>appId</code> &#x2F; <code>apiKey</code> &#x2F; <code>indexName</code> 发到你的邮箱</li><li>填进上面的配置并把 <code>enable</code> 改为 <code>true</code></li></ol><div class="note warning flat"><p>DocSearch 靠<strong>爬虫抓取线上站点</strong>建索引，所以必须先把博客部署到公网并提交申请；本地 <code>hexo server</code> 是测不出搜索结果的。</p></div><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="三、导航菜单"><a href="#三、导航菜单" class="headerlink" title="三、导航菜单"></a>三、导航菜单</h2><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">menu:</span></span><br><span class="line">  <span class="string">首页:</span> <span class="string">/</span> <span class="string">||</span> <span class="string">fas</span> <span class="string">fa-home</span></span><br><span class="line">  <span class="string">归档:</span> <span class="string">/archives/</span> <span class="string">||</span> <span class="string">fas</span> <span class="string">fa-archive</span></span><br><span class="line">  <span class="string">标签:</span> <span class="string">/tags/</span> <span class="string">||</span> <span class="string">fas</span> <span class="string">fa-tags</span></span><br><span class="line">  <span class="string">分类:</span> <span class="string">/categories/</span> <span class="string">||</span> <span class="string">fas</span> <span class="string">fa-folder-open</span></span><br><span class="line">  <span class="string">追番:</span> <span class="string">/bangumis/</span> <span class="string">||</span> <span class="string">fas</span> <span class="string">fa-film</span></span><br><span class="line">  <span class="string">友链:</span> <span class="string">/link/</span> <span class="string">||</span> <span class="string">fas</span> <span class="string">fa-link</span></span><br><span class="line">  <span class="string">关于:</span> <span class="string">/about/</span> <span class="string">||</span> <span class="string">fas</span> <span class="string">fa-heart</span></span><br></pre></td></tr></table></figure><p>格式是 <code>显示名: 路径 || 图标类名</code>。图标从 <a href="https://fontawesome.com/search?o=r&m=free">Font Awesome</a> 找，写完整类名即可。</p><div class="note danger flat"><p>菜单里的路径<strong>必须有对应页面</strong>，否则点进去是 404。创建页面用：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">npx hexo new page categories</span><br><span class="line">npx hexo new page tags</span><br><span class="line">npx hexo new page <span class="built_in">link</span></span><br></pre></td></tr></table></figure><p>会在 <code>source/categories/index.md</code> 生成页面，确认里面的 <code>type</code> 字段正确：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">---</span></span><br><span class="line"><span class="attr">title:</span> <span class="string">文章分类</span></span><br><span class="line"><span class="attr">type:</span> <span class="string">&quot;categories&quot;</span>      <span class="comment"># tags 页写 &quot;tags&quot;，友链页写 &quot;link&quot;</span></span><br><span class="line"><span class="meta">---</span></span><br></pre></td></tr></table></figure></div><h2 id="四、站点基础信息"><a href="#四、站点基础信息" class="headerlink" title="四、站点基础信息"></a>四、站点基础信息</h2><p><code>_config.yml</code>（站点配置）：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">title:</span> <span class="string">你的站名</span></span><br><span class="line"><span class="attr">subtitle:</span> <span class="string">副标题</span></span><br><span class="line"><span class="attr">description:</span> <span class="string">站点描述（SEO</span> <span class="string">与分享卡片会用到）</span></span><br><span class="line"><span class="attr">author:</span> <span class="string">你的名字</span></span><br><span class="line"><span class="attr">language:</span> <span class="string">zh-CN</span></span><br><span class="line"><span class="attr">timezone:</span> <span class="string">Asia/Shanghai</span></span><br><span class="line"><span class="attr">url:</span> <span class="string">https://www.example.com</span>      <span class="comment"># ⭐ 必须带 https，否则生成的 sitemap 链接不对</span></span><br></pre></td></tr></table></figure><div class="note warning flat"><p><code>url</code> 一定要和最终访问域名完全一致（含 <code>www</code> 与否）。它决定 sitemap、RSS、文章永久链接，<strong>填错会让百度收录失败</strong>。</p></div><h2 id="五、头图、封面与头像"><a href="#五、头图、封面与头像" class="headerlink" title="五、头图、封面与头像"></a>五、头图、封面与头像</h2><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># _config.butterfly.yml</span></span><br><span class="line"><span class="attr">avatar:</span></span><br><span class="line">  <span class="attr">img:</span> <span class="string">/img/avatar.png</span></span><br><span class="line">  <span class="attr">effect:</span> <span class="literal">true</span>          <span class="comment"># 鼠标悬停时头像旋转</span></span><br><span class="line"></span><br><span class="line"><span class="attr">index_img:</span> <span class="string">/img/home.jpg</span>           <span class="comment"># 首页顶部大图</span></span><br><span class="line"><span class="attr">default_top_img:</span> <span class="string">/img/default.jpg</span>  <span class="comment"># 没指定 cover 的文章用这张</span></span><br><span class="line"><span class="attr">archive_img:</span> <span class="string">/img/archive.jpg</span>      <span class="comment"># 归档页头图</span></span><br><span class="line"></span><br><span class="line"><span class="attr">cover:</span></span><br><span class="line">  <span class="attr">index_enable:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">aside_enable:</span> <span class="literal">true</span>               <span class="comment"># 侧栏最新文章是否显示缩略图</span></span><br><span class="line">  <span class="attr">archives_enable:</span> <span class="literal">true</span></span><br></pre></td></tr></table></figure><p>单篇文章指定封面（front-matter）：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">---</span></span><br><span class="line"><span class="attr">title:</span> <span class="string">文章标题</span></span><br><span class="line"><span class="attr">cover:</span> <span class="string">/img/cover.jpg</span></span><br><span class="line"><span class="meta">---</span></span><br></pre></td></tr></table></figure><div class="note info flat"><p>头图建议尺寸 <strong>1920×1080</strong> 左右、控制在 300KB 以内。太大的话首屏会先白一下，体验很差。统一裁成相同比例，翻页时观感更整齐。</p></div><h2 id="六、侧边栏卡片"><a href="#六、侧边栏卡片" class="headerlink" title="六、侧边栏卡片"></a>六、侧边栏卡片</h2><p><code>aside</code> 控制侧栏显示哪些卡片及排序：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">aside:</span></span><br><span class="line">  <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">hide:</span> <span class="literal">false</span></span><br><span class="line">  <span class="attr">button:</span> <span class="literal">true</span>            <span class="comment"># 是否显示侧栏切换按钮</span></span><br><span class="line">  <span class="attr">mobile:</span> <span class="literal">true</span>            <span class="comment"># 手机端是否显示</span></span><br><span class="line">  <span class="attr">position:</span> <span class="string">right</span>         <span class="comment"># left / right</span></span><br><span class="line">  <span class="attr">display:</span></span><br><span class="line">    <span class="attr">archive:</span> <span class="literal">true</span></span><br><span class="line">    <span class="attr">tag:</span> <span class="literal">true</span></span><br><span class="line">    <span class="attr">category:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">card_author:</span></span><br><span class="line">    <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line">    <span class="attr">description:</span> <span class="string">一句自我介绍</span></span><br><span class="line">  <span class="attr">card_announcement:</span></span><br><span class="line">    <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line">    <span class="attr">content:</span> <span class="string">公告内容，支持</span> <span class="string">HTML</span></span><br><span class="line">  <span class="attr">card_recent_post:</span></span><br><span class="line">    <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line">    <span class="attr">limit:</span> <span class="number">5</span></span><br><span class="line">  <span class="attr">card_newest_comments:</span></span><br><span class="line">    <span class="attr">enable:</span> <span class="literal">false</span>         <span class="comment"># 需要评论系统支持</span></span><br><span class="line">  <span class="string">card_tags</span> <span class="string">/</span> <span class="string">card_categories</span> <span class="string">/</span> <span class="string">card_webinfo</span> <span class="string">...</span></span><br></pre></td></tr></table></figure><p><code>card_webinfo</code> 能显示运行时间、文章字数、访问量（访问量需配合不蒜子等统计）。</p><h2 id="七、评论系统"><a href="#七、评论系统" class="headerlink" title="七、评论系统"></a>七、评论系统</h2><p>本站用的是 Twikoo（免费、基于云函数、国内访问快）：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">comments:</span></span><br><span class="line">  <span class="attr">use:</span> <span class="string">Twikoo</span>        <span class="comment"># 多个用数组： - Twikoo</span></span><br><span class="line">  <span class="attr">text:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">lazyload:</span> <span class="literal">true</span>     <span class="comment"># 滚动到评论区才加载，提速</span></span><br><span class="line">  <span class="attr">count:</span> <span class="literal">true</span>        <span class="comment"># 文章列表显示评论数</span></span><br><span class="line"></span><br><span class="line"><span class="attr">twikoo:</span></span><br><span class="line">  <span class="attr">envId:</span> <span class="string">https://xxx.vercel.app</span>     <span class="comment"># 你部署的云函数地址</span></span><br><span class="line">  <span class="attr">region:</span></span><br><span class="line">  <span class="attr">visitor:</span> <span class="literal">true</span></span><br></pre></td></tr></table></figure><p>其它可选方案对比：</p><table><thead><tr><th>方案</th><th>优点</th><th>缺点</th></tr></thead><tbody><tr><td>Twikoo</td><td>免费、部署简单、支持邮件通知</td><td>依赖云函数（Vercel &#x2F; 腾讯云）</td></tr><tr><td>Waline</td><td>界面现代、支持多数据库</td><td>同样需服务端</td></tr><tr><td>Giscus</td><td>基于 GitHub Discussions，零后端</td><td>评论者需 GitHub 账号</td></tr><tr><td>Disqus</td><td>老牌、功能全</td><td>国内访问不稳定</td></tr></tbody></table><h2 id="八、代码高亮与代码块"><a href="#八、代码高亮与代码块" class="headerlink" title="八、代码高亮与代码块"></a>八、代码高亮与代码块</h2><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">highlight:</span></span><br><span class="line">  <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">line_number:</span> <span class="literal">true</span>         <span class="comment"># 显示行号</span></span><br><span class="line">  <span class="attr">auto_detect:</span> <span class="literal">false</span></span><br><span class="line">  <span class="attr">tab_replace:</span></span><br><span class="line">  <span class="attr">wrap:</span> <span class="literal">true</span>                <span class="comment"># 代码过长自动换行还是横向滚动</span></span><br><span class="line">  <span class="attr">height_limit:</span> <span class="literal">false</span>       <span class="comment"># 也可写 300，超出折叠</span></span><br><span class="line">  <span class="attr">theme:</span> <span class="string">mac</span>                <span class="comment"># 代码块顶部的样式风格</span></span><br><span class="line"></span><br><span class="line"><span class="attr">prismjs:</span></span><br><span class="line">  <span class="attr">enable:</span> <span class="literal">false</span>             <span class="comment"># 与 highlight 二选一</span></span><br></pre></td></tr></table></figure><p>美化代码块（本站用的这类效果）可以写在自定义 CSS 里：</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* source/css/custom.css */</span></span><br><span class="line"><span class="selector-id">#article-container</span> <span class="selector-tag">figure</span><span class="selector-class">.highlight</span> &#123;</span><br><span class="line">  <span class="attribute">border-radius</span>: <span class="number">12px</span>;</span><br><span class="line">  <span class="attribute">box-shadow</span>: <span class="number">0</span> <span class="number">4px</span> <span class="number">16px</span> <span class="built_in">rgba</span>(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, .<span class="number">06</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="九、主题色与深色模式"><a href="#九、主题色与深色模式" class="headerlink" title="九、主题色与深色模式"></a>九、主题色与深色模式</h2><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">theme_color:</span></span><br><span class="line">  <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">main:</span> <span class="string">&quot;#5b5bd6&quot;</span>            <span class="comment"># 主色调，全站按钮/链接/下划线都会跟着变</span></span><br><span class="line">  <span class="attr">paginator:</span> <span class="string">&quot;#5b5bd6&quot;</span></span><br><span class="line">  <span class="attr">button_hover:</span> <span class="string">&quot;#ff7242&quot;</span></span><br><span class="line">  <span class="attr">text_selection:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">link_color:</span> <span class="string">&quot;#5b5bd6&quot;</span></span><br><span class="line">  <span class="attr">meta_color:</span> <span class="string">&quot;#858585&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="attr">darkmode:</span></span><br><span class="line">  <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">start:</span> <span class="number">0</span>                   <span class="comment"># 0:00 开始</span></span><br><span class="line">  <span class="attr">end:</span> <span class="number">6</span>                     <span class="comment"># 6:00 结束</span></span><br><span class="line">  <span class="attr">autoChangeMode:</span> <span class="literal">false</span>      <span class="comment"># true = 跟随系统/时间自动切换</span></span><br></pre></td></tr></table></figure><div class="note info flat"><p>改主色最快的方式就是 <code>theme_color.main</code> 一个值。想做更细的定制（比如三档主题切换），可以用 CSS 变量覆盖 + 注入 JS，参考本站 <code>source/css/theme-tri.css</code> 的做法，不动主题源文件。</p></div><h2 id="十、自定义-CSS-JS（关键技能）"><a href="#十、自定义-CSS-JS（关键技能）" class="headerlink" title="十、自定义 CSS &#x2F; JS（关键技能）"></a>十、自定义 CSS &#x2F; JS（关键技能）</h2><p>想改样式但<strong>不想动主题源码</strong>，用注入：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">inject:</span></span><br><span class="line">  <span class="attr">head:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">&lt;link</span> <span class="string">rel=&quot;stylesheet&quot;</span> <span class="string">href=&quot;/css/custom.css&quot;&gt;</span></span><br><span class="line">  <span class="attr">bottom:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">&lt;script</span> <span class="string">src=&quot;/js/custom.js&quot;&gt;&lt;/script&gt;</span></span><br></pre></td></tr></table></figure><p>对应文件放在 <code>source/css/</code> 和 <code>source/js/</code>，Hexo 会原样拷贝到 <code>public/</code>。</p><div class="note danger flat"><p><strong>CSS 覆盖不生效时的排查顺序</strong>：</p><ol><li>文件是否真的被引用（看页面源码里有没有这个 <code>&lt;link&gt;</code>）</li><li>加载顺序 —— 自定义 CSS 必须在主题 CSS <strong>之后</strong></li><li>选择器特异性不够 —— 去 <code>public/css/index.css</code> 里搜原规则，看它用了几层选择器，照着补齐（比如主题写 <code>#nav .site-page:not(.child):after</code>，你只写 <code>#nav .site-page::after</code> 就压不过它）</li><li>浏览器缓存 —— 强制刷新 <code>Cmd + Shift + R</code></li></ol></div><h2 id="十一、常用功能开关速查"><a href="#十一、常用功能开关速查" class="headerlink" title="十一、常用功能开关速查"></a>十一、常用功能开关速查</h2><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 文章相关</span></span><br><span class="line"><span class="attr">post_meta:</span>                <span class="comment"># 文章 meta 信息显示哪些</span></span><br><span class="line">  <span class="attr">post:</span> <span class="literal">true</span>              <span class="comment"># 作者、日期、分类</span></span><br><span class="line">  <span class="attr">categories:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">tags:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">date_type:</span> <span class="string">created</span>      <span class="comment"># created / updated</span></span><br><span class="line"></span><br><span class="line"><span class="attr">toc:</span>                      <span class="comment"># 文章目录</span></span><br><span class="line">  <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">number:</span> <span class="literal">false</span></span><br><span class="line">  <span class="attr">expand:</span> <span class="literal">true</span></span><br><span class="line"></span><br><span class="line"><span class="attr">related_post:</span>             <span class="comment"># 相关文章推荐</span></span><br><span class="line">  <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">limit:</span> <span class="number">6</span></span><br><span class="line"></span><br><span class="line"><span class="attr">wordcount:</span>                <span class="comment"># 字数统计（需装 hexo-wordcount）</span></span><br><span class="line">  <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 效果类</span></span><br><span class="line"><span class="attr">beautify:</span></span><br><span class="line">  <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">field:</span> <span class="string">post</span>             <span class="comment"># site / post</span></span><br><span class="line">  <span class="attr">title-prefix-icon:</span> <span class="string">&#x27;\f0c1&#x27;</span></span><br><span class="line">  <span class="attr">title-prefix-icon-color:</span> <span class="string">&#x27;#5b5bd6&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="attr">anchor:</span>                   <span class="comment"># 标题锚点</span></span><br><span class="line">  <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line"></span><br><span class="line"><span class="attr">lazyload:</span>                 <span class="comment"># 图片懒加载</span></span><br><span class="line">  <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">field:</span> <span class="string">site</span></span><br><span class="line">  <span class="attr">placeholder:</span></span><br><span class="line">  <span class="attr">blur:</span> <span class="literal">false</span></span><br><span class="line"></span><br><span class="line"><span class="attr">pjax:</span></span><br><span class="line">  <span class="attr">enable:</span> <span class="literal">true</span>            <span class="comment"># 站内跳转无刷新，体感更快</span></span><br></pre></td></tr></table></figure><h2 id="十二、值得装的插件"><a href="#十二、值得装的插件" class="headerlink" title="十二、值得装的插件"></a>十二、值得装的插件</h2><table><thead><tr><th>插件</th><th>作用</th></tr></thead><tbody><tr><td><code>hexo-abbrlink</code></td><td>生成短链接（<code>/posts/xxxx.html</code>），比中文路径友好</td></tr><tr><td><code>hexo-wordcount</code></td><td>字数与阅读时长统计</td></tr><tr><td><code>hexo-generator-sitemap</code> &#x2F; <code>hexo-generator-baidu-sitemap</code></td><td>生成 sitemap，提交搜索引擎用</td></tr><tr><td><code>hexo-bilibili-bangumi</code></td><td>追番页面</td></tr><tr><td><code>hexo-butterfly-swiper</code></td><td>首页轮播图（本站用了 <code>swiper_index</code>）</td></tr><tr><td><code>hexo-filter-nofollow</code></td><td>外链加 <code>nofollow</code>，有利于 SEO</td></tr></tbody></table><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install hexo-abbrlink hexo-wordcount hexo-generator-sitemap --save</span><br></pre></td></tr></table></figure><h2 id="十三、常见坑"><a href="#十三、常见坑" class="headerlink" title="十三、常见坑"></a>十三、常见坑</h2><table><thead><tr><th>现象</th><th>原因</th><th>解法</th></tr></thead><tbody><tr><td>改了配置没生效</td><td>没执行 <code>hexo clean</code></td><td>清缓存后重新生成</td></tr><tr><td>菜单点进去 404</td><td>没创建对应 page</td><td><code>hexo new page xxx</code></td></tr><tr><td>样式改了不生效</td><td>选择器特异性不够 &#x2F; 缓存</td><td>见第十节排查顺序</td></tr><tr><td>部署后文章链接变了</td><td><code>permalink</code> 或 <code>abbrlink</code> 配置变了</td><td>改链接后必须配 301 重定向</td></tr><tr><td>图片不显示</td><td>路径大小写、中文文件名</td><td>用相对路径 <code>/img/x.png</code>，避免中文名</td></tr><tr><td>搜索无结果</td><td>本地搜索索引未生成</td><td>确认装了 <code>hexo-generator-search</code></td></tr></tbody></table><hr><div class="note success flat"><p><strong>改动原则</strong>：能用配置解决的不写代码，能靠 CSS 覆盖的不改主题源文件。这样主题升级时一条 <code>git pull</code> 就能跟上，自己的定制也不会丢。</p></div>]]></content>
    
    
    <summary type="html">Hexo Butterfly 主题常用配置修改记录，涵盖站点信息、首页配置、侧边栏小部件与文章显示效果的自定义方法。</summary>
    
    
    
    <category term="博客搭建" scheme="https://www.amoit.top/categories/%E5%8D%9A%E5%AE%A2%E6%90%AD%E5%BB%BA/"/>
    
    
    <category term="Hexo" scheme="https://www.amoit.top/tags/Hexo/"/>
    
    <category term="Butterfly" scheme="https://www.amoit.top/tags/Butterfly/"/>
    
    <category term="主题美化" scheme="https://www.amoit.top/tags/%E4%B8%BB%E9%A2%98%E7%BE%8E%E5%8C%96/"/>
    
  </entry>
  
  <entry>
    <title>Vue2 与 Vue3 学习笔记</title>
    <link href="https://www.amoit.top/posts/vue2-vue3-study-notes/"/>
    <id>https://www.amoit.top/posts/vue2-vue3-study-notes/</id>
    <published>2024-01-05T08:09:01.000Z</published>
    <updated>2026-10-06T12:33:24.366Z</updated>
    
    <content type="html"><![CDATA[<h2 id="vsc"><a href="#vsc" class="headerlink" title="vsc"></a>vsc</h2><h3 id="2024-4-12-下载源过期问题"><a href="#2024-4-12-下载源过期问题" class="headerlink" title="2024.4.12 下载源过期问题"></a>2024.4.12 下载源过期问题</h3><p>一、报错情况 </p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">npm ERR! code CERT_HAS_EXPIRED</span><br><span class="line">npm ERR! errno CERT_HAS_EXPIRED</span><br><span class="line">npm ERR! request to https://registry.npm.taobao.org/webpack failed, reason: certificate has expired</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>npm的证书失效了，它不再支持自签名证书 </p><p>二、解决方案</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">1.查看自己的下载源</span><br><span class="line">npm config get registry</span><br><span class="line">2.发现我们之前配置了下载镜像源为https开头的，</span><br><span class="line">https://registry.npm.taobao.org/</span><br><span class="line">3.执行命令清除npm缓存 </span><br><span class="line">npm cache clean --force</span><br><span class="line">4.执行命令取消ssl验证 </span><br><span class="line">npm config set strict-ssl false</span><br><span class="line">5.再次执行npm install ***，还不行可以尝试设置你的npm镜像源为http开头的，不使用https</span><br><span class="line">npm config set registry http://registry.npm.taobao.org</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="配置node环境和包管理工具"><a href="#配置node环境和包管理工具" class="headerlink" title="配置node环境和包管理工具"></a>配置node环境和包管理工具</h3><p>1.npm,node 安装<br>Node的介绍与安装<br>Node.js是一个基于Chrome V8引擎的JavaScript运行时。它允许开发者使用JavaScript在服务器端运行代码，而不仅仅局限于浏览器环境。Node.js提供了丰富的内置模块和包管理器npm，使开发者能够轻松地构建和管理应用程序。Node.js在前端开发中广泛应用于构建工具、服务器端渲染、API开发等方面，为前端工程师提供了更多的技术选择和灵活性。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">检查代码</span><br><span class="line">node -v</span><br><span class="line">npm -v</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>2.yarn 的安装</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">npm install --global yarn</span><br><span class="line">yarn --version</span><br><span class="line"></span><br></pre></td></tr></table></figure><ol start="3"><li>Webpack的介绍与安装<br>Webpack： Webpack是一个模块打包工具，它可以将多个前端资源（如JavaScript、CSS、图片等）打包成一个或多个静态文件。Webpack通过模块化的方式管理项目中的各个模块，并根据配置文件进行打包和优化。它提供了丰富的插件和加载器，可以处理各种类型的文件，实现代码分割、压缩、懒加载等功能。Webpack还支持热模块替换（HMR），可以在开发过程中实时预览修改的效果。通过使用Webpack，前端工程师可以更好地组织和管理项目代码，提高开发效率和性能。</li></ol><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">npm install webpack -g</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>4.Vue CLI的安装与介绍<br>Vue CLI是一个用于快速构建Vue.js项目的脚手架工具。它提供了一套完整的项目开发工具链，包括项目初始化、开发服务器、打包构建等功能。Vue CLI基于Webpack，并集成了Vue.js相关的插件和配置，使得前端工程师可以快速搭建和开发Vue项目。Vue CLI还提供了丰富的插件和模板，可以根据项目需求进行定制化配置。通过使用Vue CLI，前端工程师可以快速启动项目，统一项目结构和开发规范，并享受到Vue.js的开发优势。<br>全局安装Vue CLI</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">npm install -g @vue/cli</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>5.初始化Vue项目并运行</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">新建一个文件夹，在控制台输入</span><br><span class="line">vue create vue2_test</span><br><span class="line">选择vue2或者vue3的默认模板安装 (回车键)</span><br><span class="line">安装好后，执行</span><br><span class="line">cd vue2_test</span><br><span class="line">npm run serve</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="Vue框架学习"><a href="#Vue框架学习" class="headerlink" title="Vue框架学习"></a>Vue框架学习</h2><p>渐进式JavaScript框架<br>vue是一个框架，也是一个生态。<br>官方文档：<br><a href="https://cn.vuejs.org/">地址</a></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">window版本:</span><br><span class="line">yarn 与npm</span><br><span class="line">npm i yarn //下到本磁盘中</span><br><span class="line">npm i - global yarn //下载到全局</span><br><span class="line">yarn add ** </span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="Vue和react对比"><a href="#Vue和react对比" class="headerlink" title="Vue和react对比"></a>Vue和react对比</h3><h3 id="使用vue的不同方式："><a href="#使用vue的不同方式：" class="headerlink" title="使用vue的不同方式："></a>使用vue的不同方式：</h3><p>1.无须构建步骤，渐进式增强静态的HTML<br>2.在任何页面中作为Web Components 嵌入<br>3.单页应用 SPA<br>4.全栈&#x2F;服务器渲染 SSR<br>5.Jamstrack &#x2F;静态站点生成 SSG<br>6.开发桌面端、移动端、webGL，甚至是命令行终端中的界面</p><h3 id="vue-API：选项式API和组合式API"><a href="#vue-API：选项式API和组合式API" class="headerlink" title="vue API：选项式API和组合式API"></a>vue API：选项式API和组合式API</h3><h3 id="Element-UI-主题样式更改"><a href="#Element-UI-主题样式更改" class="headerlink" title="Element-UI 主题样式更改"></a>Element-UI 主题样式更改</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">帮助文档:https://element.eleme.cn/2.7/#/zh-CN/component/custom-theme</span><br><span class="line">在线生成工具:https://elementui.github.io/theme-chalk-preview/#/zh-CN</span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">Vue2 与 Vue3 学习笔记，涵盖响应式原理、组合式 API、组件通信与项目实践中的常见问题。</summary>
    
    
    
    <category term="前端开发" scheme="https://www.amoit.top/categories/%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91/"/>
    
    
    <category term="Vue" scheme="https://www.amoit.top/tags/Vue/"/>
    
    <category term="前端" scheme="https://www.amoit.top/tags/%E5%89%8D%E7%AB%AF/"/>
    
    <category term="学习笔记" scheme="https://www.amoit.top/tags/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
    
  </entry>
  
  <entry>
    <title>React 学习笔记</title>
    <link href="https://www.amoit.top/posts/react-study-notes/"/>
    <id>https://www.amoit.top/posts/react-study-notes/</id>
    <published>2024-01-05T08:09:01.000Z</published>
    <updated>2026-10-06T14:53:38.099Z</updated>
    
    <content type="html"><![CDATA[<div class="note info flat"><p>这是一篇边学边记的 React 笔记，目标不是抄文档，而是把「什么时候该用什么」讲清楚。示例代码基于 <strong>React 18+</strong>，大部分写法在 React 19 同样适用，有差异的地方单独标注。</p></div><h2 id="一、React-到底是什么"><a href="#一、React-到底是什么" class="headerlink" title="一、React 到底是什么"></a>一、React 到底是什么</h2><p>一句话：<strong>React 是一个用于构建用户界面的 JavaScript 库</strong>，它只负责「数据 → 界面」这一层，路由、请求、状态管理都交给生态。</p><p>三个核心观念，理解了它们就理解了 React 的一半：</p><table><thead><tr><th>观念</th><th>含义</th><th>带来的好处</th></tr></thead><tbody><tr><td>声明式</td><td>你描述「界面应该长什么样」，而不是「一步步怎么改 DOM」</td><td>不用手写 DOM 操作，心智负担低</td></tr><tr><td>组件化</td><td>UI 拆成独立、可复用的函数（组件）</td><td>复用、隔离、好测试</td></tr><tr><td>单向数据流</td><td>数据从父组件流向子组件，子组件不能直接改父组件的数据</td><td>数据变化可追踪，出 bug 好定位</td></tr></tbody></table><p>对比一下就明白了。同样是「点击按钮后把数字加一」：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 命令式（原生 JS）—— 需要自己管 DOM</span></span><br><span class="line"><span class="keyword">let</span> count = <span class="number">0</span></span><br><span class="line">btn.<span class="property">onclick</span> = <span class="function">() =&gt;</span> &#123;</span><br><span class="line">  count += <span class="number">1</span></span><br><span class="line">  el.<span class="property">textContent</span> = count      <span class="comment">// 手动更新</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 声明式（React）—— 只描述结果</span></span><br><span class="line"><span class="keyword">const</span> [count, setCount] = <span class="title function_">useState</span>(<span class="number">0</span>)</span><br><span class="line">&lt;button onClick=&#123;<span class="function">() =&gt;</span> <span class="title function_">setCount</span>(count + <span class="number">1</span>)&#125;&gt;&#123;count&#125;&lt;/button&gt;</span><br></pre></td></tr></table></figure><h2 id="二、环境搭建"><a href="#二、环境搭建" class="headerlink" title="二、环境搭建"></a>二、环境搭建</h2><p>现在官方推荐用 Vite，<code>create-react-app</code> 已经不推荐在新项目里使用了。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 创建项目（选择 React + JavaScript/TypeScript）</span></span><br><span class="line">npm create vite@latest my-app -- --template react</span><br><span class="line"></span><br><span class="line"><span class="built_in">cd</span> my-app</span><br><span class="line">npm install</span><br><span class="line">npm run dev      <span class="comment"># 启动开发服务器，默认 http://localhost:5173</span></span><br><span class="line">npm run build    <span class="comment"># 打包产物输出到 dist/</span></span><br></pre></td></tr></table></figure><p>生成的关键文件：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">my-app/</span><br><span class="line">├── index.html            # 唯一的 HTML 入口</span><br><span class="line">├── src/</span><br><span class="line">│   ├── main.jsx          # 挂载点，把 &lt;App /&gt; 渲染到 #root</span><br><span class="line">│   ├── App.jsx           # 根组件</span><br><span class="line">│   └── components/       # 自己建的组件目录（约定俗成）</span><br><span class="line">└── vite.config.js</span><br></pre></td></tr></table></figure><p><code>main.jsx</code> 里这几行是整个应用的起点：</p><figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> <span class="title class_">React</span> <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">ReactDOM</span> <span class="keyword">from</span> <span class="string">&#x27;react-dom/client&#x27;</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">App</span> <span class="keyword">from</span> <span class="string">&#x27;./App&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="title class_">ReactDOM</span>.<span class="title function_">createRoot</span>(<span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&#x27;root&#x27;</span>)).<span class="title function_">render</span>(<span class="language-xml"><span class="tag">&lt;<span class="name">App</span> /&gt;</span></span>)</span><br></pre></td></tr></table></figure><h2 id="三、JSX-语法要点"><a href="#三、JSX-语法要点" class="headerlink" title="三、JSX 语法要点"></a>三、JSX 语法要点</h2><p>JSX 不是模板字符串，也不是 HTML，它会被编译成 <code>React.createElement()</code> 调用。和 HTML 的差异是新手最容易踩坑的地方：</p><table><thead><tr><th>场景</th><th>HTML 写法</th><th>JSX 写法</th><th>原因</th></tr></thead><tbody><tr><td>类名</td><td><code>class=&quot;box&quot;</code></td><td><code>className=&quot;box&quot;</code></td><td><code>class</code> 是 JS 关键字</td></tr><tr><td>内联样式</td><td><code>style=&quot;color:red&quot;</code></td><td><code>style=&#123;&#123; color: 'red' &#125;&#125;</code></td><td>外层 <code>&#123;&#125;</code> 是表达式，内层 <code>&#123;&#125;</code> 是对象</td></tr><tr><td>label</td><td><code>for=&quot;name&quot;</code></td><td><code>htmlFor=&quot;name&quot;</code></td><td>同上，<code>for</code> 是关键字</td></tr><tr><td>自闭合</td><td><code>&lt;br&gt;</code></td><td><code>&lt;br /&gt;</code></td><td>JSX 要求标签闭合</td></tr><tr><td>注释</td><td><code>&lt;!-- x --&gt;</code></td><td><code>&#123;/* x */&#125;</code></td><td>JSX 里只能写 JS 注释</td></tr></tbody></table><p>三条规则记住就不会错：</p><ol><li><strong>只能返回一个根元素</strong> —— 多个并列元素用 <code>&lt;&gt; &lt;/&gt;</code>（Fragment）包起来</li><li><strong><code>&#123;&#125;</code> 里可以放任何 JS 表达式</strong>，但不能放语句（如 <code>if</code>、<code>for</code>）</li><li><strong>属性名用驼峰</strong>：<code>onclick</code> → <code>onClick</code>，<code>tabindex</code> → <code>tabIndex</code></li></ol><figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">UserCard</span>(<span class="params">&#123; user &#125;</span>) &#123;</span><br><span class="line">  <span class="keyword">return</span> (</span><br><span class="line">    <span class="language-xml"><span class="tag">&lt;&gt;</span></span></span><br><span class="line"><span class="language-xml">      <span class="tag">&lt;<span class="name">h2</span> <span class="attr">style</span>=<span class="string">&#123;&#123;</span> <span class="attr">fontSize:</span> <span class="attr">18</span> &#125;&#125;&gt;</span>&#123;user.name&#125;<span class="tag">&lt;/<span class="name">h2</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">      &#123;/* 三元表达式可以写在 &#123;&#125; 里 */&#125;</span></span><br><span class="line"><span class="language-xml">      <span class="tag">&lt;<span class="name">span</span> <span class="attr">className</span>=<span class="string">&#123;user.vip</span> ? &#x27;<span class="attr">tag</span> <span class="attr">tag--vip</span>&#x27; <span class="attr">:</span> &#x27;<span class="attr">tag</span>&#x27;&#125;&gt;</span></span></span><br><span class="line"><span class="language-xml">        &#123;user.vip ? &#x27;VIP&#x27; : &#x27;普通用户&#x27;&#125;</span></span><br><span class="line"><span class="language-xml">      <span class="tag">&lt;/<span class="name">span</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;/&gt;</span></span></span><br><span class="line">  )</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="四、组件与-Props"><a href="#四、组件与-Props" class="headerlink" title="四、组件与 Props"></a>四、组件与 Props</h2><p><strong>组件就是首字母大写的函数</strong>，返回一段 JSX。Props 是父组件传进来的参数，是个只读对象。</p><figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 子组件：通过 props 接收</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">Button</span>(<span class="params">&#123; text, type = <span class="string">&#x27;default&#x27;</span>, onClick &#125;</span>) &#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="language-xml"><span class="tag">&lt;<span class="name">button</span> <span class="attr">className</span>=<span class="string">&#123;</span>`<span class="attr">btn</span> <span class="attr">btn--</span>$&#123;<span class="attr">type</span>&#125;`&#125; <span class="attr">onClick</span>=<span class="string">&#123;onClick&#125;</span>&gt;</span>&#123;text&#125;<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 父组件：像写 HTML 属性一样传值</span></span><br><span class="line">&lt;<span class="title class_">Button</span> text=<span class="string">&quot;提交&quot;</span> type=<span class="string">&quot;primary&quot;</span> onClick=&#123;handleSubmit&#125; /&gt;</span><br></pre></td></tr></table></figure><div class="note warning flat"><p>Props 是<strong>只读</strong>的，永远不要在子组件里写 <code>props.name = &#39;xxx&#39;</code>。组件内部要变的数据用 state，要通知父组件就调用父组件传下来的回调函数。</p></div><p><code>children</code> 是个特殊的 prop，代表标签之间的内容：</p><figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">Card</span>(<span class="params">&#123; title, children &#125;</span>) &#123;</span><br><span class="line">  <span class="keyword">return</span> (</span><br><span class="line">    <span class="language-xml"><span class="tag">&lt;<span class="name">div</span> <span class="attr">className</span>=<span class="string">&quot;card&quot;</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">      <span class="tag">&lt;<span class="name">h3</span>&gt;</span>&#123;title&#125;<span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">      <span class="tag">&lt;<span class="name">div</span> <span class="attr">className</span>=<span class="string">&quot;card__body&quot;</span>&gt;</span>&#123;children&#125;<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">  )</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">&lt;<span class="title class_">Card</span> title=<span class="string">&quot;提示&quot;</span>&gt;这里是正文内容&lt;/<span class="title class_">Card</span>&gt;</span><br></pre></td></tr></table></figure><h2 id="五、State-与事件处理"><a href="#五、State-与事件处理" class="headerlink" title="五、State 与事件处理"></a>五、State 与事件处理</h2><p><code>useState</code> 是组件内部的「可变数据」。调用 <code>setXxx</code> 会让组件重新渲染。</p><figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; useState &#125; <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">Counter</span>(<span class="params"></span>) &#123;</span><br><span class="line">  <span class="keyword">const</span> [count, setCount] = <span class="title function_">useState</span>(<span class="number">0</span>)</span><br><span class="line"></span><br><span class="line">  <span class="comment">// ✅ 正确：传函数，基于最新值计算</span></span><br><span class="line">  <span class="keyword">const</span> <span class="title function_">add</span> = (<span class="params"></span>) =&gt; <span class="title function_">setCount</span>(<span class="function"><span class="params">c</span> =&gt;</span> c + <span class="number">1</span>)</span><br><span class="line"></span><br><span class="line">  <span class="comment">// ❌ 错误示范：连续调用两次也只加 1，因为 count 是本次渲染的快照</span></span><br><span class="line">  <span class="keyword">const</span> <span class="title function_">wrongAdd</span> = (<span class="params"></span>) =&gt; &#123;</span><br><span class="line">    <span class="title function_">setCount</span>(count + <span class="number">1</span>)</span><br><span class="line">    <span class="title function_">setCount</span>(count + <span class="number">1</span>)</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> <span class="language-xml"><span class="tag">&lt;<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">&#123;add&#125;</span>&gt;</span>&#123;count&#125;<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><div class="note danger flat"><p><strong>state 更新是异步且批量的</strong>：调用 <code>setCount</code> 后立刻 <code>console.log(count)</code> 拿到的是旧值。要拿到更新后的值，用 <code>useEffect</code> 监听，或者直接用新值继续计算。</p></div><p>事件绑定的三种写法，注意括号：</p><figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&lt;button onClick=&#123;handleClick&#125;&gt;传函数引用&lt;<span class="regexp">/button&gt;        &#123;/</span>* ✅ 推荐 */&#125;</span><br><span class="line">&lt;button onClick=&#123;<span class="function">() =&gt;</span> <span class="title function_">handleClick</span>(id)&#125;&gt;需要传参&lt;<span class="regexp">/button&gt; &#123;/</span>* ✅ 用箭头函数包一层 */&#125;</span><br><span class="line">&lt;button onClick=&#123;<span class="title function_">handleClick</span>()&#125;&gt;错误写法&lt;<span class="regexp">/button&gt;         &#123;/</span>* ❌ 渲染时就执行了 */&#125;</span><br></pre></td></tr></table></figure><h2 id="六、条件渲染与列表渲染"><a href="#六、条件渲染与列表渲染" class="headerlink" title="六、条件渲染与列表渲染"></a>六、条件渲染与列表渲染</h2><figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 1. 三元表达式：二选一</span></span><br><span class="line">&#123;isLogin ? <span class="language-xml"><span class="tag">&lt;<span class="name">UserPanel</span> /&gt;</span></span> : <span class="language-xml"><span class="tag">&lt;<span class="name">LoginBtn</span> /&gt;</span></span>&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 2. &amp;&amp; ：满足条件才显示（别用数字 0 做条件，会渲染出一个 &quot;0&quot;）</span></span><br><span class="line">&#123;list.<span class="property">length</span> &gt; <span class="number">0</span> &amp;&amp; <span class="language-xml"><span class="tag">&lt;<span class="name">List</span> <span class="attr">data</span>=<span class="string">&#123;list&#125;</span> /&gt;</span></span>&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 3. 早期 return：分支复杂时最清晰</span></span><br><span class="line"><span class="keyword">if</span> (loading) <span class="keyword">return</span> <span class="language-xml"><span class="tag">&lt;<span class="name">Loading</span> /&gt;</span></span></span><br><span class="line"><span class="keyword">if</span> (error) <span class="keyword">return</span> <span class="language-xml"><span class="tag">&lt;<span class="name">Error</span> <span class="attr">msg</span>=<span class="string">&#123;error.message&#125;</span> /&gt;</span></span></span><br><span class="line"><span class="keyword">return</span> <span class="language-xml"><span class="tag">&lt;<span class="name">Content</span> <span class="attr">data</span>=<span class="string">&#123;data&#125;</span> /&gt;</span></span></span><br></pre></td></tr></table></figure><p>列表渲染用 <code>map</code>，<strong>必须写 <code>key</code></strong>：</p><figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&#123;users.<span class="title function_">map</span>(<span class="function"><span class="params">user</span> =&gt;</span> (</span><br><span class="line">  <span class="language-xml"><span class="tag">&lt;<span class="name">li</span> <span class="attr">key</span>=<span class="string">&#123;user.id&#125;</span>&gt;</span>&#123;user.name&#125;<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span></span><br><span class="line">))&#125;</span><br></pre></td></tr></table></figure><div class="note warning flat"><p><code>key</code> 不要用数组下标（<code>index</code>）。删除中间某一项时下标会错位，导致 React 复用错误的 DOM 和组件状态 —— 表单输入框内容错位就是这么来的。用数据里稳定的 <code>id</code>。</p></div><h2 id="七、表单：受控组件"><a href="#七、表单：受控组件" class="headerlink" title="七、表单：受控组件"></a>七、表单：受控组件</h2><p>React 里推荐「受控组件」：表单的值由 state 保管，<code>value</code> 与 <code>onChange</code> 成对出现。</p><figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">Form</span>(<span class="params"></span>) &#123;</span><br><span class="line">  <span class="keyword">const</span> [form, setForm] = <span class="title function_">useState</span>(&#123; <span class="attr">name</span>: <span class="string">&#x27;&#x27;</span>, <span class="attr">email</span>: <span class="string">&#x27;&#x27;</span> &#125;)</span><br><span class="line"></span><br><span class="line">  <span class="keyword">const</span> <span class="title function_">handleChange</span> = e =&gt; &#123;</span><br><span class="line">    <span class="keyword">const</span> &#123; name, value &#125; = e.<span class="property">target</span></span><br><span class="line">    <span class="title function_">setForm</span>(<span class="function"><span class="params">prev</span> =&gt;</span> (&#123; ...prev, [name]: value &#125;))   <span class="comment">// 展开旧值再覆盖</span></span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">const</span> <span class="title function_">handleSubmit</span> = e =&gt; &#123;</span><br><span class="line">    e.<span class="title function_">preventDefault</span>()      <span class="comment">// 阻止表单默认提交导致页面刷新</span></span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(form)</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> (</span><br><span class="line">    <span class="language-xml"><span class="tag">&lt;<span class="name">form</span> <span class="attr">onSubmit</span>=<span class="string">&#123;handleSubmit&#125;</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">      <span class="tag">&lt;<span class="name">input</span> <span class="attr">name</span>=<span class="string">&quot;name&quot;</span>  <span class="attr">value</span>=<span class="string">&#123;form.name&#125;</span>  <span class="attr">onChange</span>=<span class="string">&#123;handleChange&#125;</span> /&gt;</span></span></span><br><span class="line"><span class="language-xml">      <span class="tag">&lt;<span class="name">input</span> <span class="attr">name</span>=<span class="string">&quot;email&quot;</span> <span class="attr">value</span>=<span class="string">&#123;form.email&#125;</span> <span class="attr">onChange</span>=<span class="string">&#123;handleChange&#125;</span> /&gt;</span></span></span><br><span class="line"><span class="language-xml">      <span class="tag">&lt;<span class="name">button</span> <span class="attr">type</span>=<span class="string">&quot;submit&quot;</span>&gt;</span>提交<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;/<span class="name">form</span>&gt;</span></span></span><br><span class="line">  )</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="八、Hooks-逐个拆解"><a href="#八、Hooks-逐个拆解" class="headerlink" title="八、Hooks 逐个拆解"></a>八、Hooks 逐个拆解</h2><p>Hooks 就是「在函数组件里使用状态等 React 特性」的函数。规则只有两条：<strong>只能在组件顶层调用</strong>（不能放进 if &#x2F; for &#x2F; 嵌套函数）、<strong>只能在组件或自定义 Hook 里调用</strong>。</p><h3 id="useState"><a href="#useState" class="headerlink" title="useState"></a>useState</h3><figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> [state, setState] = <span class="title function_">useState</span>(初始值)</span><br></pre></td></tr></table></figure><p>初始值可以传函数（懒初始化，只在首次渲染执行，适合开销大的计算）：</p><figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> [list, setList] = <span class="title function_">useState</span>(<span class="function">() =&gt;</span> <span class="title class_">JSON</span>.<span class="title function_">parse</span>(<span class="variable language_">localStorage</span>.<span class="title function_">getItem</span>(<span class="string">&#x27;list&#x27;</span>)) || [])</span><br></pre></td></tr></table></figure><h3 id="useEffect-——-处理「副作用」"><a href="#useEffect-——-处理「副作用」" class="headerlink" title="useEffect —— 处理「副作用」"></a>useEffect —— 处理「副作用」</h3><p>副作用 &#x3D; 渲染之外的事情：请求数据、订阅、操作 DOM、定时器。</p><figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="title function_">useEffect</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">  <span class="keyword">const</span> timer = <span class="built_in">setInterval</span>(<span class="function">() =&gt;</span> <span class="title function_">setTime</span>(<span class="title class_">Date</span>.<span class="title function_">now</span>()), <span class="number">1000</span>)</span><br><span class="line">  <span class="keyword">return</span> <span class="function">() =&gt;</span> <span class="built_in">clearInterval</span>(timer)      <span class="comment">// 👈 清理函数，组件卸载时执行</span></span><br><span class="line">&#125;, [])                                    <span class="comment">// 👈 依赖数组</span></span><br></pre></td></tr></table></figure><p>依赖数组的三种情况，务必分清：</p><table><thead><tr><th>依赖数组</th><th>执行时机</th><th>典型场景</th></tr></thead><tbody><tr><td>不写</td><td><strong>每次渲染后都执行</strong></td><td>几乎不用，容易死循环</td></tr><tr><td><code>[]</code></td><td>只在挂载后执行一次</td><td>初始化请求、绑定全局事件</td></tr><tr><td><code>[a, b]</code></td><td>挂载时 + <code>a</code>&#x2F;<code>b</code> 变化时</td><td>按条件重新请求数据</td></tr></tbody></table><div class="note danger flat"><p>依赖数组里<strong>必须写全 effect 中用到的所有会变化的外部变量</strong>（state、props、组件内定义的函数），否则会拿到过期的旧值 —— 这是 useEffect 最经典的坑。装上 <code>eslint-plugin-react-hooks</code> 可以自动提示。</p></div><h3 id="useRef-——-拿-DOM-或存「不触发渲染的值」"><a href="#useRef-——-拿-DOM-或存「不触发渲染的值」" class="headerlink" title="useRef —— 拿 DOM 或存「不触发渲染的值」"></a>useRef —— 拿 DOM 或存「不触发渲染的值」</h3><figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> inputRef = <span class="title function_">useRef</span>(<span class="literal">null</span>)</span><br><span class="line"><span class="keyword">const</span> <span class="title function_">focus</span> = (<span class="params"></span>) =&gt; inputRef.<span class="property">current</span>.<span class="title function_">focus</span>()</span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> <span class="language-xml"><span class="tag">&lt;<span class="name">input</span> <span class="attr">ref</span>=<span class="string">&#123;inputRef&#125;</span> /&gt;</span></span></span><br></pre></td></tr></table></figure><p>改 <code>ref.current</code> <strong>不会触发重新渲染</strong>，所以它适合存定时器 ID、上一次的值这类不需要显示在界面上的数据。</p><h3 id="useMemo-useCallback-——-缓存"><a href="#useMemo-useCallback-——-缓存" class="headerlink" title="useMemo &#x2F; useCallback —— 缓存"></a>useMemo &#x2F; useCallback —— 缓存</h3><figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> expensive = <span class="title function_">useMemo</span>(<span class="function">() =&gt;</span> <span class="title function_">heavyCalc</span>(list), [list])       <span class="comment">// 缓存计算结果</span></span><br><span class="line"><span class="keyword">const</span> handleClick = <span class="title function_">useCallback</span>(<span class="function">() =&gt;</span> <span class="title function_">doSomething</span>(id), [id])   <span class="comment">// 缓存函数引用</span></span><br></pre></td></tr></table></figure><div class="note info flat"><p>别滥用。二者本身也有开销，只在这两种情况下用：① 计算确实很重；② 函数要传给用 <code>React.memo</code> 包过的子组件（否则每次渲染函数引用都变，memo 白做）。</p></div><h3 id="useContext-——-跨层传递"><a href="#useContext-——-跨层传递" class="headerlink" title="useContext —— 跨层传递"></a>useContext —— 跨层传递</h3><p>解决「props 一层层往下传」的地狱：</p><figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 1. 创建</span></span><br><span class="line"><span class="keyword">const</span> <span class="title class_">ThemeContext</span> = <span class="title function_">createContext</span>(<span class="string">&#x27;light&#x27;</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 2. 顶层提供</span></span><br><span class="line">&lt;<span class="title class_">ThemeContext</span>.<span class="property">Provider</span> value=<span class="string">&quot;dark&quot;</span>&gt;</span><br><span class="line">  <span class="language-xml"><span class="tag">&lt;<span class="name">App</span> /&gt;</span></span></span><br><span class="line">&lt;/<span class="title class_">ThemeContext</span>.<span class="property">Provider</span>&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 3. 任意深层消费</span></span><br><span class="line"><span class="keyword">const</span> theme = <span class="title function_">useContext</span>(<span class="title class_">ThemeContext</span>)</span><br></pre></td></tr></table></figure><h3 id="useReducer-——-复杂状态逻辑"><a href="#useReducer-——-复杂状态逻辑" class="headerlink" title="useReducer —— 复杂状态逻辑"></a>useReducer —— 复杂状态逻辑</h3><p>state 结构复杂、更新逻辑多时，比 useState 清晰得多（Redux 的迷你版）：</p><figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">reducer</span>(<span class="params">state, action</span>) &#123;</span><br><span class="line">  <span class="keyword">switch</span> (action.<span class="property">type</span>) &#123;</span><br><span class="line">    <span class="keyword">case</span> <span class="string">&#x27;add&#x27;</span>:    <span class="keyword">return</span> &#123; ...state, <span class="attr">count</span>: state.<span class="property">count</span> + <span class="number">1</span> &#125;</span><br><span class="line">    <span class="keyword">case</span> <span class="string">&#x27;reset&#x27;</span>:  <span class="keyword">return</span> &#123; <span class="attr">count</span>: <span class="number">0</span> &#125;</span><br><span class="line">    <span class="attr">default</span>:       <span class="keyword">return</span> state</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> [state, dispatch] = <span class="title function_">useReducer</span>(reducer, &#123; <span class="attr">count</span>: <span class="number">0</span> &#125;)</span><br><span class="line"><span class="title function_">dispatch</span>(&#123; <span class="attr">type</span>: <span class="string">&#x27;add&#x27;</span> &#125;)</span><br></pre></td></tr></table></figure><h3 id="自定义-Hook-——-逻辑复用"><a href="#自定义-Hook-——-逻辑复用" class="headerlink" title="自定义 Hook —— 逻辑复用"></a>自定义 Hook —— 逻辑复用</h3><p>把重复逻辑抽出来，名字以 <code>use</code> 开头：</p><figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">useLocalStorage</span>(<span class="params">key, initial</span>) &#123;</span><br><span class="line">  <span class="keyword">const</span> [value, setValue] = <span class="title function_">useState</span>(<span class="function">() =&gt;</span> <span class="variable language_">localStorage</span>.<span class="title function_">getItem</span>(key) ?? initial)</span><br><span class="line">  <span class="title function_">useEffect</span>(<span class="function">() =&gt;</span> &#123; <span class="variable language_">localStorage</span>.<span class="title function_">setItem</span>(key, value) &#125;, [key, value])</span><br><span class="line">  <span class="keyword">return</span> [value, setValue]</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 用起来</span></span><br><span class="line"><span class="keyword">const</span> [theme, setTheme] = <span class="title function_">useLocalStorage</span>(<span class="string">&#x27;theme&#x27;</span>, <span class="string">&#x27;light&#x27;</span>)</span><br></pre></td></tr></table></figure><h2 id="九、组件通信方式汇总"><a href="#九、组件通信方式汇总" class="headerlink" title="九、组件通信方式汇总"></a>九、组件通信方式汇总</h2><table><thead><tr><th>场景</th><th>方案</th></tr></thead><tbody><tr><td>父 → 子</td><td>props</td></tr><tr><td>子 → 父</td><td>父传回调函数，子调用</td></tr><tr><td>兄弟组件</td><td>状态提升到共同的父组件</td></tr><tr><td>跨多层</td><td>Context &#x2F; 状态管理库</td></tr><tr><td>任意组件</td><td>Zustand &#x2F; Redux 等状态管理库</td></tr></tbody></table><h2 id="十、数据请求"><a href="#十、数据请求" class="headerlink" title="十、数据请求"></a>十、数据请求</h2><p>推荐用 axios，比原生 fetch 好用（自动 JSON 解析、拦截器、超时控制）。</p><figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="title function_">useEffect</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">  <span class="keyword">let</span> cancelled = <span class="literal">false</span>      <span class="comment">// 防止组件已卸载还 setState（竞态问题）</span></span><br><span class="line"></span><br><span class="line">  axios.<span class="title function_">get</span>(<span class="string">&#x27;/api/users&#x27;</span>, &#123; <span class="attr">params</span>: &#123; page &#125; &#125;)</span><br><span class="line">    .<span class="title function_">then</span>(<span class="function"><span class="params">res</span> =&gt;</span> &#123; <span class="keyword">if</span> (!cancelled) <span class="title function_">setUsers</span>(res.<span class="property">data</span>) &#125;)</span><br><span class="line">    .<span class="title function_">catch</span>(<span class="function"><span class="params">err</span> =&gt;</span> &#123; <span class="keyword">if</span> (!cancelled) <span class="title function_">setError</span>(err.<span class="property">message</span>) &#125;)</span><br><span class="line">    .<span class="title function_">finally</span>(<span class="function">() =&gt;</span> &#123; <span class="keyword">if</span> (!cancelled) <span class="title function_">setLoading</span>(<span class="literal">false</span>) &#125;)</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> <span class="function">() =&gt;</span> &#123; cancelled = <span class="literal">true</span> &#125;</span><br><span class="line">&#125;, [page])</span><br></pre></td></tr></table></figure><div class="note info flat"><p>正经项目建议直接用 <strong>TanStack Query（原 React Query）</strong>，它把 loading &#x2F; error &#x2F; 缓存 &#x2F; 重试 &#x2F; 竞态全包了，能省掉上百行样板代码。</p></div><h2 id="十一、路由（React-Router-v6）"><a href="#十一、路由（React-Router-v6）" class="headerlink" title="十一、路由（React Router v6）"></a>十一、路由（React Router v6）</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install react-router-dom</span><br></pre></td></tr></table></figure><figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&lt;<span class="title class_">Routes</span>&gt;</span><br><span class="line">  <span class="language-xml"><span class="tag">&lt;<span class="name">Route</span> <span class="attr">path</span>=<span class="string">&quot;/&quot;</span> <span class="attr">element</span>=<span class="string">&#123;</span>&lt;<span class="attr">Home</span> /&gt;</span>&#125; /&gt;</span></span><br><span class="line">  <span class="language-xml"><span class="tag">&lt;<span class="name">Route</span> <span class="attr">path</span>=<span class="string">&quot;/posts/:id&quot;</span> <span class="attr">element</span>=<span class="string">&#123;</span>&lt;<span class="attr">Post</span> /&gt;</span>&#125; /&gt;</span></span><br><span class="line">  <span class="language-xml"><span class="tag">&lt;<span class="name">Route</span> <span class="attr">path</span>=<span class="string">&quot;*&quot;</span> <span class="attr">element</span>=<span class="string">&#123;</span>&lt;<span class="attr">NotFound</span> /&gt;</span>&#125; /&gt;</span></span><br><span class="line">&lt;/<span class="title class_">Routes</span>&gt;</span><br></pre></td></tr></table></figure><figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 编程式跳转</span></span><br><span class="line"><span class="keyword">const</span> navigate = <span class="title function_">useNavigate</span>()</span><br><span class="line"><span class="title function_">navigate</span>(<span class="string">`/posts/<span class="subst">$&#123;id&#125;</span>`</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 取路径参数 /posts/123 → id = 123</span></span><br><span class="line"><span class="keyword">const</span> &#123; id &#125; = <span class="title function_">useParams</span>()</span><br><span class="line"></span><br><span class="line"><span class="comment">// 取查询串 ?page=2</span></span><br><span class="line"><span class="keyword">const</span> [search] = <span class="title function_">useSearchParams</span>()</span><br><span class="line"><span class="keyword">const</span> page = search.<span class="title function_">get</span>(<span class="string">&#x27;page&#x27;</span>)</span><br></pre></td></tr></table></figure><h2 id="十二、状态管理怎么选"><a href="#十二、状态管理怎么选" class="headerlink" title="十二、状态管理怎么选"></a>十二、状态管理怎么选</h2><div class="tabs" id="选型"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#选型-1"><i class="fas fa-seedling"></i>小项目</button></li><li class="tab"><button type="button" data-href="#选型-2"><i class="fas fa-city"></i>中大型</button></li><li class="tab"><button type="button" data-href="#选型-3"><i class="fas fa-users"></i>强规范团队</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="选型-1"><p>组件不多、共享状态少 → <strong>Context + useReducer</strong> 就够用，别一上来就引入 Redux。</p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="选型-2"><p>推荐 <strong>Zustand</strong>：API 极简（一个 <code>create</code> 搞定）、不需要 Provider 包裹、体积约 1KB。</p><figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; create &#125; <span class="keyword">from</span> <span class="string">&#x27;zustand&#x27;</span></span><br><span class="line"><span class="keyword">const</span> useStore = <span class="title function_">create</span>(<span class="function"><span class="params">set</span> =&gt;</span> (&#123;</span><br><span class="line">  <span class="attr">count</span>: <span class="number">0</span>,</span><br><span class="line">  <span class="attr">add</span>: <span class="function">() =&gt;</span> <span class="title function_">set</span>(<span class="function"><span class="params">s</span> =&gt;</span> (&#123; <span class="attr">count</span>: s.<span class="property">count</span> + <span class="number">1</span> &#125;)),</span><br><span class="line">&#125;))</span><br><span class="line"><span class="comment">// 组件里直接用</span></span><br><span class="line"><span class="keyword">const</span> &#123; count, add &#125; = <span class="title function_">useStore</span>()</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="选型-3"><p><strong>Redux Toolkit</strong>：严格的单向数据流、时间旅行调试、完善的中间件体系，团队协作规范性强，代价是样板代码偏多。</p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="十三、性能优化清单"><a href="#十三、性能优化清单" class="headerlink" title="十三、性能优化清单"></a>十三、性能优化清单</h2><ul><li>列表项组件用 <code>React.memo</code> 包裹，父组件重渲染时跳过未变化的子项</li><li>传给 memo 子组件的回调函数用 <code>useCallback</code> 包住，避免引用变化让 memo 失效</li><li>长列表用虚拟滚动（<code>react-window</code> &#x2F; <code>react-virtuoso</code>），只渲染可视区域</li><li>路由级代码分割：<code>const Page = lazy(() =&gt; import(&#39;./Page&#39;))</code> 配合 <code>&lt;Suspense&gt;</code></li><li>图片懒加载 + CDN + 合适尺寸（可参考本站的封面缩放做法）</li></ul><h2 id="十四、常见坑速查"><a href="#十四、常见坑速查" class="headerlink" title="十四、常见坑速查"></a>十四、常见坑速查</h2><table><thead><tr><th>现象</th><th>原因</th><th>解法</th></tr></thead><tbody><tr><td>setState 后读到旧值</td><td>更新是异步批量的</td><td>用 <code>useEffect</code> 监听，或直接用新值</td></tr><tr><td>连续 setState 只生效一次</td><td>用了快照值而非函数式更新</td><td>改成 <code>setCount(c =&gt; c + 1)</code></td></tr><tr><td>useEffect 死循环</td><td>依赖里放了每次渲染都变的对象&#x2F;数组</td><td>用 <code>useMemo</code> 稳定引用，或调整依赖</td></tr><tr><td>列表删除后输入框错位</td><td>用 index 当 key</td><td>换成数据里的稳定 id</td></tr><tr><td>样式没生效</td><td>写了 <code>class</code> 而不是 <code>className</code></td><td>改 <code>className</code></td></tr><tr><td>事件里 e.target 变成 null</td><td>React 的事件对象会被回收</td><td>先解构 <code>const &#123; value &#125; = e.target</code></td></tr></tbody></table><h2 id="十五、React-与-Vue-对照"><a href="#十五、React-与-Vue-对照" class="headerlink" title="十五、React 与 Vue 对照"></a>十五、React 与 Vue 对照</h2><table><thead><tr><th>能力</th><th>React</th><th>Vue 3</th></tr></thead><tbody><tr><td>模板</td><td>JSX（JS 里写 HTML）</td><td>template（HTML 里写 JS）</td></tr><tr><td>状态</td><td><code>useState</code></td><td><code>ref</code> &#x2F; <code>reactive</code></td></tr><tr><td>副作用</td><td><code>useEffect</code> + 依赖数组</td><td><code>watch</code> &#x2F; <code>watchEffect</code>（自动收集依赖）</td></tr><tr><td>计算属性</td><td><code>useMemo</code></td><td><code>computed</code></td></tr><tr><td>组件通信</td><td>props + 回调</td><td>props + <code>emit</code></td></tr><tr><td>跨层传递</td><td>Context</td><td>provide &#x2F; inject</td></tr></tbody></table><p>两者思想高度相似（虚拟 DOM + 响应式 + 组件化），精通一个后学另一个的成本很低。</p><hr><div class="note success flat"><p><strong>学习路径建议</strong>：JSX → 组件&#x2F;Props → useState 与事件 → 条件与列表渲染 → useEffect → 表单 → 自定义 Hook → 路由 → 状态管理。每一步都配一个小 demo，比通读文档有效得多。</p></div>]]></content>
    
    
    <summary type="html">React 学习笔记整理，涵盖组件设计、Hooks 常用用法、状态管理与前端工程实践中的常见问题。</summary>
    
    
    
    <category term="前端开发" scheme="https://www.amoit.top/categories/%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91/"/>
    
    
    <category term="前端" scheme="https://www.amoit.top/tags/%E5%89%8D%E7%AB%AF/"/>
    
    <category term="学习笔记" scheme="https://www.amoit.top/tags/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
    
    <category term="React" scheme="https://www.amoit.top/tags/React/"/>
    
  </entry>
  
  <entry>
    <title>Windows 10 磁盘分区</title>
    <link href="https://www.amoit.top/posts/windows10-disk-partition/"/>
    <id>https://www.amoit.top/posts/windows10-disk-partition/</id>
    <published>2024-01-04T11:37:01.000Z</published>
    <updated>2026-10-06T15:01:03.551Z</updated>
    
    <content type="html"><![CDATA[<div class="note info flat"><p>新电脑只有一个 C 盘，或者想把游戏、素材单独放一个盘 —— 这篇把 Windows 10 下分区的三种方法（系统工具 &#x2F; 命令行 &#x2F; 第三方）和常见翻车点整理清楚。</p></div><h2 id="一、先想清楚要不要分"><a href="#一、先想清楚要不要分" class="headerlink" title="一、先想清楚要不要分"></a>一、先想清楚要不要分</h2><table><thead><tr><th>分盘的好处</th><th>分盘的代价</th></tr></thead><tbody><tr><td>系统盘满了不会拖累整个电脑</td><td>每个盘空间固定，后期调整麻烦</td></tr><tr><td>重装系统只格式化 C 盘，资料盘不受影响</td><td>盘之间移动文件较慢（跨分区）</td></tr><tr><td>文件分类清晰，备份方便</td><td>分配不均时容易某个盘爆满</td></tr></tbody></table><div class="note info flat"><p><strong>现在的建议</strong>：SSD 上分 2 个区就够（系统盘 + 数据盘）。机械硬盘可以按需多分。不用刻意追求「四个盘」，反而容易顾此失彼。</p></div><h2 id="二、动手前必做"><a href="#二、动手前必做" class="headerlink" title="二、动手前必做"></a>二、动手前必做</h2><div class="note danger flat"><p>分区涉及磁盘底层结构，<strong>任何一步出错都可能导致数据丢失</strong>。开始前：</p><ol><li>重要文件<strong>备份到移动硬盘或云盘</strong>（这是唯一真正保险的做法）</li><li>笔记本保证接电源，中途断电风险极高</li><li>确认 BitLocker 已关闭（控制面板 → BitLocker 驱动器加密）</li></ol></div><h2 id="三、方法一：Windows-自带「磁盘管理」（推荐新手）"><a href="#三、方法一：Windows-自带「磁盘管理」（推荐新手）" class="headerlink" title="三、方法一：Windows 自带「磁盘管理」（推荐新手）"></a>三、方法一：Windows 自带「磁盘管理」（推荐新手）</h2><h3 id="打开磁盘管理"><a href="#打开磁盘管理" class="headerlink" title="打开磁盘管理"></a>打开磁盘管理</h3><p>任选一种：</p><ul><li>右键「此电脑」→ <strong>管理</strong> → 左侧「存储」→ <strong>磁盘管理</strong></li><li><code>Win + X</code> → 磁盘管理</li><li><code>Win + R</code> → 输入 <code>diskmgmt.msc</code> → 回车</li></ul><p>打开后能看到所有磁盘和分区的图形条：蓝色是主分区，黑色是<strong>未分配空间</strong>。</p><h3 id="第一步：压缩卷（腾出空间）"><a href="#第一步：压缩卷（腾出空间）" class="headerlink" title="第一步：压缩卷（腾出空间）"></a>第一步：压缩卷（腾出空间）</h3><ol><li>选择要拆分的那个盘（通常是 C 盘），<strong>右键 → 压缩卷</strong></li><li>系统会自动计算可压缩空间，稍等几秒</li><li>在弹出的窗口输入要压缩出的容量</li></ol><div class="note warning flat"><p><strong>单位换算</strong>：这里填的是 <strong>MB</strong>。想要 100GB 就填 <code>100 × 1024 = 102400</code>。</p><p>另外，<strong>「可用压缩空间大小」通常远小于磁盘剩余空间</strong>，这是正常的 —— 见第六节的原因与解法。</p></div><ol start="4"><li>点击「压缩」，完成后会出现一块黑色的「未分配」区域</li></ol><h3 id="第二步：新建简单卷（建立新盘）"><a href="#第二步：新建简单卷（建立新盘）" class="headerlink" title="第二步：新建简单卷（建立新盘）"></a>第二步：新建简单卷（建立新盘）</h3><ol><li>右键那块<strong>未分配</strong>的黑色区域 → <strong>新建简单卷</strong></li><li>进入向导，一路「下一步」：<ul><li><strong>指定卷大小</strong> —— 用满就保持默认；想再分几个区就填小一点</li><li><strong>分配驱动器号</strong> —— 选一个没用过的字母（如 D、E）</li><li><strong>格式化分区</strong> —— 文件系统选 <strong>NTFS</strong>，勾选「执行快速格式化」，卷标可以填「数据」「游戏」之类</li></ul></li><li>点击「完成」</li></ol><p>稍等几秒，打开「此电脑」就能看到新分区了。</p><h3 id="第三步：删除分区（收回到未分配）"><a href="#第三步：删除分区（收回到未分配）" class="headerlink" title="第三步：删除分区（收回到未分配）"></a>第三步：删除分区（收回到未分配）</h3><p>需要合并分区时用：右键分区 → <strong>删除卷</strong> → 确认。删除后该区域变回黑色未分配，可再分配给相邻分区。</p><h2 id="四、方法二：diskpart-命令行"><a href="#四、方法二：diskpart-命令行" class="headerlink" title="四、方法二：diskpart 命令行"></a>四、方法二：diskpart 命令行</h2><p>图形界面搞不定时用它（比如压缩卷按钮灰显、需要精确控制）。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 1. 以管理员身份打开 PowerShell 或 CMD</span></span><br><span class="line">Win + X → Windows PowerShell(管理员)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. 进入 diskpart</span></span><br><span class="line">diskpart</span><br><span class="line"></span><br><span class="line"><span class="comment"># 3. 查看磁盘列表</span></span><br><span class="line">list disk</span><br><span class="line"></span><br><span class="line"><span class="comment"># 4. 选择目标磁盘（把 0 换成你的磁盘编号）</span></span><br><span class="line">select disk 0</span><br><span class="line"></span><br><span class="line"><span class="comment"># 5. 查看该磁盘上的分区</span></span><br><span class="line">list partition</span><br><span class="line"></span><br><span class="line"><span class="comment"># 6. 选择要压缩的分区（把 3 换成主分区编号）</span></span><br><span class="line">select partition 3</span><br><span class="line"></span><br><span class="line"><span class="comment"># 7. 压缩出 100GB（单位 MB）</span></span><br><span class="line">shrink desired=102400</span><br><span class="line"></span><br><span class="line"><span class="comment"># 8. 用剩余空间创建主分区</span></span><br><span class="line">create partition primary</span><br><span class="line"></span><br><span class="line"><span class="comment"># 9. 格式化</span></span><br><span class="line">format fs=ntfs quick</span><br><span class="line"></span><br><span class="line"><span class="comment"># 10. 分配盘符</span></span><br><span class="line">assign letter=E</span><br><span class="line"></span><br><span class="line"><span class="comment"># 退出</span></span><br><span class="line"><span class="built_in">exit</span></span><br></pre></td></tr></table></figure><div class="note danger flat"><p><code>list disk</code> 后务必核对<strong>磁盘容量</strong>再 <code>select</code>，选错磁盘会操作到移动硬盘甚至另一块系统盘。<code>clean</code> 命令会清空整块磁盘，不到万不得已不要用。</p></div><h2 id="五、方法三：第三方工具"><a href="#五、方法三：第三方工具" class="headerlink" title="五、方法三：第三方工具"></a>五、方法三：第三方工具</h2><p>自带工具搞不定的场景（调整分区大小、合并相邻分区、MBR 转 GPT），用第三方更省事：</p><table><thead><tr><th>工具</th><th>特点</th></tr></thead><tbody><tr><td><a href="https://www.diskpart.com/">傲梅分区助手</a></td><td>免费、中文、操作直观，支持无损调整大小</td></tr><tr><td>DiskGenius</td><td>功能强大，数据恢复也强，免费版够用</td></tr><tr><td>MiniTool Partition Wizard</td><td>界面友好，免费版有功能限制</td></tr></tbody></table><div class="note info flat"><p>傲梅分区助手的「<strong>分配空闲空间</strong>」功能可以直接把 D 盘的空余空间划给 C 盘，这是系统自带工具做不到的（自带工具要求空间必须相邻且在右侧）。</p></div><h2 id="六、分区表与文件系统"><a href="#六、分区表与文件系统" class="headerlink" title="六、分区表与文件系统"></a>六、分区表与文件系统</h2><h3 id="MBR-还是-GPT"><a href="#MBR-还是-GPT" class="headerlink" title="MBR 还是 GPT"></a>MBR 还是 GPT</h3><table><thead><tr><th></th><th>MBR</th><th>GPT</th></tr></thead><tbody><tr><td>最大磁盘</td><td>2 TB</td><td>理论无上限</td></tr><tr><td>主分区数量</td><td>最多 4 个</td><td>最多 128 个</td></tr><tr><td>启动方式</td><td>Legacy BIOS</td><td>UEFI（现在的标配）</td></tr><tr><td>容错</td><td>无备份分区表</td><td>有多份备份</td></tr></tbody></table><div class="note info flat"><p>新电脑（UEFI 启动）一律是 <strong>GPT</strong>。查看方式：磁盘管理里右键磁盘（左侧「磁盘 0」那块）→ 属性 → 卷 → 分区样式。老机器想用 2TB 以上硬盘必须转 GPT。</p></div><h3 id="文件系统怎么选"><a href="#文件系统怎么选" class="headerlink" title="文件系统怎么选"></a>文件系统怎么选</h3><table><thead><tr><th>格式</th><th>单个文件上限</th><th>适用</th></tr></thead><tbody><tr><td><strong>NTFS</strong></td><td>16 TB</td><td><strong>Windows 分区默认选择</strong>，支持权限、压缩、加密</td></tr><tr><td>exFAT</td><td>16 EB</td><td>U 盘、移动硬盘，Win&#x2F;Mac 通用</td></tr><tr><td>FAT32</td><td>4 GB</td><td>老设备、车载 U 盘（放不下高清电影）</td></tr></tbody></table><h2 id="七、常见问题"><a href="#七、常见问题" class="headerlink" title="七、常见问题"></a>七、常见问题</h2><h3 id="「可用压缩空间」远小于剩余空间"><a href="#「可用压缩空间」远小于剩余空间" class="headerlink" title="「可用压缩空间」远小于剩余空间"></a>「可用压缩空间」远小于剩余空间</h3><div class="note warning flat"><p>原因：NTFS 里有些<strong>不可移动的文件</strong>卡在磁盘中间，压缩只能到它们的位置为止。常见的是：</p><ul><li>页面文件 <code>pagefile.sys</code>（虚拟内存）</li><li>休眠文件 <code>hiberfil.sys</code></li><li>系统还原点 &#x2F; 卷影复制</li><li>MFT 主文件表等元数据</li></ul></div><p>解决办法（按需选择，做完重启后再压缩）：</p><figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 1. 关闭休眠（会删除 hiberfil.sys，省出几个 GB）</span></span><br><span class="line">powercfg <span class="literal">-h</span> off</span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. 关闭系统保护（此电脑 → 属性 → 系统保护 → 配置 → 禁用）</span></span><br><span class="line"><span class="comment">#    或命令行：</span></span><br><span class="line">vssadmin delete shadows /all /quiet</span><br><span class="line"></span><br><span class="line"><span class="comment"># 3. 临时把虚拟内存设为无（控制面板 → 系统 → 高级 → 性能 → 虚拟内存）</span></span><br></pre></td></tr></table></figure><p>机械硬盘还可以先做一次<strong>碎片整理</strong>（优化驱动器），把文件挪到前面，能多腾出空间。</p><h3 id="压缩卷-扩展卷按钮是灰的"><a href="#压缩卷-扩展卷按钮是灰的" class="headerlink" title="压缩卷 &#x2F; 扩展卷按钮是灰的"></a>压缩卷 &#x2F; 扩展卷按钮是灰的</h3><table><thead><tr><th>原因</th><th>解法</th></tr></thead><tbody><tr><td>磁盘是「动态磁盘」</td><td>需先转回基本磁盘（数据会丢，先备份）</td></tr><tr><td>分区是 FAT32 或未格式化</td><td>转成 NTFS：<code>convert X: /fs:ntfs</code></td></tr><tr><td>BitLocker 已加密</td><td>先解密</td></tr><tr><td>剩余空间为 0</td><td>先清理磁盘</td></tr></tbody></table><h3 id="扩展卷灰显，扩不了-C-盘"><a href="#扩展卷灰显，扩不了-C-盘" class="headerlink" title="扩展卷灰显，扩不了 C 盘"></a>扩展卷灰显，扩不了 C 盘</h3><div class="note danger flat"><p>Windows 自带的「扩展卷」<strong>只能吸收右侧紧邻的未分配空间</strong>。如果你的 C 盘右边是 D 盘，即使把 D 盘删了，也只有 D 盘能扩展，C 盘不行 —— 必须用第三方工具（傲梅、DiskGenius）来移动分区。</p></div><h3 id="新建的分区在「此电脑」看不到"><a href="#新建的分区在「此电脑」看不到" class="headerlink" title="新建的分区在「此电脑」看不到"></a>新建的分区在「此电脑」看不到</h3><p>多半是没格式化或没分配盘符。回到磁盘管理，右键该分区 → <strong>更改驱动器号和路径</strong> → 添加一个盘符即可。</p><h3 id="关于-4K-对齐"><a href="#关于-4K-对齐" class="headerlink" title="关于 4K 对齐"></a>关于 4K 对齐</h3><p>固态硬盘需要 4K 对齐才能发挥性能。Windows 7 之后系统创建的分区<strong>默认已对齐</strong>，不用管。验证方式：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 管理员 PowerShell</span></span><br><span class="line">wmic partition get StartingOffset</span><br><span class="line"><span class="comment"># 结果能被 4096 整除即为已对齐</span></span><br></pre></td></tr></table></figure><h2 id="八、分区方案参考"><a href="#八、分区方案参考" class="headerlink" title="八、分区方案参考"></a>八、分区方案参考</h2><table><thead><tr><th>硬盘</th><th>建议</th></tr></thead><tbody><tr><td>512GB SSD</td><td>C 盘 200GB（系统+软件）+ D 盘剩余（资料）</td></tr><tr><td>1TB SSD</td><td>C 盘 250～300GB，剩余做数据盘</td></tr><tr><td>1TB SSD + 2TB HDD</td><td>SSD 装系统和常用软件，HDD 存影音素材与备份</td></tr></tbody></table><div class="note info flat"><p><strong>C 盘别分太小</strong>。Windows 本身约 30GB，加上更新、软件默认安装路径、缓存目录，200GB 是较稳妥的下限，低于 150GB 未来大概率要扩容。</p></div><h2 id="九、最后确认"><a href="#九、最后确认" class="headerlink" title="九、最后确认"></a>九、最后确认</h2><p>分区完成后检查这几项：</p><ul><li><input disabled="" type="checkbox"> 「此电脑」里新盘符可见且能正常读写</li><li><input disabled="" type="checkbox"> 磁盘管理中无异常状态（不显示「未分配」残留）</li><li><input disabled="" type="checkbox"> 原分区的文件完好无损</li><li><input disabled="" type="checkbox"> 固态硬盘的 4K 已对齐（见上文命令）</li><li><input disabled="" type="checkbox"> 若之前关了休眠&#x2F;系统保护，按需重新开启</li></ul><hr><div class="note success flat"><p><strong>最省心的顺序</strong>：备份 → 磁盘管理压缩卷 → 新建简单卷。自带工具足够应付 90% 的需求，需要跨分区挪空间时再上第三方工具。</p></div>]]></content>
    
    
    <summary type="html">Windows 10 磁盘分区方法整理，含磁盘管理工具使用、分区格式选择与数据安全注意事项。</summary>
    
    
    
    <category term="工具效率" scheme="https://www.amoit.top/categories/%E5%B7%A5%E5%85%B7%E6%95%88%E7%8E%87/"/>
    
    
    <category term="Windows" scheme="https://www.amoit.top/tags/Windows/"/>
    
    <category term="系统工具" scheme="https://www.amoit.top/tags/%E7%B3%BB%E7%BB%9F%E5%B7%A5%E5%85%B7/"/>
    
  </entry>
  
  <entry>
    <title>Windows 10 搭建 GitLab 服务器</title>
    <link href="https://www.amoit.top/posts/gitlab-server-win10/"/>
    <id>https://www.amoit.top/posts/gitlab-server-win10/</id>
    <published>2024-01-04T11:37:01.000Z</published>
    <updated>2026-10-06T12:33:24.567Z</updated>
    
    <content type="html"><![CDATA[<p>参考文章：</p><h2 id="Clash-for-windows"><a href="#Clash-for-windows" class="headerlink" title="Clash for windows"></a>Clash for windows</h2><h3 id="配置：windows10"><a href="#配置：windows10" class="headerlink" title="配置：windows10"></a>配置：windows10</h3><h3 id="方法一-暂时未成功-docker无法在非专业版windows10进行配置没找到虚拟机接口"><a href="#方法一-暂时未成功-docker无法在非专业版windows10进行配置没找到虚拟机接口" class="headerlink" title="方法一 暂时未成功 docker无法在非专业版windows10进行配置没找到虚拟机接口"></a>方法一 暂时未成功 docker无法在非专业版windows10进行配置没找到虚拟机接口</h3><p>在家庭版安装Hyper-v虚拟机<br>参考文献：<br>Hyper-V是Windows系统自带的虚拟机软件，其主要功能是在不影响原系统的情况下创建多个Windows或非Windows子系统。</p><p>请注意：Hyper-V 仅在 Windows 10 专业版、企业版和教育版以及 Windows Server 2012 及以上版本中可用。<br>1、打开记事本输入以下命令。</p><p>&#96;&#96;</p><p>pushd “%~dp0”</p><p>dir &#x2F;b %SystemRoot%\servicing\Packages*Hyper-V*.mum &gt;hyper-v.txt</p><p>for &#x2F;f %%i in (‘findstr &#x2F;i . hyper-v.txt 2^&gt;nul’) do dism &#x2F;online &#x2F;norestart &#x2F;add-package:”%SystemRoot%\servicing\Packages%%i”<br>del hyper-v.txt<br>Dism &#x2F;online &#x2F;enable-feature &#x2F;featurename:Microsoft-Hyper-V-All &#x2F;LimitAccess &#x2F;ALL</p><p>&#96;&#96;<br>2、保存并命名为 Hyper-V.cmd，然后点击文件，右键以管理员身份运行，等待执行完成</p><p>3、输入Y重启计算机，重启完后就可以按Win键在开始菜单下的Windows管理工具查看有没有安装成功，安装成功会有个Hyper-V管理器</p><p>docker 删除不干净问题<br>参考文章：</p><p>解决方法：<br>把 C:&#x2F;Program Files&#x2F;Docker 删除后<br><code>按下Window+R唤起命令输入界面，输入regedit打开注册表编辑 在地址栏输入HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Docker Desktop 将整个Docker Desktop组点击右键删除</code></p><h3 id="方法二-ubuntu-应用商店自带（推荐）【2024-1-5可用】"><a href="#方法二-ubuntu-应用商店自带（推荐）【2024-1-5可用】" class="headerlink" title="方法二 ubuntu 应用商店自带（推荐）【2024.1.5可用】"></a>方法二 ubuntu 应用商店自带（推荐）【2024.1.5可用】</h3><p>1）打开ubuntu<br>设置用户名和密码<br>2）<br><code>https://about.gitlab.com/downloads/#ubuntu1404</code></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">sudo apt update</span><br><span class="line"></span><br><span class="line">sudo apt-get upgrade</span><br><span class="line"></span><br><span class="line">sudo apt-get install curl openssh-server ca-certificates postfix</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>出现的问题：<br>1.Ubuntu错误提示 E: Could not open lock file &#x2F;var&#x2F;lib&#x2F;dpkg&#x2F;lock-frontend - open<br>解决方案：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">1. sudo rm /var/lib/dpkg/lock-frontend</span><br><span class="line">2. sudo rm /var/lib/dpkg/lock</span><br><span class="line">3. sudo apt install p7zip-full</span><br></pre></td></tr></table></figure><p>2.找不到gitLabURL<br>解决方案：<br>[windows10 找寻ip地址：192.168.0.129:8077 root密码123456]<br>把&#x2F;etc&#x2F;gitlab&#x2F;gitlab弄坏了<br>一定要输入i！！！！<br>然后</p><h3 id="方法三：windows10改ubuntu搭建gitlab服务器"><a href="#方法三：windows10改ubuntu搭建gitlab服务器" class="headerlink" title="方法三：windows10改ubuntu搭建gitlab服务器"></a>方法三：windows10改ubuntu搭建gitlab服务器</h3><pre><code>准备：1.U盘 32G（作者使用）2.window10系统的电脑</code></pre><p>【把u盘变成装两个系统1.window10 2.ubuntu 的功能盘】<br>1.先分区 用DiskGenius</p><h4 id="1-windows10改ubuntu"><a href="#1-windows10改ubuntu" class="headerlink" title="1.windows10改ubuntu"></a>1.windows10改ubuntu</h4><p>1）Ubuntu系统镜像下载<br><img src="https://cdn.jsdelivr.net/gh/qvp-nvn/image/img/ubuntuzp.jpg" alt="ubuntu首页照片"><br>2.1）制作启动盘软件(UltraISO)下载<br>UltralSO官网：</p><blockquote><p><a href="https://filehippo.com/download_ultra-iso"></a><br>直接下载免费试用版本，全部默认下一步安装。<br>2.2）下载rufus(官网推荐)<br>下载地址（<a href="https://rufus.ie/%EF%BC%89%E6%88%96">https://rufus.ie/）或</a><br>下载地址(<a href="https://www.jb51.net/softs/86993.html">https://www.jb51.net/softs/86993.html</a>)<br>【 分区类型：GPT和MBR的区别】<br>MBR<br>MBR的意思是“主引导记录”，是IBM公司早年间提出的。它是存在于磁盘驱动器开始部分的一个特殊的启动扇区。这个扇区包含了已安装的操作系统系统信息，并用一小段代码来启动系统。如果你安装了Windows，其启动信息就放在这一段代码中——如果MBR的信息损坏或误删就不能正常启动Windows，这时候你就需要找一个引导修复软件工具来修复它就可以了。Linux系统中MBR通常会是GRUB加载器。MBR。当一台电脑启动时，它会先启动主板自带的BIOS系统，bios加载MBR，MBR再启动Windows，这就是mbr的启动过程。<br>GPT<br>GPT的意思是GUID Partition Table，即“全局唯一标识磁盘分区表”。他是另外一种更加先进新颖的磁盘组织方式，一种使用UEFI启动的磁盘组织方式。最开始是为了更好的兼容性，后来因为其更大的支持内存（mbr分区最多支持2T的磁盘），更多的兼容而被广泛使用，特别是苹果的MAC系统全部使用gpt分区。gtp不在有分区的概念，所有CDEF盘都在一段信息中存储。<br>这是一个正逐渐取代MBR的新标准，它和UEFI相辅相成——UEFI用于取代老旧的BIOS，而GPT则取代老旧的MBR。之所以叫作”GUID分区表”，是因为你的驱动器上的每个分区都有一个全局唯一的标识符（globally unique identifier，GUID）——这是一个随机生成的字符串，可以保证为地球上的每一个GPT分区都分配完全唯一的标识符；<br>MBR分区和GPT分区的区别<br>因为兼容问题，gpt其实在引导的最开始部分也有一段mbr引导，也叫做“保护引导”，为了防止设备不支持uefi。</p></blockquote><p>mbr最多支持2T，而gpt理论上是无限制的。<br>mbr最多支持四个主分区，gpt没有限制。如果你想跑多系统，mbr最多4个而gpt没有限制。<br>win7只能用mbr分区，从Win8开始微软建议你使用gpt。<br>gpt是由uefi启动的，而uefi是后来才提出的概念，兼容性和稳定性不如bios+mbr。</p><p>原文链接：<a href="https://blog.csdn.net/wjzh2008/article/details/126927841">https://blog.csdn.net/wjzh2008/article/details/126927841</a><br>【文件系统】<br>文件系统，是计算机管理数据的一种目录结构。<br><em>两张对比图片</em><br><img src="https://cdn.jsdelivr.net/gh/qvp-nvn/image/img/%25E6%2596%2587%25E4%25BB%25B6%25E7%25B3%25BB%25E7%25BB%259F%25E5%25AF%25B9%25E6%25AF%25941.png" alt="文件系统对比1"><br><img src="https://cdn.jsdelivr.net/gh/qvp-nvn/image/img/%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E5%AF%B9%E6%AF%942.png" alt="文件系统对比2"></p><p><img src="https://cdn.jsdelivr.net/gh/qvp-nvn/image/img/rufus.jpg" alt="rufus"><br>【建议使用GPT和NTFS】</p><p>单击第二行的“选择”，选择下载好的Ubuntu的iso文件。</p><p>单机“打开”，询问是否下载，选择“是”。</p><p>选择第一个，选择“OK”，再选择确定，稍等一会，启动盘制作完成。</p><p>三、安装Ubuntu<br>重启电脑，从u盘启动，作者从F11进入的</p><p>进入Ubuntu（safe graphics）</p><p>在界面中进入安装程序<br>中文简体-安装Ubuntu-键盘布局建议选English(US)-网络连接-最小安装，其他默认-清除整个磁盘并安装Ubuntu，也可以分区【<a href="https://blog.csdn.net/u012052268/article/details/77145427">分区参考</a>】-设置时区【自行设置】-设置用户名密码-自行设置-进行配置-在对应提示时拔掉u盘启动盘-进入ubuntu系统</p><h4 id="2-ubuntu系统中搭建gitlab"><a href="#2-ubuntu系统中搭建gitlab" class="headerlink" title="2.ubuntu系统中搭建gitlab"></a>2.ubuntu系统中搭建gitlab</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">sudo apt update</span><br><span class="line"></span><br><span class="line">sudo apt-get upgrade</span><br><span class="line"></span><br><span class="line">sudo apt-get install curl openssh-server ca-certificates postfix</span><br><span class="line">也可以用</span><br><span class="line">sudo apt-get install -y curl openssh-server ca-certificates tzdata perl</span><br><span class="line"></span><br><span class="line">curl -s https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>可以用在线和离线两种方式下载gitlab<br>1.在线【推荐】<br>2.离线</p>]]></content>
    
    
    <summary type="html">在 Windows 10 上本地搭建 GitLab 服务器的步骤记录，含环境准备、服务启动与常见问题排查。</summary>
    
    
    
    <category term="环境配置" scheme="https://www.amoit.top/categories/%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE/"/>
    
    
    <category term="Windows" scheme="https://www.amoit.top/tags/Windows/"/>
    
    <category term="GitLab" scheme="https://www.amoit.top/tags/GitLab/"/>
    
    <category term="服务器" scheme="https://www.amoit.top/tags/%E6%9C%8D%E5%8A%A1%E5%99%A8/"/>
    
  </entry>
  
  <entry>
    <title>PicGo + GitHub 图床搭建</title>
    <link href="https://www.amoit.top/posts/picgo-github-image-bed/"/>
    <id>https://www.amoit.top/posts/picgo-github-image-bed/</id>
    <published>2024-01-02T05:06:27.000Z</published>
    <updated>2026-10-06T15:03:59.892Z</updated>
    
    <content type="html"><![CDATA[<div class="note info flat"><p>写博客最烦的事之一，就是图片没地方放。这篇记录用 <strong>PicGo + GitHub + jsDelivr</strong> 搭一套免费、稳定、可长期使用的图床，Mac 上的完整流程（Windows 步骤基本一致）。</p></div><h2 id="一、图床是什么"><a href="#一、图床是什么" class="headerlink" title="一、图床是什么"></a>一、图床是什么</h2><p>图床就是<strong>专门存放图片的服务器</strong>，上传后返回一个 URL，把这个链接写进 Markdown 即可。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">本地图片 → 上传到图床 → 得到 https://xxx/a.png → 写进文章</span><br></pre></td></tr></table></figure><p>图床分国内和国外：</p><ul><li><strong>国外</strong>（GitHub、SM.MS、Imgur）：免费、不限量，但国内访问可能慢</li><li><strong>国内</strong>（七牛云、阿里云 OSS、腾讯云 COS）：速度快，通常需要实名 + 域名，<strong>超出免费额度要钱</strong></li></ul><h2 id="二、为什么选-GitHub-jsDelivr"><a href="#二、为什么选-GitHub-jsDelivr" class="headerlink" title="二、为什么选 GitHub + jsDelivr"></a>二、为什么选 GitHub + jsDelivr</h2><table><thead><tr><th>方案</th><th>费用</th><th>速度</th><th>稳定性</th><th>备注</th></tr></thead><tbody><tr><td><strong>GitHub + jsDelivr</strong></td><td>永久免费</td><td>⭐ 快（CDN 加速）</td><td>高</td><td>⭐ 本文方案</td></tr><tr><td>SM.MS</td><td>免费</td><td>一般</td><td>一般</td><td>免费版有限制，跑路过</td></tr><tr><td>七牛云 &#x2F; 阿里云 OSS</td><td>有免费额度</td><td>快</td><td>高</td><td>需实名 + 备案域名</td></tr><tr><td>微博 &#x2F; 知乎图床</td><td>免费</td><td>快</td><td>❌ 差</td><td>有防盗链，随时可能失效</td></tr><tr><td>付费图床（又拍云等）</td><td>付费</td><td>最快</td><td>最高</td><td>商业项目推荐</td></tr></tbody></table><div class="note success flat"><p>GitHub 仓库本身访问慢，但配合 <strong>jsDelivr</strong> 这个免费 CDN 后，图片会被缓存到全球节点，国内访问速度完全够用。而且数据在自己仓库里，<strong>迁移自由、不怕跑路</strong>。</p></div><h2 id="三、准备工作"><a href="#三、准备工作" class="headerlink" title="三、准备工作"></a>三、准备工作</h2><h3 id="1-创建-GitHub-仓库"><a href="#1-创建-GitHub-仓库" class="headerlink" title="1. 创建 GitHub 仓库"></a>1. 创建 GitHub 仓库</h3><ol><li>登录 GitHub，右上角 <code>+</code> → <strong>New repository</strong></li><li>填写仓库名（如 <code>image</code> 或 <code>blog-images</code>）</li><li><strong>必须选 Public（公开）</strong> —— jsDelivr 只能加速公开仓库</li><li>勾选 <strong>Add a README file</strong>（避免空仓库）</li><li>点 <strong>Create repository</strong> 完成</li></ol><div class="note warning flat"><p>仓库一定要 <strong>Public</strong>。私有仓库 jsDelivr 无法读取，图片会全部 403。</p></div><h3 id="2-创建个人-Token"><a href="#2-创建个人-Token" class="headerlink" title="2. 创建个人 Token"></a>2. 创建个人 Token</h3><p>Token 是给 PicGo 用的「钥匙」，让它有权限往你的仓库上传文件。</p><div class="tabs" id="token-类型"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#token-类型-1"><i class="fas fa-key"></i>Classic Token（推荐）</button></li><li class="tab"><button type="button" data-href="#token-类型-2"><i class="fas fa-shield-halved"></i>Fine-grained Token</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="token-类型-1"><ol><li>GitHub 右上角头像 → <strong>Settings</strong></li><li>左侧最下方 → <strong>Developer settings</strong></li><li><strong>Personal access tokens</strong> → <strong>Tokens (classic)</strong></li><li>右上角 <strong>Generate new token</strong> → <strong>Generate new token (classic)</strong></li><li>填写：<ul><li><strong>Note</strong>：随便写，如 <code>PicGo</code></li><li><strong>Expiration</strong>：选 <strong>No expiration</strong>（永不过期，省得每年来换）</li><li><strong>Select scopes</strong>：勾选 <strong><code>repo</code></strong>（勾选它会自动选中其下所有子项）</li></ul></li><li>拉到页面最底部，点绿色的 <strong>Generate token</strong></li></ol><div class="note danger flat"><p>Token <strong>只显示这一次</strong>，关掉页面就再也看不到了。立刻复制保存（可以存到备忘录或密码管理器）。</p></div><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="token-类型-2"><p>GitHub 现在也提供细粒度 Token，权限更精确、更安全：</p><ol><li>Settings → Developer settings → <strong>Personal access tokens</strong> → <strong>Fine-grained tokens</strong></li><li><strong>Generate new token</strong></li><li>Resource owner 选自己，<strong>Repository access</strong> 选 <strong>Only selected repositories</strong> → 选刚建的图床仓库</li><li><strong>Permissions</strong> → Repository permissions → 找到 <strong>Contents</strong> → 设为 <strong>Read and write</strong></li><li>生成并保存</li></ol><div class="note info flat"><p>细粒度 Token 更安全（泄露后只能操作这一个仓库），但 PicGo 对它的兼容性不如 classic 稳定。<strong>出问题就换回 classic</strong>。</p></div><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h3 id="3-安装-PicGo"><a href="#3-安装-PicGo" class="headerlink" title="3. 安装 PicGo"></a>3. 安装 PicGo</h3><p>PicGo 是一个用于快速上传图片并获取 URL 链接的工具。</p><div class="tabs" id="安装方式"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#安装方式-1"><i class="fab fa-apple"></i>macOS</button></li><li class="tab"><button type="button" data-href="#安装方式-2"><i class="fab fa-windows"></i>Windows</button></li><li class="tab"><button type="button" data-href="#安装方式-3"><i class="fab fa-linux"></i>Linux</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="安装方式-1"><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">brew install picgo --cask</span><br></pre></td></tr></table></figure><p>或从 <a href="https://github.com/Molunerfinn/PicGo/releases">GitHub Releases</a> 下载 <code>PicGo-x.x.x.dmg</code> 安装。</p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="安装方式-2"><p>到 <a href="https://github.com/Molunerfinn/PicGo/releases">GitHub Releases</a> 下载 <code>PicGo-Setup-x.x.x.exe</code>，一路下一步即可。</p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="安装方式-3"><p>下载 <code>PicGo-x.x.x.AppImage</code>，加执行权限后运行；或用 <code>snap install picgo</code>。</p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="四、配置-PicGo"><a href="#四、配置-PicGo" class="headerlink" title="四、配置 PicGo"></a>四、配置 PicGo</h2><p>打开 PicGo → 左侧「图床设置」→ <strong>GitHub 图床</strong>，逐项填写：</p><table><thead><tr><th>字段</th><th>填什么</th><th>示例</th></tr></thead><tbody><tr><td>仓库名</td><td><code>用户名/仓库名</code></td><td><code>qvp-nvn/image</code></td></tr><tr><td>分支名</td><td>主分支名</td><td><code>main</code>（老仓库可能是 <code>master</code>）</td></tr><tr><td>Token</td><td>上一步复制的 token</td><td><code>ghp_xxxxxxxxxxxx</code></td></tr><tr><td>存储路径</td><td>仓库里的目录（可空）</td><td><code>img/</code></td></tr><tr><td>自定义域名</td><td>jsDelivr 地址</td><td><code>https://cdn.jsdelivr.net/gh/用户名/仓库名</code></td></tr><tr><td>设定默认图床</td><td>✅ 打开</td><td>—</td></tr></tbody></table><div class="note danger flat"><p><strong>仓库名要写「用户名&#x2F;仓库名」完整格式</strong>，只写仓库名会上传失败。分支名也要和仓库实际分支一致（去 GitHub 仓库页面左上角确认）。</p></div><p>填完后点「确定」，并把 GitHub 图床设为<strong>默认图床</strong>。</p><h2 id="五、上传测试"><a href="#五、上传测试" class="headerlink" title="五、上传测试"></a>五、上传测试</h2><p>三种方式任选：</p><ol><li><strong>拖拽</strong> —— 把图片直接拖进 PicGo 的「上传区」</li><li><strong>剪贴板</strong> —— 截图后按快捷键（<code>⌘ + Shift + P</code> 默认）上传剪贴板图片</li><li><strong>点击上传区</strong> —— 选择文件上传</li></ol><p>上传成功后「相册」里会出现图片，右键 → <strong>复制 Markdown 链接</strong>，得到：</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">![<span class="string">图片说明</span>](<span class="link">https://cdn.jsdelivr.net/gh/qvp-nvn/image/img/a.png</span>)</span><br></pre></td></tr></table></figure><p>把这段粘进文章即可。</p><h2 id="六、用-jsDelivr-加速（关键一步）"><a href="#六、用-jsDelivr-加速（关键一步）" class="headerlink" title="六、用 jsDelivr 加速（关键一步）"></a>六、用 jsDelivr 加速（关键一步）</h2><p><strong>CDN</strong>（Content Delivery Network，内容分发网络）的原理：把内容缓存到离用户最近的节点，用户就近取数据，速度大幅提升。</p><p>jsDelivr 是一个免费、公开的 CDN，专门为开源项目服务，可以直接加速 GitHub 仓库里的文件。</p><p>配置方法很简单 —— 在 PicGo 的图床配置里填上<strong>自定义域名</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://cdn.jsdelivr.net/gh/用户名/仓库名</span><br></pre></td></tr></table></figure><p>填了之后，PicGo 返回的链接会从</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://raw.githubusercontent.com/用户名/仓库名/main/img/a.png   ← 慢</span><br></pre></td></tr></table></figure><p>变成</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://cdn.jsdelivr.net/gh/用户名/仓库名/img/a.png               ← 快</span><br></pre></td></tr></table></figure><div class="note info flat"><p>注意 jsDelivr 的 URL 里<strong>没有分支名</strong>。填错（多写一段 <code>/main</code>）会导致 404。</p></div><h2 id="七、在-Typora-中配置-PicGo"><a href="#七、在-Typora-中配置-PicGo" class="headerlink" title="七、在 Typora 中配置 PicGo"></a>七、在 Typora 中配置 PicGo</h2><p>配好之后，写文档时截图能<strong>自动上传并替换成图床链接</strong>，不用手动操作。</p><ol><li>Typora → 偏好设置（Preferences）→ <strong>图像</strong></li><li>「插入图片时」选择 <strong>上传图片</strong></li><li>「上传服务」选择 <strong>PicGo (app)</strong></li><li>PicGo 路径填 <code>/Applications/PicGo.app</code>（Windows 填 PicGo 安装路径）</li><li>点「验证图片上传选项」测试，出现成功提示即可</li></ol><div class="note success flat"><p>配置成功后，在 Typora 里直接 <code>⌘ + V</code> 粘贴截图，图片会自动上传并变成 jsDelivr 链接。写博客的效率提升非常明显。</p></div><p>其它编辑器：</p><table><thead><tr><th>编辑器</th><th>方案</th></tr></thead><tbody><tr><td>VS Code</td><td>装 <code>PicGo</code> 插件，或直接用 PicGo-Core + <code>vscode-picgo</code></td></tr><tr><td>Obsidian</td><td>装 <code>Image auto upload</code> 插件</td></tr><tr><td>命令行</td><td><code>npm install picgo -g</code>，然后 <code>picgo upload a.png</code></td></tr></tbody></table><h2 id="八、上传前先压缩"><a href="#八、上传前先压缩" class="headerlink" title="八、上传前先压缩"></a>八、上传前先压缩</h2><p>GitHub 仓库建议控制在 1GB 以内，图片累积起来很快。上传前压一下：</p><table><thead><tr><th>工具</th><th>用法</th></tr></thead><tbody><tr><td><a href="https://tinypng.com/">TinyPNG</a></td><td>拖拽压缩，免费每月 500 张</td></tr><tr><td><a href="https://squoosh.app/">Squoosh</a></td><td>在线转 WebP，可实时对比</td></tr><tr><td>PicGo 插件 <code>picgo-plugin-compress</code></td><td>上传时自动压缩（在插件设置里搜）</td></tr></tbody></table><div class="note info flat"><p>截图建议存 <strong>PNG</strong>（文字清晰），照片一律转 <strong>WebP</strong>（体积小 30% 以上）。一张 2MB 的图，博客里加载会明显卡顿。</p></div><h2 id="九、常见问题"><a href="#九、常见问题" class="headerlink" title="九、常见问题"></a>九、常见问题</h2><h3 id="图片上传失败"><a href="#图片上传失败" class="headerlink" title="图片上传失败"></a>图片上传失败</h3><table><thead><tr><th>现象</th><th>原因</th><th>解法</th></tr></thead><tbody><tr><td><code>404</code> &#x2F; 权限错误</td><td>Token 没勾 <code>repo</code> 或已过期</td><td>重新生成 Token</td></tr><tr><td>仓库不存在</td><td>仓库名格式写错</td><td>写成 <code>用户名/仓库名</code></td></tr><tr><td>分支错误</td><td>填了 master 但实际是 main</td><td>去仓库确认分支名</td></tr><tr><td>网络超时</td><td>GitHub 访问不畅</td><td>检查网络，或给 PicGo 配代理</td></tr></tbody></table><h3 id="图片能上传但打不开"><a href="#图片能上传但打不开" class="headerlink" title="图片能上传但打不开"></a>图片能上传但打不开</h3><ul><li>仓库是私有的 → 改成 Public</li><li>自定义域名写错了 → 去掉分支名，格式是 <code>.../gh/用户名/仓库名</code></li><li>刚上传就访问 → jsDelivr 缓存需要几十秒到几分钟，稍等再试</li></ul><h3 id="同名文件覆盖"><a href="#同名文件覆盖" class="headerlink" title="同名文件覆盖"></a>同名文件覆盖</h3><p>PicGo 默认会按时间戳重命名，正常不会重复。如果手动上传了同名文件，后传的会覆盖先前的 —— 建议开启 PicGo 的「<strong>时间戳重命名</strong>」。</p><h3 id="仓库越来越大"><a href="#仓库越来越大" class="headerlink" title="仓库越来越大"></a>仓库越来越大</h3><ul><li>GitHub 单个文件上限 <strong>100MB</strong>，jsDelivr 单文件限制 <strong>20MB</strong>，仓库建议 <strong>1GB 以内</strong></li><li>超出后 GitHub 会发邮件提醒，可考虑新建仓库（如 <code>image2</code>）分流</li></ul><h3 id="jsDelivr-缓存没更新"><a href="#jsDelivr-缓存没更新" class="headerlink" title="jsDelivr 缓存没更新"></a>jsDelivr 缓存没更新</h3><p>改了同名图片但链接内容没变，去 <a href="https://purge.jsdelivr.net/">purge.jsdelivr.net</a> 刷新缓存，或干脆换个文件名上传（更省事）。</p><h3 id="Token-泄露了怎么办"><a href="#Token-泄露了怎么办" class="headerlink" title="Token 泄露了怎么办"></a>Token 泄露了怎么办</h3><p>立刻去 Settings → Developer settings → 找到该 Token → <strong>Delete</strong>。然后重新生成一个并更新 PicGo 配置。<strong>永远不要把 Token 提交到公开仓库或写进文章里。</strong></p><h2 id="十、备份与迁移建议"><a href="#十、备份与迁移建议" class="headerlink" title="十、备份与迁移建议"></a>十、备份与迁移建议</h2><div class="note success flat"><ul><li>仓库定期 <code>git clone</code> 一份到本地或另一处，图床也是数据</li><li>关键图片（如站点 Logo、头像）<strong>不要只放在图床</strong>，本地留原件</li><li>万一 jsDelivr 不可用，改 PicGo 自定义域名即可切换 CDN，仓库里的图片不受影响</li></ul></div><hr><div class="note info flat"><p>这套方案我用了很久，成本为零、速度够用、数据在自己手里。唯一要养成的习惯是：<strong>上传前压缩，Token 别外泄</strong>。</p></div>]]></content>
    
    
    <summary type="html">使用 PicGo 配合 GitHub 仓库搭建免费图床的完整教程，含 Token 申请、仓库配置与自定义域名绑定。</summary>
    
    
    
    <category term="工具效率" scheme="https://www.amoit.top/categories/%E5%B7%A5%E5%85%B7%E6%95%88%E7%8E%87/"/>
    
    
    <category term="GitHub" scheme="https://www.amoit.top/tags/GitHub/"/>
    
    <category term="图床" scheme="https://www.amoit.top/tags/%E5%9B%BE%E5%BA%8A/"/>
    
    <category term="PicGo" scheme="https://www.amoit.top/tags/PicGo/"/>
    
  </entry>
  
  <entry>
    <title>Github 回滚代码</title>
    <link href="https://www.amoit.top/posts/github-roll-back-code/"/>
    <id>https://www.amoit.top/posts/github-roll-back-code/</id>
    <published>2023-03-08T11:37:01.000Z</published>
    <updated>2026-10-06T14:59:49.746Z</updated>
    
    <content type="html"><![CDATA[<div class="note info flat"><p>项目更新到最新版后异常报错，需要回到上一个版本 —— 这是最典型的回滚场景。原笔记只记了 <code>reset --hard</code> + <code>push -f</code> 这一条路，这次把几种方案补全，并说明<strong>什么时候不能用它</strong>。</p></div><h2 id="一、先搞清三个区域"><a href="#一、先搞清三个区域" class="headerlink" title="一、先搞清三个区域"></a>一、先搞清三个区域</h2><p>Git 的操作都绕不开这三个地方，理解它们，<code>reset</code> 就不再靠死记：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">工作区（你编辑的文件）  --git add--&gt;  暂存区（Index）  --git commit--&gt;  版本库（HEAD）</span><br><span class="line">        ↑                                  ↑                              ↑</span><br><span class="line">     改了还没 add                       add 了还没 commit               已经提交</span><br></pre></td></tr></table></figure><h2 id="二、找到要回滚到哪一次提交"><a href="#二、找到要回滚到哪一次提交" class="headerlink" title="二、找到要回滚到哪一次提交"></a>二、找到要回滚到哪一次提交</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">git <span class="built_in">log</span>                    <span class="comment"># 查看提交历史（从新到旧）</span></span><br><span class="line">git <span class="built_in">log</span> --oneline          <span class="comment"># 精简版，一行一条 ⭐ 最常用</span></span><br><span class="line">git <span class="built_in">log</span> --oneline -10      <span class="comment"># 只看最近 10 条</span></span><br><span class="line">git reflog                 <span class="comment"># ⭐ 查看所有操作记录（含被&quot;删掉&quot;的提交）</span></span><br></pre></td></tr></table></figure><p>输出长这样：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">$ git <span class="built_in">log</span> --oneline</span><br><span class="line">4ad24e8 (HEAD -&gt; main) 修复登录报错</span><br><span class="line">8f3c1a2 添加用户模块</span><br><span class="line">d91b077 初始化项目</span><br></pre></td></tr></table></figure><p><code>4ad24e8</code> 就是 commit hash（版本号），回滚时用它指定目标位置。</p><div class="note success flat"><p><strong><code>git reflog</code> 是后悔药</strong>。它记录了 HEAD 的每一次移动，包括你 <code>reset --hard</code> 掉的提交。只要操作过（commit 过），几乎都能用 reflog 找回来 —— 见第七节。</p></div><h2 id="三、reset-的三种模式（关键区别）"><a href="#三、reset-的三种模式（关键区别）" class="headerlink" title="三、reset 的三种模式（关键区别）"></a>三、reset 的三种模式（关键区别）</h2><p><code>git reset</code> 把 HEAD 移到指定提交，但<strong>工作区和暂存区怎么处理</strong>，由参数决定：</p><table><thead><tr><th>参数</th><th>版本库 HEAD</th><th>暂存区</th><th>工作区（你的文件）</th><th>危险性</th></tr></thead><tbody><tr><td><code>--soft</code></td><td>回退</td><td>保留</td><td><strong>保留</strong></td><td>低：改动都还在，只是撤了 commit</td></tr><tr><td><code>--mixed</code>（默认）</td><td>回退</td><td>重置</td><td><strong>保留</strong></td><td>中：撤了 commit 和 add</td></tr><tr><td><code>--hard</code></td><td>回退</td><td>重置</td><td><strong>删除</strong> ⚠️</td><td>高：改动直接丢失</td></tr></tbody></table><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">git reset --soft  8f3c1a2    <span class="comment"># 只是撤销提交，改动保留在暂存区，可重新 commit</span></span><br><span class="line">git reset --mixed 8f3c1a2    <span class="comment"># 撤销提交和 add，改动回到工作区</span></span><br><span class="line">git reset --hard  8f3c1a2    <span class="comment"># 彻底回到 8f3c1a2 的状态，之后的改动全丢弃</span></span><br></pre></td></tr></table></figure><div class="note danger flat"><p><code>--hard</code> 会<strong>永久丢弃</strong>目标提交之后的所有改动（未 commit 的内容也会一起没）。执行前先确认没有需要保留的代码 —— 不确定就先 <code>git stash</code> 或新建分支备份。</p></div><h2 id="四、场景一：回滚本地提交（还没-push）"><a href="#四、场景一：回滚本地提交（还没-push）" class="headerlink" title="四、场景一：回滚本地提交（还没 push）"></a>四、场景一：回滚本地提交（还没 push）</h2><p>最安全的情况，因为只影响你自己的仓库。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 1. 查看历史，找到目标版本</span></span><br><span class="line">git <span class="built_in">log</span> --oneline</span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. 回退（想保留改动用 --soft，不要了用 --hard）</span></span><br><span class="line">git reset --hard 8f3c1a2</span><br><span class="line"></span><br><span class="line"><span class="comment"># 3. 确认结果</span></span><br><span class="line">git <span class="built_in">log</span> --oneline</span><br><span class="line">git status</span><br></pre></td></tr></table></figure><p>此时本地已经回到上一个版本。</p><div class="note warning flat"><p>如果 <code>git reset --hard</code> 之后发现<strong>回退错了</strong>，<code>git log</code> 里已经看不到那些提交了 —— 别慌，用 <code>git reflog</code> 找到原来的 hash，再 <code>git reset --hard &lt;那个hash&gt;</code> 就能回来。</p></div><h2 id="五、场景二：回滚已推送到远程（GitHub）"><a href="#五、场景二：回滚已推送到远程（GitHub）" class="headerlink" title="五、场景二：回滚已推送到远程（GitHub）"></a>五、场景二：回滚已推送到远程（GitHub）</h2><div class="note danger flat"><p><code>git reset</code> 只改本地，<strong>GitHub 上的代码不会跟着变</strong>。想让远程也回退，必须强制推送 —— 但这一步是团队协作中最危险的操作之一。</p></div><h3 id="方案-A：reset-强制推送（原笔记的做法）"><a href="#方案-A：reset-强制推送（原笔记的做法）" class="headerlink" title="方案 A：reset + 强制推送（原笔记的做法）"></a>方案 A：reset + 强制推送（原笔记的做法）</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git reset --hard 8f3c1a2     <span class="comment"># 本地回退</span></span><br><span class="line">git push -f                  <span class="comment"># 强制推送，覆盖远程</span></span><br></pre></td></tr></table></figure><p><strong>仅在满足全部以下条件时使用</strong>：</p><ul><li>✅ 这是你个人的仓库 &#x2F; 分支</li><li>✅ 确定没有别人基于这些提交继续开发</li><li>✅ 已通知可能受影响的人</li></ul><div class="note danger flat"><p><code>-f</code>（<code>--force</code>）会用你的本地历史<strong>直接覆盖远程</strong>，别人的提交会被抹掉。多人协作的主分支上这么做，同事下次 pull 会丢失工作。</p><p>更安全的写法是 <code>git push --force-with-lease</code>：推送前先检查远程是否有你不知道的新提交，有则拒绝推送，避免误覆盖。</p></div><h3 id="方案-B：revert（推荐，不改写历史）"><a href="#方案-B：revert（推荐，不改写历史）" class="headerlink" title="方案 B：revert（推荐，不改写历史）"></a>方案 B：revert（推荐，不改写历史）</h3><p><code>revert</code> 的思路不是「删掉历史」，而是<strong>新建一次提交，把之前的改动反向抵消</strong>。历史完整保留，所有人正常 pull 即可同步。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 撤销某一次提交（会打开编辑器填写提交信息）</span></span><br><span class="line">git revert 4ad24e8</span><br><span class="line"></span><br><span class="line"><span class="comment"># 直接提交，不打开编辑器</span></span><br><span class="line">git revert --no-edit 4ad24e8</span><br><span class="line"></span><br><span class="line"><span class="comment"># 撤销连续多次提交（不包含起点 d91b077，包含终点 4ad24e8）</span></span><br><span class="line">git revert --no-commit d91b077..4ad24e8</span><br><span class="line">git commit -m <span class="string">&quot;回滚 3 月 8 日的功能改动&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 推送，普通 push 即可，不需要 -f</span></span><br><span class="line">git push</span><br></pre></td></tr></table></figure><div class="note success flat"><p><strong>revert 是团队协作下的标准做法</strong>。它不改写历史，因此可以安全地在 main &#x2F; master 上使用，也不需要强制推送。</p></div><h3 id="两个方案怎么选"><a href="#两个方案怎么选" class="headerlink" title="两个方案怎么选"></a>两个方案怎么选</h3><table><thead><tr><th>对比项</th><th><code>reset</code> + <code>push -f</code></th><th><code>revert</code> + <code>push</code></th></tr></thead><tbody><tr><td>是否改写历史</td><td>✅ 删掉提交记录</td><td>❌ 新增一次反向提交</td></tr><tr><td>需要强制推送</td><td>✅ 需要</td><td>❌ 不需要</td></tr><tr><td>影响他人</td><td>可能丢失他人提交</td><td>无影响</td></tr><tr><td>能否撤销回滚</td><td>需靠 reflog</td><td>再 revert 一次即可</td></tr><tr><td>适用场景</td><td>个人仓库、刚 push 的错误提交</td><td><strong>团队协作、公共分支</strong></td></tr></tbody></table><h2 id="六、撤销-merge-提交"><a href="#六、撤销-merge-提交" class="headerlink" title="六、撤销 merge 提交"></a>六、撤销 merge 提交</h2><p><code>revert</code> 一个 merge 提交时需要指定保留哪条主线：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git revert -m 1 &lt;merge-commit-hash&gt;</span><br></pre></td></tr></table></figure><p><code>-m 1</code> 表示保留<strong>第一个父提交</strong>（通常是合入时所在的分支，如 main）。用错会回滚到错误的分支状态，执行前用 <code>git log --graph --oneline</code> 看清分叉结构。</p><h2 id="七、误操作恢复：reflog-救命"><a href="#七、误操作恢复：reflog-救命" class="headerlink" title="七、误操作恢复：reflog 救命"></a>七、误操作恢复：reflog 救命</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">$ git reflog</span><br><span class="line">8f3c1a2 HEAD@&#123;0&#125;: reset: moving to 8f3c1a2</span><br><span class="line">4ad24e8 HEAD@&#123;1&#125;: commit: 修复登录报错      ← 被 reset 掉的提交在这里</span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git reset --hard 4ad24e8      <span class="comment"># 回到误操作前的状态</span></span><br></pre></td></tr></table></figure><div class="note info flat"><p>reflog 默认保留 90 天（未被引用的提交 30 天后可能被 GC 清理）。所以要恢复就尽快，<strong>别拖</strong>。</p></div><h2 id="八、其它常见撤销场景"><a href="#八、其它常见撤销场景" class="headerlink" title="八、其它常见撤销场景"></a>八、其它常见撤销场景</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 只撤销某一个文件到指定版本（不影响其它文件）</span></span><br><span class="line">git checkout 8f3c1a2 -- src/main.js</span><br><span class="line"><span class="comment"># 新版 Git 推荐写法</span></span><br><span class="line">git restore --<span class="built_in">source</span>=8f3c1a2 -- src/main.js</span><br><span class="line"></span><br><span class="line"><span class="comment"># 撤销工作区未 add 的修改（危险，改动会丢失）</span></span><br><span class="line">git checkout -- src/main.js</span><br><span class="line">git restore src/main.js</span><br><span class="line"></span><br><span class="line"><span class="comment"># 撤销已 add 但未 commit（把文件从暂存区移回工作区）</span></span><br><span class="line">git restore --staged src/main.js</span><br><span class="line"></span><br><span class="line"><span class="comment"># 修改上一次的提交信息（还没 push 时）</span></span><br><span class="line">git commit --amend -m <span class="string">&quot;新的提交信息&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 临时保管改动，之后再取回</span></span><br><span class="line">git stash            <span class="comment"># 存起来</span></span><br><span class="line">git stash pop        <span class="comment"># 取回来</span></span><br></pre></td></tr></table></figure><h2 id="九、删除中间某次提交（交互式-rebase）"><a href="#九、删除中间某次提交（交互式-rebase）" class="headerlink" title="九、删除中间某次提交（交互式 rebase）"></a>九、删除中间某次提交（交互式 rebase）</h2><p>想「去掉」历史上某一次提交（而不是反向抵消），用交互式 rebase：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git rebase -i 8f3c1a2        <span class="comment"># 对 8f3c1a2 之后的所有提交做整理</span></span><br></pre></td></tr></table></figure><p>编辑器里把目标行前的 <code>pick</code> 改成：</p><table><thead><tr><th>指令</th><th>作用</th></tr></thead><tbody><tr><td><code>pick</code></td><td>保留这次提交</td></tr><tr><td><code>drop</code>（或 <code>d</code>）</td><td>删除这次提交</td></tr><tr><td><code>squash</code>（或 <code>s</code>）</td><td>合并到上一次提交</td></tr><tr><td><code>reword</code>（或 <code>r</code>）</td><td>只改提交信息</td></tr><tr><td><code>edit</code>（或 <code>e</code>）</td><td>停下来修改这次提交</td></tr></tbody></table><div class="note danger flat"><p>rebase 同样<strong>改写历史</strong>，已推送的分支用完后必须 <code>push -f</code>，风险和第五节方案 A 一样。公共分支请改用 <code>revert</code>。</p></div><h2 id="十、GitHub-网页端回滚"><a href="#十、GitHub-网页端回滚" class="headerlink" title="十、GitHub 网页端回滚"></a>十、GitHub 网页端回滚</h2><p>不想敲命令的话，GitHub 也提供了图形化入口：</p><ol><li>进入仓库 → 点击 <strong>Commits</strong> 查看提交历史</li><li>点开要撤销的那次提交，右上角点 <strong>Revert</strong></li><li>GitHub 会自动创建一个 revert 的 PR，确认合并即可</li></ol><p>这本质就是 <code>git revert</code>，安全且可追溯，适合不熟悉命令行的场景。</p><h2 id="十一、安全准则"><a href="#十一、安全准则" class="headerlink" title="十一、安全准则"></a>十一、安全准则</h2><div class="note success flat"><ol><li><strong>回滚前先备份</strong>：<code>git branch backup-20240308</code> 建个分支，随时能回来</li><li><strong>公共分支只用 revert</strong>，不用 reset + push -f</li><li><strong>强制推送一律用 <code>--force-with-lease</code></strong> 代替 <code>-f</code></li><li>用 <code>--hard</code> 前先 <code>git stash</code> 或确认工作区干净</li><li>重要分支在 GitHub 上开启 <strong>branch protection</strong>，禁止强制推送</li></ol></div><hr><div class="note info flat"><p><strong>一句话记忆</strong>：自己的分支、刚提交的错 → <code>reset --hard</code>；别人也在用的分支 → <code>revert</code>。拿不准就用 revert，它永远安全。</p></div>]]></content>
    
    
    <summary type="html">记录 GitHub 仓库回滚的几种实用方法，包括使用 git revert、git reset 以及通过 GitHub 网页端直接回滚提交的操作步骤与注意事项。</summary>
    
    
    
    <category term="工具效率" scheme="https://www.amoit.top/categories/%E5%B7%A5%E5%85%B7%E6%95%88%E7%8E%87/"/>
    
    
    <category term="Git" scheme="https://www.amoit.top/tags/Git/"/>
    
    <category term="GitHub" scheme="https://www.amoit.top/tags/GitHub/"/>
    
    <category term="版本管理" scheme="https://www.amoit.top/tags/%E7%89%88%E6%9C%AC%E7%AE%A1%E7%90%86/"/>
    
  </entry>
  
  <entry>
    <title>Mac 下 Matplotlib 中文显示问题</title>
    <link href="https://www.amoit.top/posts/matplotlib-chinese-mac/"/>
    <id>https://www.amoit.top/posts/matplotlib-chinese-mac/</id>
    <published>2023-03-08T10:16:27.000Z</published>
    <updated>2026-10-06T12:33:24.652Z</updated>
    
    <content type="html"><![CDATA[<h1 id="Matplotlib输出中文显示问题-mac"><a href="#Matplotlib输出中文显示问题-mac" class="headerlink" title="Matplotlib输出中文显示问题 (mac)"></a>Matplotlib输出中文显示问题 (mac)</h1><p>声明：这是对别人经验的总结</p><h2 id="问题描述"><a href="#问题描述" class="headerlink" title="问题描述"></a>问题描述</h2><p>matplotlib绘制图像的时候显示中文时候，中文会变成小方格子。</p><h2 id="解决办法"><a href="#解决办法" class="headerlink" title="解决办法"></a>解决办法</h2><h3 id="方法一：修改配置文件matplotlibrc"><a href="#方法一：修改配置文件matplotlibrc" class="headerlink" title="方法一：修改配置文件matplotlibrc"></a>方法一：修改配置文件matplotlibrc</h3><p>在matplotlib的安装路径：Python36\site-packages\matplotlib\mpl-data\matplotlibrc，文件中有如下内容：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">font.family    : sans-serif</span><br><span class="line">font.sans-serif   : Bitstream Vera Sans, Lucida Grande, Verdana, Geneva, Lucid, Anal, Helvetica, Avant Ga </span><br></pre></td></tr></table></figure><h3 id="方法二：动态设置参数（推荐方式）"><a href="#方法二：动态设置参数（推荐方式）" class="headerlink" title="方法二：动态设置参数（推荐方式）"></a>方法二：动态设置参数（推荐方式）</h3><h4 id="1"><a href="#1" class="headerlink" title="(1)"></a>(1)</h4><p>在python脚本中动态设置matplotlibrc，这样就避免了更改配置文件的麻烦，方便灵活，例如:</p><p>from pylab import mpl<br>mpl.rcParams[‘font.sans-serif] &#x3D; [‘SimHei’]</p><p>由于更改了字体导致显示不出负号，将配署文件中axes.unicode minus : True修改为Falsest就可以了，当然这而可以用代码来完成。</p><p>from pylab import mpl</p><p>mpl.rcParams[‘font.sans-serif’] &#x3D; [‘FangSong’] # 指定默认字体<br>mpl.rcParams[‘axes.unicode_minus’] &#x3D; False # 解决保存图像是负号’-‘显示为方块的问题</p><h4 id="2"><a href="#2" class="headerlink" title="(2)"></a>(2)</h4><p>plt.rcParams[‘font.sans-serif’] &#x3D; [‘Arial Unicode MS’]<br>方法三：使用字体管理器<br>python有个字体管理器，font_manager</p><p>myfont &#x3D; matplotlib.font_manager.FontProperties(fname&#x3D;’C:&#x2F;Windows&#x2F;Fonts&#x2F;msyh.ttf’)<br>mpl.rcParams[‘axes.unicode_minus’] &#x3D; False  </p><h3 id="字体对应名称"><a href="#字体对应名称" class="headerlink" title="字体对应名称:"></a>字体对应名称:</h3><p>黑体SimHei<br>微软雅黑Microsoft YaHei<br>微软正黑体Microsoft JhengHei<br>新宋体NSimSun<br>新细明体PMingLiU<br>细明体MingLiU<br>标楷体DFKai-SB<br>仿宋FangSong<br>楷体KaiTi<br>仿宋_GB2312FangSong_GB2312<br>楷体_GB2312KaiTi_GB2312</p><p>宋体：SimSuncss中中文字体（font-family）的英文名称</p><p>Mac OS的一些：</p><p>华文细黑：STHeiti Light [STXihei]</p><p>华文黑体：STHeiti</p><p>华文楷体：STKaiti</p><p>华文宋体：STSong</p><p>华文仿宋：STFangsong</p><p>儷黑 Pro：LiHei Pro Medium</p><p>儷宋 Pro：LiSong Pro Light</p><p>標楷體：BiauKai</p><p>蘋果儷中黑：Apple LiGothic Medium</p><p>蘋果儷細宋：Apple LiSung Light</p><p>Windows的一些：</p><p>新細明體：PMingLiU</p><p>細明體：MingLiU</p><p>標楷體：DFKai-SB</p><p>黑体：SimHei</p><p>新宋体：NSimSun</p><p>仿宋：FangSong</p><p>楷体：KaiTi</p><p>仿宋_GB2312：FangSong_GB2312</p><p>楷体_GB2312：KaiTi_GB2312</p><p>微軟正黑體：Microsoft JhengHei</p><p>微软雅黑体：Microsoft YaHei</p><p>装Office会生出来的一些：</p><p>隶书：LiSu</p><p>幼圆：YouYuan</p><p>华文细黑：STXihei</p><p>华文楷体：STKaiti</p><p>华文宋体：STSong</p><p>华文中宋：STZhongsong</p><p>华文仿宋：STFangsong</p><p>方正舒体：FZShuTi</p><p>方正姚体：FZYaoti</p><p>华文彩云：STCaiyun</p><p>华文琥珀：STHupo</p><p>华文隶书：STLiti</p><p>华文行楷：STXingkai</p><p>华文新魏：STXinwei</p>]]></content>
    
    
    <summary type="html">解决 Mac 环境下 Matplotlib 绘图中文显示为方框的问题，包含字体查找、缓存清理与 rcParams 配置方法。</summary>
    
    
    
    <category term="环境配置" scheme="https://www.amoit.top/categories/%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE/"/>
    
    
    <category term="Python" scheme="https://www.amoit.top/tags/Python/"/>
    
    <category term="Matplotlib" scheme="https://www.amoit.top/tags/Matplotlib/"/>
    
    <category term="macOS" scheme="https://www.amoit.top/tags/macOS/"/>
    
  </entry>
  
  <entry>
    <title>蓝桥杯 Python 组准备</title>
    <link href="https://www.amoit.top/posts/lanqiao-cup-python-prep/"/>
    <id>https://www.amoit.top/posts/lanqiao-cup-python-prep/</id>
    <published>2023-03-07T09:57:27.000Z</published>
    <updated>2026-10-06T12:33:25.003Z</updated>
    
    <content type="html"><![CDATA[<h1 id="蓝桥杯-python组"><a href="#蓝桥杯-python组" class="headerlink" title="蓝桥杯 python组"></a>蓝桥杯 python组</h1><h1 id="idle的使用快捷键"><a href="#idle的使用快捷键" class="headerlink" title="idle的使用快捷键"></a>idle的使用快捷键</h1><h1 id="python了解"><a href="#python了解" class="headerlink" title="python了解"></a>python了解</h1><h2 id="os常用方法"><a href="#os常用方法" class="headerlink" title="os常用方法"></a>os常用方法</h2><p>os.remove() 删除文件</p><p>os.rename() 重命名文件</p><p>os.walk() 生成目录树下的所有文件名</p><p>os.chdir() 改变目录</p><p>os.mkdir&#x2F;makedirs 创建目录&#x2F;多层目录</p><p>os.rmdir&#x2F;removedirs 删除目录&#x2F;多层目录</p><p>os.listdir() 列出指定目录的文件</p><p>os.getcwd() 取得当前工作目录</p><p>os.chmod() 改变目录权限</p><p>os.path.basename() 去掉目录路径，返回文件名</p><p>os.path.dirname() 去掉文件名，返回目录路径</p><p>os.path.join() 将分离的各部分组合成一个路径名</p><p>os.path.split() 返回( dirname(), basename())元组</p><p>os.path.splitext() 返回 (filename, extension) 元组</p><p>os.path.getatime\ctime\mtime 分别返回最近访问、创建、修改时间</p><p>os.path.getsize() 返回文件大小</p><p>os.path.exists() 是否存在</p><p>os.path.isabs() 是否为绝对路径</p><p>os.path.isdir() 是否为目录</p><p>os.path.isfile() 是否为文件 </p><h2 id="sys-常用方法"><a href="#sys-常用方法" class="headerlink" title="sys 常用方法"></a>sys 常用方法</h2><p>sys.argv 命令行参数List，第一个元素是程序本身路径</p><p>sys.modules.keys() 返回所有已经导入的模块列表</p><p>sys.exc_info() 获取当前正在处理的异常类,exc_type、exc_value、exc_traceback当前处理的异常详细信息</p><p>sys.exit(n) 退出程序，正常退出时exit(0)</p><p>sys.hexversion 获取Python解释程序的版本值，16进制格式如：0x020403F0</p><p>sys.version 获取Python解释程序的版本信息</p><p>sys.maxint 最大的Int值</p><p>sys.maxunicode 最大的Unicode值</p><p>sys.modules 返回系统导入的模块字段，key是模块名，value是模块</p><p>sys.path 返回模块的搜索路径，初始化时使用PYTHONPATH环境变量的值</p><p>sys.platform 返回操作系统平台名称</p><p>sys.stdout 标准输出</p><p>sys.stdin 标准输入</p><p>sys.stderr 错误输出</p><p>sys.exc_clear() 用来清除当前线程所出现的当前的或最近的错误信息</p><p>sys.exec_prefix 返回平台独立的python文件安装的位置</p><p>sys.byteorder 本地字节规则的指示器，big-endian平台的值是’big’,little-endian平台的值是’little’</p><p>sys.copyright 记录python版权相关的东西</p><p>sys.api_version 解释器的C的API版本</p>]]></content>
    
    
    <summary type="html">蓝桥杯 Python 程序设计比赛准备笔记，涵盖算法题型、练习平台与备赛时间安排。</summary>
    
    
    
    <category term="学海拾遗" scheme="https://www.amoit.top/categories/%E5%AD%A6%E6%B5%B7%E6%8B%BE%E9%81%97/"/>
    
    
    <category term="Python" scheme="https://www.amoit.top/tags/Python/"/>
    
    <category term="算法" scheme="https://www.amoit.top/tags/%E7%AE%97%E6%B3%95/"/>
    
    <category term="蓝桥杯" scheme="https://www.amoit.top/tags/%E8%93%9D%E6%A1%A5%E6%9D%AF/"/>
    
  </entry>
  
  <entry>
    <title>Hexo + Netlify + Twikoo 搭建个人博客</title>
    <link href="https://www.amoit.top/posts/hexo-netlify-twikoo-blog/"/>
    <id>https://www.amoit.top/posts/hexo-netlify-twikoo-blog/</id>
    <published>2023-01-13T09:57:27.000Z</published>
    <updated>2026-10-06T12:33:24.952Z</updated>
    
    <content type="html"><![CDATA[<h1 id="hexo-netilify-twikoo-建立个人博客-（mac）"><a href="#hexo-netilify-twikoo-建立个人博客-（mac）" class="headerlink" title="hexo+netilify+twikoo 建立个人博客 （mac）"></a>hexo+netilify+twikoo 建立个人博客 （mac）</h1><h2 id="参考博客："><a href="#参考博客：" class="headerlink" title="参考博客："></a>参考博客：</h2><pre><code>[小冰大佬的博客](https://zfe.space/)[安知鱼的博客](https://anzhiy.cn/)[爱铺bug的熊博客]( https://blog.cuijiacai.com/)</code></pre><h2 id="其他的资源"><a href="#其他的资源" class="headerlink" title="其他的资源"></a>其他的资源</h2><pre><code>//一些图标[阿里巴巴矢量库](https://www.iconfont.cn)//图片[vilipix](https://www.vilipix.com/)</code></pre><p>注意：一些地方需要到外网来搭建，建议先购买梯子</p><h1 id="使用的工具及系统环境以及花销"><a href="#使用的工具及系统环境以及花销" class="headerlink" title="使用的工具及系统环境以及花销:"></a>使用的工具及系统环境以及花销:</h1><pre><code>花销：19rmb博客框架是hexo，博客文件拖管于github，博客网站用netlify生成，国内访问采用vercel加速以及评论区制作系统环境是macOS，后续的教程都基于macOS的终端及其包管理软件homebrew进行域名是从阿里云购买的，9rmb/年图床使用的安知鱼的图床，懒得搭建了 10r/1Ghttps://image.anzhiy.cn/user/albums</code></pre><h1 id="hexo博客框架"><a href="#hexo博客框架" class="headerlink" title="hexo博客框架"></a>hexo博客框架</h1><h2 id="介绍"><a href="#介绍" class="headerlink" title="介绍"></a>介绍</h2><p>hexo是一个基于nodejs的静态博客网站生成器，作者是来自台湾的Tommy Chen<br>使用的one markdown进行日常的写博客，保存到_post文件下<br>（目前还需要新建 hexo n ‘博客主标题’）</p><h2 id="环境配置"><a href="#环境配置" class="headerlink" title="环境配置"></a>环境配置</h2><p>hexo是一个基于nodejs的静态博客网站生成器，作者是来自台湾的Tommy Chen</p><h3 id="homebrew-安装"><a href="#homebrew-安装" class="headerlink" title="homebrew 安装"></a>homebrew 安装</h3><h3 id="命令安装："><a href="#命令安装：" class="headerlink" title="命令安装："></a>命令安装：</h3><p><code>brew install node # homebrew安装nodejs</code></p><h3 id="确认环境配置信息"><a href="#确认环境配置信息" class="headerlink" title="确认环境配置信息"></a>确认环境配置信息</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">node -v # 查看node版本信息</span><br><span class="line">npm -v # 查看npm版本信息</span><br></pre></td></tr></table></figure><h3 id="npm默认的官网源可能会比较慢-需要设置成淘宝镜像"><a href="#npm默认的官网源可能会比较慢-需要设置成淘宝镜像" class="headerlink" title="npm默认的官网源可能会比较慢,需要设置成淘宝镜像"></a>npm默认的官网源可能会比较慢,需要设置成淘宝镜像</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">npm config get registry # 查看原来的源</span><br><span class="line">npm config set registry https://registry.npm.taobao.org # 修改为淘宝源</span><br><span class="line">npm config get registry # 查看现在的源</span><br></pre></td></tr></table></figure><h2 id="生成博客"><a href="#生成博客" class="headerlink" title="生成博客"></a>生成博客</h2><p><code>npm install hexo-cli -g # 全局安装hexo命令行工具</code><br>其中-g参数表示全局安装，没有这个参数就只在当前目录下安装，建议全局安装。</p><h2 id="初始化"><a href="#初始化" class="headerlink" title="初始化"></a>初始化</h2><h3 id="新建文件夹-“博客名字”"><a href="#新建文件夹-“博客名字”" class="headerlink" title="新建文件夹 “博客名字”"></a>新建文件夹 “博客名字”</h3><p><code>hexo init &quot;你的博客目录名称&quot; # 目录名称不含空格的时候双引号可以省略</code> </p><h3 id="进入博客目录："><a href="#进入博客目录：" class="headerlink" title="进入博客目录："></a>进入博客目录：</h3><p> (1)右键文件夹-&gt;服务-&gt;新建位于文件夹位置的终端窗口<br> (2)终端-&gt;<code>cd &quot;博客目录&quot;</code><br>（安装一些其他的插件: <code>npm install &quot;所要安装的插件名&quot;# 安装的依赖项在package.json文件的dependencies字段中可以看到</code>）</p><h3 id="博客项目目录结构介绍"><a href="#博客项目目录结构介绍" class="headerlink" title="博客项目目录结构介绍"></a>博客项目目录结构介绍</h3><h4 id="config-yml"><a href="#config-yml" class="headerlink" title="_config.yml"></a>_config.yml</h4><p>为全局配置文件，网站的很多信息都在这里配置，比如说网站名称，副标题，描述，作者，语言，主题等等。具体可以参考官方文档：<a href="https://hexo.io/zh-cn/docs/configuration.html%E3%80%82">https://hexo.io/zh-cn/docs/configuration.html。</a></p><h4 id="scaffolds"><a href="#scaffolds" class="headerlink" title="scaffolds"></a>scaffolds</h4><p>骨架文件，是生成新页面或者新博客的模版。可以根据需求编辑，当hexo生成新博客的时候，会用这里面的模版进行初始化。</p><h4 id="source"><a href="#source" class="headerlink" title="source"></a>source</h4><p>这个文件夹下面存放的是网站的markdown源文件，里面有一个_post文件夹，所有的.md博客文件都会存放在这个文件夹下。现在，你应该能看到里面有一个hello-world.md文件。</p><h4 id="themes"><a href="#themes" class="headerlink" title="themes"></a>themes</h4><p>网站主题目录，hexo有非常丰富的主题支持，主题目录会存放在这个目录下面。<br>我们后续会以默认主题来演示，更多的主题参见：<a href="https://hexo.io/themes/">https://hexo.io/themes/</a></p><h2 id="生成新文章"><a href="#生成新文章" class="headerlink" title="生成新文章"></a>生成新文章</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">hexo new post &quot;test&quot; # 会在 source/_posts/ 目录下生成文件 ‘test.md’，打开编辑</span><br><span class="line">hexo generate        # 生成静态HTML文件到 /public 文件夹中</span><br><span class="line">hexo server          # 本地运行server服务预览，打开 http://localhost:4000 即可预览你的博客</span><br></pre></td></tr></table></figure><p>快捷设置：<br>package.json中增加<br>“dev”: “hexo clean &amp;&amp; hexo g &amp;&amp; hexo s”</p><h3 id="主题以及hexo命令"><a href="#主题以及hexo命令" class="headerlink" title="主题以及hexo命令"></a>主题以及hexo命令</h3><p>更多的主题可以从官网下载。<br>更详细的hexo命令可以查看文档：<a href="https://hexo.io/zh-cn/docs/commands">https://hexo.io/zh-cn/docs/commands</a></p><h3 id="博客配置"><a href="#博客配置" class="headerlink" title="博客配置"></a>博客配置</h3><figure class="highlight plaintext"><figcaption><span>Site</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br></pre></td><td class="code"><pre><span class="line">title: Hexo  # 网站标题</span><br><span class="line">subtitle:    # 网站副标题</span><br><span class="line">description: # 网站描述</span><br><span class="line">author: John Doe  # 作者</span><br><span class="line">language:    # 语言</span><br><span class="line">timezone:    # 网站时区, Hexo默认使用您电脑的时区</span><br><span class="line"></span><br><span class="line"># URL</span><br><span class="line">## If your site is put in a subdirectory, set url as &#x27;http://yoursite.com/child&#x27;</span><br><span class="line">## and root as &#x27;/child/&#x27;</span><br><span class="line">url: http://yoursite.com   # 你的站点Url</span><br><span class="line">root: /                    # 站点的根目录</span><br><span class="line">permalink: :year/:month/:day/:title/   # 文章的 永久链接 格式   </span><br><span class="line">permalink_defaults:        # 永久链接中各部分的默认值</span><br><span class="line"></span><br><span class="line"># Directory   </span><br><span class="line">source_dir: source     # 资源文件夹，这个文件夹用来存放内容</span><br><span class="line">public_dir: public     # 公共文件夹，这个文件夹用于存放生成的站点文件。</span><br><span class="line">tag_dir: tags          # 标签文件夹     </span><br><span class="line">archive_dir: archives  # 归档文件夹</span><br><span class="line">category_dir: categories     # 分类文件夹</span><br><span class="line">code_dir: downloads/code     # Include code 文件夹</span><br><span class="line">i18n_dir: :lang              # 国际化（i18n）文件夹</span><br><span class="line">skip_render:                 # 跳过指定文件的渲染，您可使用 glob 表达式来匹配路径。    </span><br><span class="line"></span><br><span class="line"># Writing</span><br><span class="line">new_post_name: :title.md  # 新文章的文件名称</span><br><span class="line">default_layout: post      # 预设布局</span><br><span class="line">titlecase: false          # 把标题转换为 title case</span><br><span class="line">external_link: true       # 在新标签中打开链接</span><br><span class="line">filename_case: 0          # 把文件名称转换为 (1) 小写或 (2) 大写</span><br><span class="line">render_drafts: false      # 是否显示草稿</span><br><span class="line">post_asset_folder: false  # 是否启动 Asset 文件夹</span><br><span class="line">relative_link: false      # 把链接改为与根目录的相对位址    </span><br><span class="line">future: true              # 显示未来的文章</span><br><span class="line">highlight:                # 内容中代码块的设置    </span><br><span class="line">  enable: true            # 开启代码块高亮</span><br><span class="line">  line_number: true       # 显示行数</span><br><span class="line">  auto_detect: false      # 如果未指定语言，则启用自动检测</span><br><span class="line">  tab_replace:            # 用 n 个空格替换 tabs；如果值为空，则不会替换 tabs</span><br><span class="line"></span><br><span class="line"># Category &amp; Tag</span><br><span class="line">default_category: uncategorized</span><br><span class="line">category_map:       # 分类别名</span><br><span class="line">tag_map:            # 标签别名</span><br><span class="line"></span><br><span class="line"># Date / Time format</span><br><span class="line">## Hexo uses Moment.js to parse and display date</span><br><span class="line">## You can customize the date format as defined in</span><br><span class="line">## http://momentjs.com/docs/#/displaying/format/</span><br><span class="line">date_format: YYYY-MM-DD     # 日期格式</span><br><span class="line">time_format: HH:mm:ss       # 时间格式    </span><br><span class="line"></span><br><span class="line"># Pagination</span><br><span class="line">## Set per_page to 0 to disable pagination</span><br><span class="line">per_page: 10           # 分页数量</span><br><span class="line">pagination_dir: page   # 分页目录</span><br><span class="line"></span><br><span class="line"># Extensions</span><br><span class="line">## Plugins: https://hexo.io/plugins/</span><br><span class="line">## Themes: https://hexo.io/themes/</span><br><span class="line">theme: landscape   # 主题名称</span><br><span class="line"></span><br><span class="line"># Deployment</span><br><span class="line">## Docs: https://hexo.io/docs/deployment.html</span><br><span class="line">#  部署部分的设置</span><br><span class="line">deploy:     </span><br><span class="line">  type: &#x27;&#x27; # 类型，常用的git </span><br></pre></td></tr></table></figure><h1 id="Github项目文件托管"><a href="#Github项目文件托管" class="headerlink" title="Github项目文件托管"></a>Github项目文件托管</h1><h2 id="小白须知：这一步需要进入外网，需要梯子，加速器等"><a href="#小白须知：这一步需要进入外网，需要梯子，加速器等" class="headerlink" title="小白须知：这一步需要进入外网，需要梯子，加速器等"></a>小白须知：这一步需要进入外网，需要梯子，加速器等</h2><h2 id="git-是在本地进行安装的"><a href="#git-是在本地进行安装的" class="headerlink" title="git 是在本地进行安装的"></a>git 是在本地进行安装的</h2><h2 id="创建本地仓库，然后推送到远端服务器："><a href="#创建本地仓库，然后推送到远端服务器：" class="headerlink" title="创建本地仓库，然后推送到远端服务器："></a>创建本地仓库，然后推送到远端服务器：</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">cd &quot;博客目录&quot;</span><br><span class="line">git init</span><br><span class="line">git add .</span><br><span class="line">git commit -m &quot;提交信息&quot;</span><br><span class="line">git remote add origin &quot;远端github仓库地址&quot;</span><br><span class="line">git branch -M main</span><br><span class="line">git push -u origin main</span><br></pre></td></tr></table></figure><h1 id="ClouldFlare加速-or-vercel加速"><a href="#ClouldFlare加速-or-vercel加速" class="headerlink" title="ClouldFlare加速 or vercel加速"></a>ClouldFlare加速 or vercel加速</h1><h1 id="twikoo评论系统"><a href="#twikoo评论系统" class="headerlink" title="twikoo评论系统"></a>twikoo评论系统</h1><h1 id="一些出现的错误"><a href="#一些出现的错误" class="headerlink" title="一些出现的错误"></a>一些出现的错误</h1><h2 id="Nelify-部署异常"><a href="#Nelify-部署异常" class="headerlink" title="Nelify 部署异常"></a>Nelify 部署异常</h2><h2 id="添加github贡献图"><a href="#添加github贡献图" class="headerlink" title="添加github贡献图"></a>添加github贡献图</h2><h2 id="评论区错误"><a href="#评论区错误" class="headerlink" title="评论区错误"></a>评论区错误</h2>]]></content>
    
    
    <summary type="html">使用 Hexo、Netlify 与 Twikoo 搭建免费个人博客的完整流程，含部署、评论系统与自定义域名配置。</summary>
    
    
    
    <category term="博客搭建" scheme="https://www.amoit.top/categories/%E5%8D%9A%E5%AE%A2%E6%90%AD%E5%BB%BA/"/>
    
    
    <category term="Hexo" scheme="https://www.amoit.top/tags/Hexo/"/>
    
    <category term="Netlify" scheme="https://www.amoit.top/tags/Netlify/"/>
    
    <category term="Twikoo" scheme="https://www.amoit.top/tags/Twikoo/"/>
    
  </entry>
  
  <entry>
    <title>Hexo 写作速查手册</title>
    <link href="https://www.amoit.top/posts/test-post/"/>
    <id>https://www.amoit.top/posts/test-post/</id>
    <published>2023-01-10T11:37:01.000Z</published>
    <updated>2026-10-06T14:58:34.104Z</updated>
    
    <content type="html"><![CDATA[<div class="note info flat"><p>写博客时最烦的不是内容，而是「那个字段名叫什么来着」「标签外挂怎么写的」。这篇把常用语法、Front-matter 字段和命令整理成一页速查表，写文章时打开复制即可。</p></div><h2 id="一、写文章的完整流程"><a href="#一、写文章的完整流程" class="headerlink" title="一、写文章的完整流程"></a>一、写文章的完整流程</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">npx hexo new <span class="string">&quot;文章标题&quot;</span>        <span class="comment"># 新建文章 → source/_posts/文章标题.md</span></span><br><span class="line"><span class="comment"># 编辑 Markdown 内容</span></span><br><span class="line">npx hexo server                <span class="comment"># 本地预览 http://localhost:4000，保存即刷新</span></span><br><span class="line">npx hexo clean &amp;&amp; npx hexo g &amp;&amp; npx hexo d    <span class="comment"># 生成并部署</span></span><br></pre></td></tr></table></figure><p>想先写不发布：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">npx hexo new draft <span class="string">&quot;草稿标题&quot;</span>  <span class="comment"># 到 source/_drafts/</span></span><br><span class="line">npx hexo server --draft        <span class="comment"># 预览草稿</span></span><br><span class="line">npx hexo publish <span class="string">&quot;草稿标题&quot;</span>    <span class="comment"># 正式发布</span></span><br></pre></td></tr></table></figure><h2 id="二、Front-matter-字段速查"><a href="#二、Front-matter-字段速查" class="headerlink" title="二、Front-matter 字段速查"></a>二、Front-matter 字段速查</h2><p>文件顶部 <code>---</code> 之间的是 Front-matter，决定文章的元信息。</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">---</span></span><br><span class="line"><span class="attr">title:</span> <span class="string">文章标题</span></span><br><span class="line"><span class="attr">date:</span> <span class="number">2024-01-05 16:09:01</span>     <span class="comment"># 发布时间</span></span><br><span class="line"><span class="attr">updated:</span> <span class="number">2024-02-01 10:00:00</span>  <span class="comment"># 更新时间（可省略）</span></span><br><span class="line"><span class="attr">categories:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">前端开发</span>                   <span class="comment"># 只能有一个层级时写单个；支持多级</span></span><br><span class="line"><span class="attr">tags:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">React</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">前端</span></span><br><span class="line"><span class="attr">cover:</span> <span class="string">/img/cover.jpg</span>          <span class="comment"># 封面图</span></span><br><span class="line"><span class="attr">description:</span> <span class="string">一句话摘要</span>         <span class="comment"># SEO 与列表页显示，很重要</span></span><br><span class="line"><span class="attr">slug:</span> <span class="string">react-study-notes</span>        <span class="comment"># 自定义 URL 片段</span></span><br><span class="line"><span class="attr">abbrlink:</span> <span class="string">7b2d9f36</span>             <span class="comment"># 短链接（需 hexo-abbrlink）</span></span><br><span class="line"><span class="attr">sticky:</span> <span class="number">1</span>                      <span class="comment"># 置顶，数字越大越靠前</span></span><br><span class="line"><span class="attr">swiper_index:</span> <span class="number">1</span>                <span class="comment"># 出现在首页轮播（需 butterfly-swiper）</span></span><br><span class="line"><span class="attr">comments:</span> <span class="literal">true</span>                 <span class="comment"># 单篇开关评论</span></span><br><span class="line"><span class="attr">toc:</span> <span class="literal">true</span>                      <span class="comment"># 显示目录</span></span><br><span class="line"><span class="attr">top_img:</span> <span class="literal">false</span>                 <span class="comment"># 关闭头图</span></span><br><span class="line"><span class="attr">keywords:</span> <span class="string">React,</span> <span class="string">Hooks</span>         <span class="comment"># 关键词（部分主题/SEO 插件用）</span></span><br><span class="line"><span class="meta">---</span></span><br></pre></td></tr></table></figure><div class="note warning flat"><p><code>categories</code> 与 <code>tags</code> 的写法区别：一篇文章通常只有<strong>一个分类</strong>，但可以有<strong>多个标签</strong>。Butterfly 里分类写多个会形成层级（父分类 → 子分类），不是并列关系。</p></div><h2 id="三、Markdown-语法速查"><a href="#三、Markdown-语法速查" class="headerlink" title="三、Markdown 语法速查"></a>三、Markdown 语法速查</h2><table><thead><tr><th>效果</th><th>语法</th></tr></thead><tbody><tr><td>标题</td><td><code># 一级</code> <code>## 二级</code> … <code>###### 六级</code></td></tr><tr><td>加粗 &#x2F; 斜体</td><td><code>**粗体**</code> &#x2F; <code>*斜体*</code></td></tr><tr><td>删除线</td><td><code>~~删除~~</code></td></tr><tr><td>行内代码</td><td><code>`code`</code></td></tr><tr><td>代码块</td><td>三个反引号 + 语言名（如 &#96;&#96;&#96;js）</td></tr><tr><td>链接</td><td><code>[文字](https://url)</code></td></tr><tr><td>图片</td><td><code>![说明](/img/a.png)</code></td></tr><tr><td>引用</td><td><code>&gt; 内容</code></td></tr><tr><td>无序列表</td><td><code>- 项</code></td></tr><tr><td>有序列表</td><td><code>1. 项</code></td></tr><tr><td>任务列表</td><td><code>- [x] 已完成</code> &#x2F; <code>- [ ] 未完成</code></td></tr><tr><td>表格</td><td>&#96;</td></tr><tr><td>分割线</td><td><code>---</code></td></tr><tr><td>脚注</td><td><code>正文[^1]</code> + <code>[^1]: 注释内容</code></td></tr><tr><td>转义</td><td><code>\#</code> 输出 # 而不是标题</td></tr></tbody></table><p>代码块示例（<strong>务必标注语言</strong>，才有语法高亮）：</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="code">```js</span></span><br><span class="line"><span class="code">const a = 1</span></span><br><span class="line"><span class="code">```</span></span><br></pre></td></tr></table></figure><h2 id="四、Butterfly-专属标签外挂"><a href="#四、Butterfly-专属标签外挂" class="headerlink" title="四、Butterfly 专属标签外挂"></a>四、Butterfly 专属标签外挂</h2><p>这是 Butterfly 比普通 Markdown 好看的关键，写在正文里即可。</p><h3 id="提示框-note"><a href="#提示框-note" class="headerlink" title="提示框 note"></a>提示框 note</h3><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&#123;% note info %&#125;普通提示&#123;% endnote %&#125;</span><br><span class="line">&#123;% note success %&#125;成功 / 推荐做法&#123;% endnote %&#125;</span><br><span class="line">&#123;% note warning %&#125;注意事项&#123;% endnote %&#125;</span><br><span class="line">&#123;% note danger %&#125;危险操作警告&#123;% endnote %&#125;</span><br></pre></td></tr></table></figure><p>样式（可选，加在类型后面）：<code>simple</code> &#x2F; <code>modern</code> &#x2F; <code>flat</code> &#x2F; <code>disabled</code>，还可加图标：</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&#123;% note success flat %&#125;</span><br><span class="line">支持多行内容与 <span class="strong">**Markdown**</span> 语法</span><br><span class="line">&#123;% endnote %&#125;</span><br></pre></td></tr></table></figure><h3 id="折叠块-hide"><a href="#折叠块-hide" class="headerlink" title="折叠块 hide"></a>折叠块 hide</h3><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&#123;% hideInline 被隐藏的内容, 点击显示 %&#125;</span><br><span class="line">&#123;% hideBlock 折叠标题 %&#125;</span><br><span class="line">里面可以是任意 Markdown</span><br><span class="line">&#123;% endhideBlock %&#125;</span><br></pre></td></tr></table></figure><h3 id="标签页-tabs"><a href="#标签页-tabs" class="headerlink" title="标签页 tabs"></a>标签页 tabs</h3><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">&#123;% tabs 标签组名 %&#125;</span><br><span class="line">&lt;!-- tab macOS@fab fa-apple --&gt;</span><br><span class="line">内容一</span><br><span class="line">&lt;!-- endtab --&gt;</span><br><span class="line">&lt;!-- tab Windows@fab fa-windows --&gt;</span><br><span class="line">内容二</span><br><span class="line">&lt;!-- endtab --&gt;</span><br><span class="line">&#123;% endtabs %&#125;</span><br></pre></td></tr></table></figure><p>第二个参数是默认激活第几个（从 0 开始）。</p><h3 id="彩色标签-label"><a href="#彩色标签-label" class="headerlink" title="彩色标签 label"></a>彩色标签 label</h3><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&#123;% label 文字 default %&#125;   &#123;% label 蓝色 blue %&#125;</span><br><span class="line">&#123;% label 粉色 pink %&#125;       &#123;% label 红色 red %&#125;</span><br><span class="line">&#123;% label 紫色 purple %&#125;     &#123;% label 橙色 orange %&#125;</span><br><span class="line">&#123;% label 绿色 green %&#125;</span><br></pre></td></tr></table></figure><h3 id="按钮-btn"><a href="#按钮-btn" class="headerlink" title="按钮 btn"></a>按钮 btn</h3><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% btn https://example.com, 按钮文字, fas fa-download, outline orange center %&#125;</span><br></pre></td></tr></table></figure><p>参数依次是：链接、文字、图标、样式（颜色 + <code>outline</code> &#x2F; <code>center</code> &#x2F; <code>block</code> &#x2F; <code>larger</code>）。</p><h3 id="时间线-timeline"><a href="#时间线-timeline" class="headerlink" title="时间线 timeline"></a>时间线 timeline</h3><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">&#123;% timeline 标题 %&#125;</span><br><span class="line">&lt;!-- timeline 2024-01-01 --&gt;</span><br><span class="line">第一件事</span><br><span class="line">&lt;!-- endtimeline --&gt;</span><br><span class="line">&lt;!-- timeline 2024-06-01 --&gt;</span><br><span class="line">第二件事</span><br><span class="line">&lt;!-- endtimeline --&gt;</span><br><span class="line">&#123;% endtimeline %&#125;</span><br></pre></td></tr></table></figure><h3 id="其它"><a href="#其它" class="headerlink" title="其它"></a>其它</h3><ul><li><code>&#123;% mermaid %&#125;...&#123;% endmermaid %&#125;</code> —— 流程图 &#x2F; 时序图（需在主题配置里启用 mermaid）</li><li><code>&#123;% gallery %&#125;</code> —— 图片画廊</li><li><code>&#123;% flink %&#125;</code> —— 友情链接卡片</li></ul><h2 id="五、图片怎么插"><a href="#五、图片怎么插" class="headerlink" title="五、图片怎么插"></a>五、图片怎么插</h2><table><thead><tr><th>方式</th><th>写法</th><th>适用</th></tr></thead><tbody><tr><td>本地相对路径</td><td><code>![](/img/a.png)</code></td><td>放 <code>source/img/</code>，最稳</td></tr><tr><td>文章同目录</td><td><code>![](a.png)</code></td><td>需开启 <code>post_asset_folder</code></td></tr><tr><td>图床</td><td><code>![](https://cdn.../a.png)</code></td><td>推荐，本站用的 PicGo + GitHub</td></tr></tbody></table><div class="note info flat"><p>用图床时建议顺手压缩：照片转 WebP、图标用 SVG。一张 1MB 的图会让首屏明显变慢。</p></div><h2 id="六、命令速查"><a href="#六、命令速查" class="headerlink" title="六、命令速查"></a>六、命令速查</h2><table><thead><tr><th>命令</th><th>作用</th></tr></thead><tbody><tr><td><code>hexo new &quot;标题&quot;</code></td><td>新建文章</td></tr><tr><td><code>hexo new page &quot;xxx&quot;</code></td><td>新建页面（tags &#x2F; categories &#x2F; about）</td></tr><tr><td><code>hexo clean</code>（<code>hexo cl</code>）</td><td>清除缓存，<strong>改配置后必做</strong></td></tr><tr><td><code>hexo generate</code>（<code>hexo g</code>）</td><td>生成静态文件到 <code>public/</code></td></tr><tr><td><code>hexo server</code>（<code>hexo s</code>）</td><td>本地预览</td></tr><tr><td><code>hexo deploy</code>（<code>hexo d</code>）</td><td>部署</td></tr><tr><td><code>hexo g -d</code></td><td>生成并部署（合并两步）</td></tr><tr><td><code>hexo list</code></td><td>列出所有文章&#x2F;页面</td></tr><tr><td><code>hexo --draft</code></td><td>显示草稿</td></tr></tbody></table><h2 id="七、写作小建议"><a href="#七、写作小建议" class="headerlink" title="七、写作小建议"></a>七、写作小建议</h2><ol><li><strong><code>description</code> 一定写</strong> —— 它决定列表页摘要和搜索结果展示，比正文开头更重要</li><li><strong>配图统一比例</strong> —— 16:9 或 4:3 固定一种，翻页时不会有跳动感</li><li><strong>代码块标语言</strong> —— <code>js</code> &#x2F; <code>bash</code> &#x2F; <code>yaml</code> &#x2F; <code>python</code>，高亮后可读性差很多</li><li><strong>标题层级别跳级</strong> —— <code>##</code> 下面直接 <code>####</code> 会让目录结构乱掉</li><li><strong>长文加目录</strong> —— Butterfly 默认自动生成 <code>toc</code>，只需要保证标题层级规范</li><li><strong>发布前本地预览一遍</strong> —— 尤其改过 Front-matter 后，避免线上 404 或字段拼写错误</li></ol><hr><div class="note success flat"><p>速查表的价值在于「不用记」，需要时 <code>Ctrl + F</code> 一下就够。把它存进书签，写文章会顺手很多。</p></div>]]></content>
    
    
    <summary type="html">Hexo + Butterfly 写作速查手册，整理 Front-matter 字段、Markdown 语法、主题标签外挂与常用命令，写博客时随手查阅。</summary>
    
    
    
    <category term="博客搭建" scheme="https://www.amoit.top/categories/%E5%8D%9A%E5%AE%A2%E6%90%AD%E5%BB%BA/"/>
    
    
    <category term="Hexo" scheme="https://www.amoit.top/tags/Hexo/"/>
    
    <category term="Markdown" scheme="https://www.amoit.top/tags/Markdown/"/>
    
    <category term="速查手册" scheme="https://www.amoit.top/tags/%E9%80%9F%E6%9F%A5%E6%89%8B%E5%86%8C/"/>
    
  </entry>
  
</feed>
