先确认差异发生在哪一层:是数据不同、容器约束不同,还是组件被页面样式覆盖。验收样例要能复现这三种来源,而不是只截一张“正常页面”的图。可执行的做法是:为同一组件建立最小对照页,固定数据,只改变一个外部条件,记录它在每种条件下的实际渲染结果,再把结果转成可回归的检查项。
同一组件在列表页正常、在详情页错位,通常有两种解释。第一种是组件本身没有边界问题,只是被父容器宽度、栅格或页面级样式影响;第二种是组件内部对数据长度、空值或加载时序有隐含假设,换个页面就暴露。两种解释对应的修复位置完全不同,验收样例也必须不同。
判断第一种解释的证据是:把组件放进一个干净容器,给定相同宽度和相同数据,表现恢复正常;一旦放回原页面容器就复现。判断第二种解释的证据是:即使容器条件一致,只要数据从短文本换成超长文本、从有图换成无图,或从同步渲染换成异步返回,组件就出现高度跳动、截断或错位。
最小对照页只保留三部分:组件本身、一个可控容器、一组固定数据。先做基线页,容器宽度设为该组件最常出现的范围,数据用最短合法值和最长合法值各一份。再做变量页,每次只改一个条件,例如把容器从固定宽度改成百分比宽度,或把数据从同步改成延迟返回。
动作上,先复制组件调用代码到对照页,保持属性一致,再逐项改变外部条件。每改一项就记录:组件是否溢出、是否换行、是否出现滚动条、是否遮挡相邻元素、交互区域是否仍可点击。记录结果会直接决定下一步:如果只在某个容器条件下失败,修复应落在页面布局约束;如果只在某类数据下失败,修复应落在组件内部。
截图只能证明“当前这样”,不能证明“为什么这样”。能区分原因的证据至少包括:同一数据在两种容器下的渲染结果、同一容器下两组边界数据的渲染结果、以及组件外层是否被页面级选择器改写了盒模型或字号。检查时可以先在对照页里临时移除页面级样式,再逐条加回,观察哪一条加回后差异出现。
如果移除某条页面级样式后差异消失,说明问题来自样式覆盖,验收样例应固定该页面的样式加载顺序和选择器范围。如果移除后差异仍在,说明组件对数据或时序有隐含依赖,验收样例应固定数据形态和加载顺序。两种结论对应不同的回归重点,不能混在同一条检查项里。
验收样例建议包含四列:条件、操作、预期、失败时先查哪里。条件写容器宽度、数据长度、加载方式;操作写“在对照页加载组件并观察高度”;预期写“不溢出、不遮挡、交互区域可点击”;失败时先查哪里写“先查父容器样式,再查组件内部空值分支”。这样写的好处是,后续页面改版时能快速判断是页面问题还是组件问题。
假设一个短例子:某卡片组件在列表页显示正常,在详情页右侧栏出现文字截断。先建对照页,固定卡片数据为最长标题,容器分别设为列表页宽度和右侧栏宽度。若只有右侧栏宽度下截断,优先检查右侧栏是否设置了固定高度或溢出隐藏;若两种宽度都截断,优先检查卡片内部标题行数限制。这个判断会决定下一步是改页面容器还是改组件样式。
如果差异只在个别页面出现,且这些页面的容器约束是历史遗留,先修页面成本更低,但代价是组件仍带着隐含假设,换一个页面可能再次暴露。如果差异在多个页面重复出现,或组件将被复用到新页面,先修组件更稳,但代价是要回归所有已用页面,确认修复没有改变原有正常表现。
选择条件可以简化为:看差异是否由页面级样式触发,以及组件未来是否会被更多页面复用。前者为真且复用范围小,先修页面;后者为真或复用范围大,先修组件。无论选哪边,都要把这次对照页保留为回归样例,而不是修完就删。