iris 公共页面抽离必须用 tmpl 的 layout 功能,主 layout 用 {{ yield }},公共片段存为 partials 并通过 {{ template "name" . }} 调用;禁止手动拼接、partial 嵌套或三层以上 layout,csrf token 需 controller 显式传入。

公共页面抽离必须用 iris.Tmpl 的 layout 功能,不能靠手动拼接
Iris 没有类似 Yii 的 $this->beginContent() 或 Vue 的 <slot></slot> 语义化嵌套机制,它的 layout 是纯模板级替换:主 layout 文件里写 {{ yield }},子模板用 {{ template "name" . }} 引入,但「公共页面」本身不是 layout,而是可复用的 .html 片段。强行在 controller 里读文件拼 HTML 会丢失上下文绑定、中断中间件链、无法被 iris.Tmpl 的缓存和热重载识别。
实操建议:
- 所有公共结构(如头部导航、侧边栏、页脚)单独存为
views/partials/header.html、views/partials/sidebar.html,统一用{{ template "header" . }}调用 - 主 layout(如
views/layouts/main.html)只负责包裹骨架:{{ template "header" . }}<main>{{ yield }}</main>{{ template "footer" . }} - 禁止在 partial 里写
{{ yield }}或嵌套调用另一个template—— Iris 不支持 partial 嵌套渲染,会导致template lookup failed - 若需动态控制某 partial 是否显示(如登录后才显示用户菜单),在 controller 里传布尔字段:
c.View("user/dashboard.html", iris.Map{"showUserMenu": true}),partial 内用{{ if .showUserMenu }}...{{ end }}
iris.Tmpl 的 layout 嵌套只能靠多层 yield + 子 layout 实现
Iris 原生不支持「layout 套 layout」的递归解析,但可通过两层 yield 模拟:第一层是全局主 layout,第二层是业务域 layout(如 admin 区域专用 layout)。关键在于子 layout 文件本身也要声明为 layout,并在其中再次使用 {{ yield }}。
常见错误现象:template: "admin/layout.html" is not a layout,或页面只渲染出子 layout 内容、主 layout 完全不生效。
实操建议:
- 主 layout:
views/layouts/main.html含{{ yield }} - 子 layout:
views/layouts/admin.html内容为:{{ template "main" . }}{{ yield }}—— 注意它先引入了主 layout,再写{{ yield }} - controller 中指定:
c.View("admin/dashboard.html", iris.Map{}).Layout("admin"),此时 Iris 会先找admin.html,发现它调用了main,再套一层 - 子 layout 里不能漏掉
{{ yield }},否则最终视图内容不会注入;也不能把{{ template "main" . }}放在{{ yield }}后面,否则内容被截断
静态资源路径和 CSRF Token 在嵌套 layout 中容易失效
当多个 layout 层级叠加时,{{ urlpath "static/css/app.css" }} 这类函数调用仍正常,但 {{ .CSRF.Token }} 在子 layout 或 partial 中可能为空 —— 因为 Iris 的 context 传递是单向的,yield 渲染时不会自动继承父级 context 的字段,除非显式传参。
使用场景:表单页嵌套在 admin layout 下,提交时 400 错误提示 token missing。
实操建议:
- CSRF Token 必须在最外层 controller 中生成并透传:
c.View("form.html", iris.Map{"csrf_token": c.GetContext().GetCSRFToken()}) - 不要依赖
.CSRF.Token模板变量,它只在顶层 layout 可靠;所有需要 token 的地方(包括 partial 表单)都从.csrf_token字段取 - 静态资源路径推荐用绝对路径前缀:
/static/...,避免因 layout 嵌套导致相对路径解析错位;若必须用{{ urlpath }},确保它在最外层 layout 中调用,不要在 partial 里重复调用
嵌套层级超过两层就该警惕性能与维护成本
Iris 的模板引擎对深度嵌套没有硬性限制,但三层以上(main → admin → form → modal)会让调试变得困难:修改一个 header partial,要清空整个模板缓存才能生效;template lookup 错误堆栈不显示具体哪一层出问题;hot reload 有时只刷新最外层,内层变更不触发重编译。
真正容易被忽略的是:Iris 默认开启模板缓存,且缓存 key 仅基于文件路径,不包含 layout 链路。这意味着你改了 admin.html,但 main.html 缓存未失效,结果页面还是旧的。
实操建议:
- 开发期禁用缓存:
iris.New(iris.Configuration{DisableTemplateEngine: false}).Tmpl(...).Cache(false) - 嵌套 layout 最多两层:主 layout + 业务域 layout(admin / user / public),业务页面直接
View(...).Layout("admin"),不再加第三层 - 复杂页面用组件化思路替代嵌套:把「弹窗表单」「数据表格」「筛选栏」拆成独立 handler + AJAX 加载,而不是塞进 layout 嵌套链











