01
介绍
beego 的模板处理引擎采用的是 Go 内置的 html/template 包进行处理,而且 beego 的模板处理逻辑是采用了缓存编译方式,也就是所有的模板会在 beego 应用启动的时候全部编译然后缓存在 map 里面。
02
模板处理
模板目录
beego 的默认模板目录是 views,也可以通过 beego.ViewPath = "viewPath" 指定模板目录。beego 会自动解析并缓存模板目录中的所有模板文件。但是在开发模式下,每次修改模板文件都会重新解析,并且不做缓存。
自动渲染
beego 会在调用完相应 method 方法之后自动调用 Render 函数,不需要用户手动调用渲染输出模板。如果不需要模板输出,可以在配置文件中配置:
autorender=false
或在 main.go 文件中设置配置变量:
web.AutoRender = false
模板标签
beego 默认使用{{}}双大括号作为模板标签,但是可能会和某些模板引擎使用的标签冲突,beego 可以通过配置文件或者设置配置变量:
web.TemplateLeft="<<" web.TemplateRight=">>"
模板数据
模板数据是通过在 controller中 this.Data 获取的,Data 字段的类型是:
Data map[interface{}]interface{}
key 和 value 都是空接口类型的 map
模板名称
自动渲染模式中,如果没有在 controller 中没有设置任何的模板名称TplName,beego 会自动将 controller 名字,method 名字,和模板后缀拼接成一个字符串,作为模板名称。
c.TplName = strings.ToLower(c.controllerName) + "/" + strings.ToLower(c.actionName) + "." + c.TplExt
beego 默认支持两种模板文件的后缀名,分别是 tpl 和 html。如果你的模板文件的后缀名不是这两种,需要设置配置变量:
web.AddTemplateExt("模板文件的后缀名")
用户还可以在 controller 中指定模板名称,beego 会自动在 viewPath 目录中查找该模板文件,设置方式如下:
this.TplName = "admin/add.tpl"
Layout 设计
beego 支持 Layout 设计,可以通过如下设置:
this.Layout = "admin/layout.html" this.TplName = "admin/add.tpl"
在 layout.html 文件中,设置如下变量:
{{.LayoutContent}}
beego 就会首先解析 TplName 指定的文件,获取到内容后,赋值给 LayoutContent,最后渲染 layout.html 文件。
另外,还可以使用如下方式:
{{template "header.html" .}} Logic code {{template "footer.html" .}}
LayoutSection
根据惯例,js 文件放在 body 的末尾,css 文件放到 head 中,所以 layout.html 文件只有一个 LayoutContent 是不够用的。
所以,在 controller 中还有一个 LayoutSection 属性,可以给 Layout.html 设置多个 section,每个 section 都可以包含各自的子模板页面。
type BlogsController struct { web.Controller } func (this *BlogsController) Get() { this.Layout = "layout_blog.tpl" this.TplName = "blogs/index.tpl" this.LayoutSections = make(map[string]string) this.LayoutSections["HtmlHead"] = "blogs/html_head.tpl" this.LayoutSections["Scripts"] = "blogs/scripts.tpl" this.LayoutSections["Sidebar"] = "blogs/side_bar.tpl" }
renderform 使用
struct:
type User struct { Id int `form:"-"` Name interface{} `form:"username"` Age int `form:"age,text,年龄:"` Sex string Intro string `form:",textarea"` }
StructTag 的定义用的标签为 form,和 ParseForm 方法共用一个标签,标签后面有三个可选参数,用 , 分割。
第一个参数为表单中类型的 name 的值,如果为空,则以 struct field name 为值。
第二个参数为表单组件的类型,如果为空,则为 text。表单组件的标签默认为 struct field name 的值,否则为第三个值。
如果要忽略一个字段,有两种办法,一是:字段名小写开头,二是:form 标签的值设置为 -
如果 form 标签只有一个值,则为表单中类型 name 的值,除了最后一个值可以忽略外,其他位置的必须要有 ,号分割,如:form:",,姓名:"
现在的代码版本只能实现固定的格式,用 br 标签实现换行,无法实现 css 和 class 等代码的插入。所以,要实现 form 的高级排版,不能使用 renderform 的方法,而需要手动处理每一个字段。
controller:
func (this *AddController) Get() { this.Data["Form"] = &User{} this.TplName = "index.tpl" }
Form 的参数必须是一个 struct 的指针。
template:
<form action="" method="post"> {{.Form | renderform}} </form>
上面的代码生成的表单为:
Name: <input name="username" type="text" value="test"></br> 年龄:<input name="age" type="text" value="0"></br> Sex: <input name="Sex" type="text" value=""></br> Intro: <input name="Intro" type="textarea" value="">
03
模板语法
模板中支持的 go 语言符号
{{"string"}} // 一般 string {{`raw string`}} // 原始 string {{'c'}} // byte {{print nil}} // nil 也被支持
模板中的 pipeline
可以是上下文的变量输出,也可以是函数通过管道传递的返回值
{{. | FuncA | FuncB | FuncC}}
当 pipeline 的值 false 或 0,nil 的指针或 interface,长度为 0 的 array、slice、map、string,那么这个 pipeline 被认为是空。
if ... else ... end
{{if pipeline}}{{end}}
if 判断时,pipeline 为空时,相当于判断为 false
this.Data["IsLogin"] = true this.Data["IsHome"] = true this.Data["IsAbout"] = true
支持嵌套的循环
{{if .IsHome}} {{else}} {{if .IsAbout}}{{end}} {{end}}
也可以使用 else if
{{if .IsHome}} {{else if .IsAbout}} {{else}} {{end}}
range ... end
{{range pipeline}}{{.}}{{end}}
pipeline 支持的类型为 array,slice,map,channel
range 循环内部的「.」改变为以上类型的子元素
对应的值长度为 0 时,range 不会执行,「.」不会改变
pages := []struct { Num int }{{10}, {20}, {30}} this.Data["Total"] = 100 this.Data["Pages"] = pages
使用「.Num」输出子元素的 Num 属性,使用「$.」引用模板中的根级上下文
{{range .Pages}} {{.Num}} of {{$.Total}} {{end}}
使用创建的变量,在这里和 go 中的 range 用法相同
{{range $index, $elem := .Pages}} {{$index}} - {{$elem.Num}} - {{.Num}} of {{$.Total}} {{end}}
range 也支持 else
{{range .Pages}} {{else}} {{/* 当 .Pages 为空 或者 长度为 0 时会执行这里 */}} {{end}}
with ... end
{{with pipeline}}{{end}}
with 用于重定向 pipeline
{{with .Field.NestField.SubField}} {{.Var}} {{end}}
也可以对变量赋值操作
{{with $value := "My name is %s"}} {{printf . "slene"}} {{end}}
with 也支持 else
{{with pipeline}} {{else}} {{/* 当 pipeline 为空时会执行这里 */}} {{end}}
define
define 可以用来定义自模板,可用于模块定义和模板嵌套
{{define "loop"}} <li>{{.Name}}</li> {{end}}
使用 template 调用模板
<ul> {{range .Items}} {{template "loop" .}} {{end}} </ul>
template
{{template "模板名" pipeline}}
将对应的上下文 pipeline 传给模板,才可以在模板中调用
beego 中支持直接载入文件模板
{{template "path/to/head.html" .}}
beego 会依据你设置的模板路径读取 head.html
在模板中可以接着载入其他模板,对于模板的分模块处理很有用处
注释
允许多行文本注释,不允许嵌套
{{/* comment content support new line */}}