兼容 fallback 会让内容重复渲染

**为旧模板保留的 fallback 路径,会让同一份内容在新模板里被渲染两次。** 症状是技能 / 总结 / 荣誉 / 作品集 / 自定义模块**重复显示**,而列表模块(工作 / 教育 / 项目 / 科研)正常 —— 差异不在数据,在模板有没有新槽。

机制

  • 新路径:section.body 直接取块状富文本(skills → content.skills,summary/awards/portfolio → 对应顶层字段)。
  • 旧路径:旧模板只有 section.items,为了让块状模块也能显示,deriveItems 把同一份富文本包成一个「假 item」塞进 item.bullets。

新模板同时写了 <slot data-bind="section.body"> 和 <slot data-bind="section.items" data-template="item">,两条路径各渲染一次 → 重复。

解法:在渲染器里记「本 section 是否已有新槽」

渲染时记录当前 section 模板是否含 section.body;若该 section 是 kind === "block" 且模板已有 section.body,就跳过 fallback 的假 item。

第二种来源:迁移脚本把「一行」替换成「一组」

模板批量迁移时,占位符被替换成「渲染全部 X」的循环,也会造成重复:旧模板本来有多行联系方式(电话 / 邮箱 / 地点 / 网站各一行),迁移时每一行都被换成 profile.contacts 循环,于是 4–5 行变成 4–5 组重复联系方式。

同一批迁移还会顺带造成另一种坏结果:把模板专属类换成通用类(.modern-contact-item → .contact-item),原 CSS 选择器不再命中,图标变大、挤成奇怪的两行 —— 「重复」和「样式丢失」可能出自同一次迁移,但根因不同,要分开定位。

判据:迁移脚本里凡是「把一个占位符替换成对集合的循环」,都要先确认原位置的语义是一行还是一组;是「一行」就不能换成循环。

可迁移的判断

  • 加兼容层时,要问「新路径和旧路径会不会同时命中同一份数据」,并给新路径一个已消费标记。
  • 列表模块不出问题不代表机制对 —— 只是因为它的 section.body 为空,两条路径天然互斥。只在块状数据上暴露的 bug,最容易被判成「个别模板的问题」。
  • 反过来也说明 section.body 不能随便往存量模板上加:曾经加它导致过块状模块双渲染。

相关