模板入门
模板是项目、主题或模块的 layouts
目录中的文件。模板使用变量、函数和方法将您的内容、资源和数据转换为已发布的页面。
例如,此 HTML 模板初始化 $v1
和 $v2
变量,然后在 HTML 段落中显示它们及其乘积。
{{ $v1 := 6 }}
{{ $v2 := 7 }}
<p>The product of {{ $v1 }} and {{ $v2 }} is {{ mul $v1 $v2 }}.</p>
虽然 HTML 模板是最常见的,但您可以为任何输出格式创建模板,包括 CSV、JSON、RSS 和纯文本。
上下文
在创建模板之前,最需要理解的概念是上下文,即传递到每个模板中的数据。数据可以是简单的值,或者更常见的是对象和相关的方法。
例如,单页模板会收到一个 Page
对象,而 Page
对象提供返回值或执行操作的方法。
当前上下文
在模板中,点 (.
) 表示当前上下文。
<h2>{{ .Title }}</h2>
在上面的示例中,点表示 Page
对象,我们调用它的 Title
方法来返回 前言 中定义的标题。
当前上下文可能会在模板中更改。例如,在模板的顶部,上下文可能是 Page
对象,但我们在 range
或 with
块中将上下文重新绑定到另一个值或对象。
<h2>{{ .Title }}</h2>
{{ range slice "foo" "bar" }}
<p>{{ . }}</p>
{{ end }}
{{ with "baz" }}
<p>{{ . }}</p>
{{ end }}
在上面的示例中,当我们 range
遍历值切片时,上下文会发生变化。在第一次迭代中,上下文是“foo”,在第二次迭代中,上下文是“bar”。在 with
块内部,上下文是“baz”。Hugo 将以上内容渲染为
<h2>My Page Title</h2>
<p>foo</p>
<p>bar</p>
<p>baz</p>
模板上下文
在 range
或 with
块中,您可以通过在点前面加上美元符号 ($
) 来访问传递到模板中的上下文
{{ with "foo" }}
<p>{{ $.Title }} - {{ . }}</p>
{{ end }}
Hugo 将其渲染为
<p>My Page Title - foo</p>
操作
在上面的示例中,成对的开闭大括号表示模板操作的开始和结束,即模板中的数据求值或控制结构。
模板操作可以包含字面值(布尔值、字符串、整数和浮点数)、变量、函数和方法。
{{ $convertToLower := true }}
{{ if $convertToLower }}
<h2>{{ strings.ToLower .Title }}</h2>
{{ end }}
在上面的示例中
$convertToLower
是一个变量true
是一个字面布尔值strings.ToLower
是一个将所有字符转换为小写的函数Title
是Page
对象上的一个方法
Hugo 将以上内容渲染为
<h2>my page title</h2>
空格
请注意上一个示例中的空白行和缩进?虽然在通常缩小输出的生产环境中无关紧要,但您可以使用带有连字符的模板操作分隔符来删除相邻的空格
{{- $convertToLower := true -}}
{{- if $convertToLower -}}
<h2>{{ strings.ToLower .Title }}</h2>
{{- end -}}
Hugo 将其渲染为
<h2>my page title</h2>
空格包括空格、水平制表符、回车符和换行符。
管道
在模板操作中,您可以将值管道传输到函数或方法。管道传输的值将成为函数或方法的最后一个参数。例如,以下两者是等效的
{{ strings.ToLower "Hugo" }} → hugo
{{ "Hugo" | strings.ToLower }} → hugo
您可以将一个函数或方法的结果管道传输到另一个函数或方法中。例如,以下两者是等效的
{{ strings.TrimSuffix "o" (strings.ToLower "Hugo") }} → hug
{{ "Hugo" | strings.ToLower | strings.TrimSuffix "o" }} → hug
以下两者也是等效的
{{ mul 6 (add 2 5) }} → 42
{{ 5 | add 2 | mul 6 }} → 42
换行
您可以将模板操作拆分到两行或更多行。例如,以下两者是等效的
{{ $v := or $arg1 $arg2 }}
{{ $v := or
$arg1
$arg2
}}
您还可以将原始字符串字面量拆分到两行或更多行。例如,以下两者是等效的
{{ $msg := "This is line one.\nThis is line two." }}
{{ $msg := `This is line one.
This is line two.`
}}
变量
变量是以美元符号 ($
) 开头的用户定义的标识符,表示任何数据类型的值,在模板操作中初始化或赋值。例如,$foo
和 $bar
是变量。
使用 :=
初始化变量,并使用 =
为先前已初始化的变量赋值。 例如:
{{ $total := 3 }}
{{ range slice 7 11 21 }}
{{ $total = add $total . }}
{{ end }}
{{ $total }} → 42
在 if
、range
或 with
代码块内部初始化的变量的作用域限定在该代码块内。 在这些代码块外部初始化的变量的作用域限定在模板中。
对于表示切片或映射的变量,请使用index
函数返回所需的值。
{{ $slice := slice "foo" "bar" "baz" }}
{{ index $slice 2 }} → baz
{{ $map := dict "a" "foo" "b" "bar" "c" "baz" }}
{{ index $map "c" }} → baz
对于表示映射或对象的变量,请链接标识符以返回所需的值或访问所需的方法。
{{ $map := dict "a" "foo" "b" "bar" "c" "baz" }}
{{ $map.c }} → baz
{{ $homePage := .Site.Home }}
{{ $homePage.Title }} → My Homepage
函数
在模板操作中使用时,函数接受一个或多个参数并返回一个值。 与方法不同,函数不与对象关联。
Go 的 text/template 和 html/template 包提供了一小部分函数、运算符和语句供通用使用。 有关详细信息,请参阅函数文档的 go-templates 部分。
Hugo 提供了数百个按命名空间分类的自定义函数。 例如,strings
命名空间包括以下函数以及其他函数:
函数 | 别名 |
---|---|
strings.ToLower |
lower |
strings.ToUpper |
upper |
strings.Replace |
replace |
如上所示,常用函数具有别名。 在模板中使用别名可以减少代码长度。
调用函数时,请使用空格将参数与函数分隔开,并使用空格分隔参数。 例如:
{{ $total := add 1 2 3 4 }}
方法
在模板操作中使用且与对象关联时,方法接受零个或多个参数,并返回一个值或执行一个操作。
最常访问的对象是 Page
和 Site
对象。 下面是每个对象可用方法的一小部分示例。
对象 | 方法 | 描述 |
---|---|---|
Page |
Date |
返回给定页面的日期。 |
Page |
Params |
返回给定页面的 front matter 中定义的自定义参数的映射。 |
Page |
Title |
返回给定页面的标题。 |
Site |
Data |
返回由 data 目录中的文件组成的数据结构。 |
Site |
Params |
返回在站点配置中定义的自定义参数的映射。 |
Site |
Title |
返回在站点配置中定义的标题。 |
使用点 (.
) 将方法链接到其对象,如下所示,请记住,前导点表示当前上下文。
{{ .Site.Title }} → My Site Title
{{ .Page.Title }} → My Page Title
传递到大多数模板中的上下文是 Page
对象,因此这与前面的示例等效
{{ .Site.Title }} → My Site Title
{{ .Title }} → My Page Title
某些方法接受参数。 使用空格将参数与方法分隔开。 例如:
{{ $page := .Page.GetPage "/books/les-miserables" }}
{{ $page.Title }} → Les Misérables
注释
模板注释类似于模板操作。 成对的开括号和闭括号表示注释的开始和结束。 例如:
{{/* This is an inline comment. */}}
{{- /* This is an inline comment with adjacent whitespace removed. */ -}}
注释内的代码不会被解析、执行或显示。 注释可以是内联的,如上所示,也可以是块形式的
{{/*
This is a block comment.
*/}}
{{- /*
This is a block comment with
adjacent whitespace removed.
*/ -}}
您不能在一个注释内嵌套另一个注释。
要呈现 HTML 注释,请通过 safeHTML
模板函数传递字符串。 例如:
{{ "<!-- I am an HTML comment. -->" | safeHTML }}
{{ printf "<!-- This is the %s site. -->" .Site.Title | safeHTML }}
包含
使用 template
函数来包含一个或多个 Hugo 的嵌入式模板
{{ template "_internal/google_analytics.html" . }}
{{ template "_internal/opengraph" . }}
{{ template "_internal/pagination.html" . }}
{{ template "_internal/schema.html" . }}
{{ template "_internal/twitter_cards.html" . }}
使用 partial
或 partialCached
函数来包含一个或多个部分模板
{{ partial "breadcrumbs.html" . }}
{{ partialCached "css.html" . }}
在 layouts/partials 目录中创建您的部分模板。
示例
这些有限的、人为设计的示例演示了上面描述的一些概念。 有关具体示例,请参阅函数、方法和模板文档。
条件块
{{ $var := 42 }}
{{ if eq $var 6 }}
{{ print "var is 6" }}
{{ else if eq $var 7 }}
{{ print "var is 7" }}
{{ else if eq $var 42 }}
{{ print "var is 42" }}
{{ else }}
{{ print "var is something else" }}
{{ end }}
逻辑运算符
{{ $v1 := true }}
{{ $v2 := false }}
{{ $v3 := false }}
{{ $result := false }}
{{ if and $v1 $v2 $v3 }}
{{ $result = true }}
{{ end }}
{{ $result }} → false
{{ if or $v1 $v2 $v3 }}
{{ $result = true }}
{{ end }}
{{ $result }} → true
循环
{{ $s := slice "foo" "bar" "baz" }}
{{ range $s }}
<p>{{ . }}</p>
{{ else }}
<p>The collection is empty</p>
{{ end }}
使用 seq
函数循环指定的次数
{{ $total := 0 }}
{{ range seq 4 }}
{{ $total = add $total . }}
{{ end }}
{{ $total }} → 10
重新绑定上下文
{{ $var := "foo" }}
{{ with $var }}
{{ . }} → foo
{{ else }}
{{ print "var is falsy" }}
{{ end }}
要测试多个条件
{{ $v1 := 0 }}
{{ $v2 := 42 }}
{{ with $v1 }}
{{ . }}
{{ else with $v2 }}
{{ . }} → 42
{{ else }}
{{ print "v1 and v2 are falsy" }}
{{ end }}
访问站点参数
请参阅 Site
对象上的 Params
方法的文档。
使用此站点配置
baseURL: https://example.org
params:
author:
email: jsmith@example.org
name: John Smith
copyright-year: "2023"
layouts:
rfc_1123: Mon, 02 Jan 2006 15:04:05 MST
rfc_3339: "2006-01-02T15:04:05-07:00"
subtitle: The Best Widgets on Earth
title: ABC Widgets
baseURL = 'https://example.org'
title = 'ABC Widgets'
[params]
copyright-year = '2023'
subtitle = 'The Best Widgets on Earth'
[params.author]
email = 'jsmith@example.org'
name = 'John Smith'
[params.layouts]
rfc_1123 = 'Mon, 02 Jan 2006 15:04:05 MST'
rfc_3339 = '2006-01-02T15:04:05-07:00'
{
"baseURL": "https://example.org",
"params": {
"author": {
"email": "jsmith@example.org",
"name": "John Smith"
},
"copyright-year": "2023",
"layouts": {
"rfc_1123": "Mon, 02 Jan 2006 15:04:05 MST",
"rfc_3339": "2006-01-02T15:04:05-07:00"
},
"subtitle": "The Best Widgets on Earth"
},
"title": "ABC Widgets"
}
通过链接标识符来访问自定义站点参数
{{ .Site.Params.subtitle }} → The Best Widgets on Earth
{{ .Site.Params.author.name }} → John Smith
{{ $layout := .Site.Params.layouts.rfc_1123 }}
{{ .Site.Lastmod.Format $layout }} → Tue, 17 Oct 2023 13:21:02 PDT
访问页面参数
请参阅 Page
对象上的 Params
方法的文档。
使用此 front matter
date: 2023-10-17T15:11:37-07:00
params:
author:
email: jsmith@example.org
name: John Smith
display_related: true
title: Annual conference
date = 2023-10-17T15:11:37-07:00
title = 'Annual conference'
[params]
display_related = true
[params.author]
email = 'jsmith@example.org'
name = 'John Smith'
{
"date": "2023-10-17T15:11:37-07:00",
"params": {
"author": {
"email": "jsmith@example.org",
"name": "John Smith"
},
"display_related": true
},
"title": "Annual conference"
}
通过链接标识符来访问自定义页面参数
{{ .Params.display_related }} → true
{{ .Params.author.name }} → John Smith