模板引擎必须在MVC初始化前通过app.RegisterView注册,否则ctx.View会panic;MVC不自带模板支持,需手动配置HTML/Jet等引擎并匹配路径后缀,传值仅能用ctx.ViewData,且View与JSON响应不可混用。

模板引擎必须在 MVC 初始化前注册,不能在 controller 里配
很多人以为 mvc.Application 自带模板支持,结果调用 ctx.View("index.html") 时直接 panic:template not found。Iris 的 MVC 层本身不绑定任何模板引擎——它只负责把 controller 方法映射成路由、把返回值转成响应,而模板渲染完全依赖底层 app 实例的配置。
正确顺序是:先用 app.RegisterView 配好引擎(比如 iris.HTML),再通过 mvc.New(app.Party(...)) 创建 MVC 实例。否则 ctx.View 会找不到渲染器。
-
app.RegisterView(iris.HTML("./templates", ".html").Layout("layouts/main.html"))是最常用写法,路径和后缀必须匹配实际文件结构 - 如果用了 Jet 模板,要额外
go get github.com/kataras/iris/v12/view/jet,然后用view.Jet替换HTML - 布局文件(
Layout)路径是相对于RegisterView第一个参数的,不是相对于项目根目录
controller 中传值只能靠 ctx.ViewData,别碰 ctx.Set 或全局变量
MVC controller 的 handler 方法(如 Get())里没有隐式传入 ctx,但 Iris 会自动注入 *context.Context 到方法签名或结构体字段。传值到模板的唯一合法方式是往 ctx.ViewData 写 map 键值对。
常见错误包括:ctx.Set("title", "首页") 不生效、在 controller struct 上定义 Title string 字段想自动绑定、或者用 app.OnAny 全局塞值——这些全无效。模板引擎只读 ctx.ViewData 这个请求级 map。
- 推荐写法:
c.Ctx.ViewData["Title"] = "首页"(假设 controller 有Ctx *context.Context字段) - 键名大小写敏感,模板里必须写
{{.Title}},不能写{{.title}} - struct 字段要传进模板,必须首字母大写,且需显式赋值:
c.Ctx.ViewData["User"] = user,其中user是User{Name string}类型
复用 layout 要手动调用 ctx.ViewLayout,且模板里必须用 {{template "content" .}}
Iris 不像某些框架默认包裹 layout。即使你 RegisterView 时设了 Layout("layouts/main.html"),它也只在你显式调用 ctx.ViewLayout 后才生效。而且 layout 文件里必须包含 {{template "content" .}} 才能插入实际页面内容。
容易漏掉的点:layout 文件名必须和 ViewLayout 参数一致;"content" 是硬编码字符串,不能改;. 表示当前传入的整个 ViewData map,所以子模板也能访问 {{.Title}}。
- 在 controller 里写:
c.Ctx.ViewLayout("layouts/main.html") - layout 文件中必须有:
{{define "content"}}{{end}}或更常见的{{template "content" .}} - 如果某个页面不想用 layout,就别调
ViewLayout,直接ctx.View("raw.html")
别在同一个 handler 里混用 ctx.View 和 ctx.JSON
这是 Iris 的硬性限制:一个请求响应体只能有一种类型。如果你在 Get() 方法里先写了 c.Ctx.View("index.html"),又写了 return mvc.Response{ContentType: "application/json"},后者会被忽略,前端收到的是 HTML 响应,但 Content-Type 可能还是 text/html——导致 JS 解析失败。
本质原因是 ctx.View 会立即写响应头和 body,后续任何输出都会被丢弃或触发 panic(取决于 debug 模式)。MVC 的 mvc.Result 返回值机制和原生 ctx 方法不可混用。
- 纯 API 接口:用
return mvc.Response{Code: 200, ContentType: "application/json", Text: "..."} - 页面渲染:只用
c.Ctx.ViewData+c.Ctx.View,不要 return 任何mvc.Result - 需要条件分支?提前判断,避免走到两种输出逻辑里
ViewData 的生命周期、layout 的触发时机、以及 View 和 JSON 的互斥性,这三处最容易反复踩坑。


















