返回文章
NO.
011
DATE
更新于 2026-07-20
READ
~4 min
KIND
案例
STATUS
原文

TAGS: 博客

一张真机截图引发的连锁修复

一张 iPhone 截图,一个下午,十几个提交:桌面目录、移动端胶囊、测试翻案、页脚重构一路连锁——修复的验收标准是驱动真实行为,不是代码看起来对。

一张 iPhone 截图,一个下午。截图里只有两处不对劲:文章底部的目录胶囊压住了页脚,页脚本身的信息层级乱成一团。但顺着这两个症状查下去,最后动了十几个提交——桌面目录、移动交互、测试套件、页脚,一路连锁。

这篇不是教程,是一次真实的排查记录。它想说的其实是一条纪律:修复的验收标准,是它有没有驱动真实行为改变,而不是代码看起来对不对。

截图里没有的三处桌面缺陷

先说反常的地方。截图是手机拍的,我却先去修了桌面。因为同一次"根治"提交号称修好了桌面目录的三个问题,我顺手在宽屏下复核,发现两处根本没生效。

桌面目录是一条 sticky 的侧栏(rail)。它该随滚动停在头部下方、超长时内部滚动。但它的滚动链断在了一个包装层上——flex 容器的 min-height: auto 让子项无法收缩,内部滚动永远不触发。号称修好的提交改了目录组件本身,却没碰这个包装层,所以"修复"在代码里存在、在页面上不存在。

教训第一次出现:声称修复 ≠ 验证修复。 一个 commit 说"三处根治",不等于三处真的生效。

那颗移动端胶囊:从边沿触发到状态机

回到截图里的正主。移动端阅读时,屏幕底部有一颗目录胶囊,滚到文章末尾(评论区/页脚)时它该让位。原实现用的是 IntersectionObserver 的"边沿触发"——元素进入视口的那一瞬间隐藏胶囊。问题是边沿触发是一次性的:一旦你在末尾区域内继续上下微调,那个"进入"事件不会再来,胶囊状态就卡住了,于是它压住了页脚。

修法是换一个问题来回答。原实现问的是"哪一瞬间该隐藏胶囊",答案绑在一个一次性事件上;新实现问的是"此刻读者在不在文章末尾区域",答案是一个随滚动持续更新的状态。

具体做法是维护一个布尔值 inEndZone(读者当前是否处于评论区/页脚这段末尾区域),胶囊的显示规则只剩一条:!inEndZone 时显示,inEndZone 时隐藏。观察器不再负责"做动作",只负责"报状态"——每当末尾区域与视口的相对位置变化,就重新给这个布尔赋值:

  • 末尾区域进入视口 → inEndZone = true,胶囊隐藏;
  • 末尾区域从视口上方离开(读者继续往下滚,人已经在它后面的页脚里)→ 仍是 true,继续隐藏;
  • 末尾区域从视口下方离开(读者往回滚,重新回到正文)→ false,胶囊重新出现。

对比一下就能看出差别:旧实现里"隐藏"只在"进入末尾"那一瞬间发生一次,读者在末尾附近来回滚动时,那个瞬间不会重演,胶囊就卡在错误状态里;新实现里任何时刻你去问"inEndZone 现在是什么",都能得到和读者实际位置一致的答案。行为从"某一刻做一次动作"变成"任何时刻状态都自洽"——这也是处理滚动、可见性这类连续交互的通用原则:用状态描述世界,而不是用事件驱动动作。

五个"环境问题"其实是真 bug

改完这两处,Playwright 套件里有五个测试是红的。它们此前被一份审计记成了"环境问题"——理由是"在主分支上也同样失败,与基线一致"。

这句"与基线一致"很危险。它让一个失实的定性存活了两天。真机截图翻了它的案:这五个失败是双层病因。一层是测试断言停在了旧行为——那次"根治"提交改了交互行为却没改对应的断言,于是断言还在验证一个已经不存在的旧行为;另一层是应用真有个末尾区域的 bug(就是上面那颗胶囊)。两层叠加,看起来像"环境不稳定",其实是两个真问题。

修完两层,套件从 4/9 诚实地转回 12/12 全绿。这里的纪律是:"和基线一样红"不是"没问题"的证据,它可能只是"基线本来就带病"。 绿,才重新是闸门。

页脚重构

最后才轮到截图最初的症状:页脚信息层级。原页脚把导航、版权、许可证、统计堆在一起,没有语义分组。重构成三块语义结构——来源优先的导航、版权/许可/隐私一行、colophon 一行——移动端按来源优先纵向堆叠,并在窄屏给固定的返顶按钮预留一条底部让位带,让它停靠时不再压住任何文字。

真正想说的

十几个提交,起点只是一张截图。但把它们串起来的不是某个具体的 CSS 或 observer,而是两条纪律:

  1. 验证驱动的修复。 桌面目录那两处"改了但没生效",和测试那五个"红了但被记成环境问题",是同一个病的两种表现——都把"代码看起来对"当成了"问题解决了"。修复的验收标准必须是驱动真实行为:目录真的在滚、胶囊真的让位、测试真的因为行为正确而变绿。

  2. 诚实记录,包括翻案。 那句"与基线一致、判为环境问题"如果一直留着,后续每一个接手的人都会在错误的基线上工作。翻案时我没有删掉原记录,而是加了一条带日期的更正——因为"我们曾经判断错、后来纠正了"这件事本身,就是这个博客最该留下的东西。

一张截图能引发多大的连锁,取决于你愿不愿意顺着第一个症状一直查到底,以及查到"其实之前判断错了"的时候,肯不肯把它写下来。

评论 →

CC BY-NC-SA 4.0

评论

评论由 GitHub Discussions 提供。登录 GitHub 后即可评论。 前往对应 Discussion