5.2 模板继承与布局


5.2 模板继承与布局

词汇表(5.1)解决「一行怎么写」,本节解决「页面怎么组织」:让全站共享一套骨架,页面只填自己的内容坑位。这是视图车间的结构课,也是本章收尾——读完这节,书店项目的列表页、详情页应当复用同一个 layout,模板重复行数趋近于零;下一站将离开视图,进入第 6 章的安检闸口。

布局的三种演进形态

骨架复用的方案按演进顺序有三代。第一代是每页完整 HTML:导航栏改一个菜单项,三十个页面改三十遍,漏一处就出现「精神分裂页面」。第二代是头尾 include:中间主体每页自己写,改动收敛到片段文件——但 <body> 标签被劈在两个片段里,每页仍要重复写 title、样式引入、脚本引入的整段头部。第三代是布局继承:母版持有完整 HTML 结构,把「每页不同的区域」挖成坑位,子模板按名填坑:

<!-- layout.html:全站唯一一份完整 HTML 骨架 --> <!DOCTYPE html> <html> <head> <title>{block name="title"}默认标题{/block} - 书店</title> {block name="css"}<link rel="stylesheet" href="/static/base.css">{/block} </head> <body> {include file="public/nav" /} <div class="container"> {block name="content"}{/block} </div> {include file="public/footer" /} {block name="js"}{/block} </body> </html>
<!-- book/list.html:子模板只写坑位 --> {extend name="layout" /} {block name="title"}图书列表{/block} {block name="css"} {__block__} <link rel="stylesheet" href="/static/book.css"> {/block} {block name="content"} {volist name="books" id="vo"} <div class="item">{$vo.title}</div> {/volist} {/block}

{extend} 声明继承关系后,子模板里只有 block 坑位生效,骨架之外的任何内容都会被忽略。{__block__} 是坑位继承语法:先保留母版默认内容再追加,上面例子的含义是「基础样式照旧,追加图书页专属样式」——没有它,每个子模板都得把母版的默认引入抄一遍,继承就退化成了复制。

一个重构现场:三份重复模板到零重复

背景:书店项目早期由两个人并行开发,列表页、详情页、用户中心各自复制了一份头部导航,某次改版要求导航新增「分类」入口。操作:先全局搜索 <nav 统计重复——三个文件、每份四十行、改动落点三处;随后建 layout 母版,把三份头部收敛为一份 {include file="public/nav" /},三个页面改为 {extend}{block name="content"};导航改动从此只落在 public/nav.html 一处。结果示例:三个页面合计删除约九十行重复 HTML,改版提交从一个跨文件的三处修改变成一行补丁。解读:这次重构真正省下的不是行数,而是「改版落点数」——落点数才是维护成本的度量单位;继承体系把落点从「每页一份」压到「母版一份」。变式:给详情页加一个侧栏坑位,验证坑位只影响声明它的页面;再把翻页条抽成片段,体验 includeblock 的分工——片段是「横向复用的小件」,坑位是「纵向继承的区域」,两者配合而非互斥。

母版设计的粒度取舍

layout 不是越细越好。母版只该挖「结构性差异」的坑位:标题、主体内容、页面级样式与脚本。把每个小区域都挖成坑位,子模板会退化为一堆碎片,读页面时要在多个文件间跳转才能拼出全貌。经验粒度是三层:全站母版(导航、页脚、公共资源)→ 分区母版(如后台的带侧栏布局,继承全站母版再加侧栏坑位)→ 页面模板(只填内容)。两层起步、三封顶;出现第四层继承时,先怀疑是不是把组件问题误当成了布局问题——按钮、卡片、表单控件属于组件,用片段或前端组件方案解决,不进继承链。模板缓存也值得一提:编译产物按模板文件粒度缓存在 runtime 目录,改模板后刷新即生效,生产环境无需手动清理;但部署脚本若整体覆盖模板目录,记得同步清缓存目录,避免新旧模板混编(第 8 章部署一节会回收这个点)。

动手练习:把书店三个页面收进一套继承体系

背景:练习项目的列表页、详情页、搜索结果页仍是三份完整 HTML。操作:抽取 layout 母版与导航页脚片段;三个页面改为继承写法;给详情页单独加 js 坑位引入放大图脚本;用浏览器的查看源码功能核对三页产物与重构前一致。结果示例:三页源码结构不变,模板侧净减约百行。解读:重构的安全绳是「产物等价」——改结构不改产物,任何渲染差异都说明坑位挖错了位置。变式:为后台再建一个继承全站母版的侧栏布局,体会三层粒度;统计你们项目里 <title> 出现的文件数,作为继承收益的直观指标。

💡 关键直觉:继承的本质是「把不变的东西钉死在一个文件里」。判断布局方案好不好,只看一个问题——下一次全站改版,你要动几个文件。答案大于一,就还有复用空间。

继承体系的排错小抄

继承写法的报错有固定几种长相,对应固定的查法。页面渲染出母版默认内容而不是子模板内容——先查 extend 标签是否在子模板首行,它前面连一个空行注释都不能有;坑位填了却出现在页面底部——查 block 的 name 拼写,对不上名的坑位内容会被丢弃或错位;样式「时灵时不灵」——查 css 坑位里有没有忘写 {block},母版的基础样式被子模板整块顶掉了。三张小抄覆盖日常九成的继承问题,排查思路都是「先看结构关系,再看内容本身」。

本节要点回顾

  • 三代方案演进:整页复制 → 头尾 include → extend 加 block 继承,维护落点逐代收敛。
  • {__block__} 是坑位继承:保留母版默认内容再追加,没有它继承会退化成复制。
  • 母版三层封顶:全站母版、分区母版、页面模板;组件别进继承链。
  • include 与 block 分工:片段复用小件,坑位继承区域,配合使用。
  • 重构安全绳:产物等价——结构重构不允许改变任何一页的渲染结果。

视图车间到此完工:数据经过 5.1 的记号与 5.2 的骨架,装配成响应原路出站。请求的下一站不再是渲染——第 6 章我们回到总线中段,看安检闸口如何验证输入、缓存热点并保管会话。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U