Revel 仅通过 app/views/_layout.html 中的 {{yield}} 实现单层布局复用,不支持继承、组件或嵌套布局;多布局需手动指定,{{yield}} 严格区分大小写且无参数,动态内容须经 RenderArgs 注入。

Revel 中复用页面布局靠的是 _layout.html 模板 + {{yield}},不是靠继承、组件或自定义标签——它不支持 Web Components,也不走 ASP.NET Core 那套 _ViewStart.cshtml 机制。
Revel 的布局文件必须叫 _layout.html,且只能放 app/views/ 根目录下
Revel 不识别 Shared/ 子目录,也不接受其他文件名(比如 layout.html 或 main_layout.html)。如果放错位置或改名,{{yield}} 会失效,所有视图都变成纯 HTML 片段,不套壳。
-
app/views/_layout.html是唯一被自动识别的布局模板 - 子目录里的同名文件(如
app/views/admin/_layout.html)会被忽略 - 多个布局?Revel 原生不支持。想实现“后台用一套、前台用另一套”,得手动在控制器里指定:
c.RenderArgs["layout"] = "admin_layout.html",再在Render前调用c.RenderTemplate("admin_layout.html")——但这已脱离自动布局机制,属于 hack
{{yield}} 是唯一内容注入点,不能写成 {{.yield}} 或 {{yield .}}
Revel 模板引擎对这个关键字大小写和语法极其敏感。写错就等于没声明占位,结果是布局 HTML 渲染了,但视图内容完全不出现,页面只剩页头页脚空壳。
- 正确写法只有:
{{yield}} - 错误示例:
{{.yield}}(加点报错)、{{yield .}}(参数传错)、{{YIELD}}(大小写敏感) - 它不接收参数,不支持条件判断包裹,也不能嵌套在
{{if}}里——否则yield逻辑会中断
全局变量要靠 RenderArgs 注入,不能依赖模板继承链
Revel 没有类似 Razor 的 @section 或 Vue 的 slot,所以页标题、CSS/JS 资源、meta 标签等动态内容,必须由控制器统一塞进 c.RenderArgs,再在 _layout.html 里显式引用。
- 控制器中:
c.RenderArgs["Title"] = "用户管理"、c.RenderArgs["Scripts"] = []string{"user.js"} - 布局中:
、{{.Title}} {{range .Scripts}}<script src="%7B%7B.%7D%7D"></script>{{end}} - 别试图在子视图里用
{{.Title = "xxx"}}修改——Go 模板是单向渲染,赋值无效 - 未初始化的 key(如
{{.Title}}但控制器没设)会输出空字符串,不会 panic,但容易漏掉关键信息
静态资源路径别硬编码,用 asset 函数或相对路径需注意开发/生产差异
Revel 默认不处理静态资源版本哈希或 CDN 路径替换。如果你在 _layout.html 里写 href="/css/app.css",上线后 CSS 更新,用户可能因缓存看不到新样式。
- 推荐做法:用 Revel 的
asset函数(需启用 asset pipeline),例如 - 若不用 asset pipeline,至少把路径写成相对
public/的,比如/css/app.css,并确保 Nginx/Apache 配置将/css/指向public/css/ - 绝对路径
http://cdn.example.com/css/app.css可行,但无法享受本地热重载;开发时建议用环境变量切换域名
最常被忽略的一点:Revel 的布局机制是“单层扁平”的,没有嵌套布局、没有 layout of layout。你不能让 _layout.html 自己再套一个 _base_layout.html。所有结构复用必须收束到一个文件里,靠 RenderArgs 和条件模板控制显示分支——这既是简单性的来源,也是复杂页面组织的瓶颈。











