Hugo 核心概念

概述

本文档旨在帮助您理解 Hugo 的核心概念和基本机制。掌握这些概念是有效使用 Hugo 的基础,涵盖模板系统、变量管理、控制流程以及内置函数的使用。

模板系统

模板引擎基础

Hugo 采用 Go 的 text/template 包作为模板引擎基础,并对其进行了扩展:

  • 模板语法:使用双大括号 {{ }} 包围动作和表达式
  • 上下文访问:通过点号 . 访问当前上下文的数据
  • 函数调用:支持内置函数和自定义函数的调用
  • 管道操作:可以将函数和操作串联起来处理数据

模板类型

Hugo 使用不同类型的模板来渲染不同种类的页面:

1. Home(首页)模板

渲染网站的首页,通常是 layouts/home.html

2. Page(页面)模板

渲染常规内容页面,如博客文章或产品页面。

3. Base(基础)模板

定义网站的整体结构,其他模板可以继承它:

<!DOCTYPE html>
<html>
<head>
    <title>{{ .Title }}</title>
</head>
<body>
    {{ block "main" . }}{{ end }}
</body>
</html>

4. 部分模板(Partial Templates)

存储在 layouts/_partials 目录下的可复用代码片段:

<!-- layouts/_partials/header.html -->
<header>
    <h1>{{ .Site.Title }}</h1>
</header>

在其他模板中调用:

{{ partial "header.html" . }}

变量系统

上下文(点 .

. 符号代表当前上下文,用于访问数据:

{{ .Title }}        <!-- 页面标题 -->
{{ .Content }}      <!-- 页面内容 -->
{{ .Date }}         <!-- 页面日期 -->
{{ .Site.Title }}   <!-- 站点标题 -->

变量声明和赋值

初始化变量

使用 := 初始化新变量:

{{ $title := .Title }}
{{ $posts := where .Site.RegularPages "Type" "post" }}

变量赋值

使用 = 给已初始化的变量赋值:

{{ $title := "默认标题" }}
{{ if .Title }}
    {{ $title = .Title }}
{{ end }}

变量作用域

变量的作用域规则:

  1. 块内变量:在 ifrangewith 块内部初始化的变量,作用域仅限于该块
  2. 模板级变量:在块外部初始化的变量,作用域为整个模板
{{ $globalVar := "全局变量" }}

{{ if .Title }}
    {{ $localVar := "局部变量" }}
    {{ $globalVar = "修改全局变量" }}
{{ end }}
<!-- $localVar 在此处不可访问 -->
<!-- $globalVar 保持修改后的值 -->

访问集合数据

切片和数组访问

使用 index 函数访问:

{{ $array := slice "apple" "banana" "cherry" }}
{{ index $array 0 }}  <!-- 输出: apple -->

字典和映射访问

{{ $dict := dict "name" "Hugo" "type" "generator" }}
{{ index $dict "name" }}  <!-- 输出: Hugo -->
{{ $dict.name }}          <!-- 也可以这样访问 -->

控制流语句

条件语句

if/else if/else

{{ if .Title }}
    <h1>{{ .Title }}</h1>
{{ else if .Description }}
    <h1>{{ .Description }}</h1>
{{ else }}
    <h1>默认标题</h1>
{{ end }}

比较操作符

{{ if eq .Type "post" }}
    这是一篇文章
{{ end }}

{{ if and (gt .WordCount 100) (lt .WordCount 500) }}
    这是中等长度的文章
{{ end }}

循环语句

range 遍历

遍历集合并为每个元素绑定上下文:

<!-- 遍历页面列表 -->
{{ range .Site.RegularPages }}
    <article>
        <h2><a href="{{ .Permalink }}">{{ .Title }}</a></h2>
        <p>{{ .Summary }}</p>
    </article>
{{ end }}

<!-- 带索引的遍历 -->
{{ range $index, $page := .Site.RegularPages }}
    <li>{{ add $index 1 }}. {{ $page.Title }}</li>
{{ end }}

循环控制

{{ range .Site.RegularPages }}
    {{ if eq .Type "draft" }}
        {{ continue }}  <!-- 跳过草稿 -->
    {{ end }}
    
    {{ if gt .WordCount 1000 }}
        {{ break }}     <!-- 停止遍历 -->
    {{ end }}
    
    <p>{{ .Title }}</p>
{{ end }}

with 语句

将上下文设置为指定值:

{{ with .Params.author }}
    <p>作者:{{ . }}</p>
{{ end }}

<!-- 等同于 -->
{{ if .Params.author }}
    <p>作者:{{ .Params.author }}</p>
{{ end }}

block 语句

定义可在继承模板中重新定义的模板块:

<!-- baseof.html -->
{{ block "title" . }}
    <title>{{ .Site.Title }}</title>
{{ end }}

<!-- single.html -->
{{ define "title" }}
    <title>{{ .Title }} - {{ .Site.Title }}</title>
{{ end }}

高级控制流

return 语句

在部分模板中终止执行并返回值:

<!-- layouts/_partials/get-author.html -->
{{ with .Params.author }}
    {{ return . }}
{{ end }}
{{ return "匿名作者" }}

try 语句

用于错误处理:

{{ $result := try (index .Params "nonexistent") }}
{{ if $result.Error }}
    处理错误:{{ $result.Error }}
{{ else }}
    值:{{ $result.Value }}
{{ end }}

内置函数分类

类型转换函数

{{ $number := "123" | int }}        <!-- 字符串转整数 -->
{{ $string := 123 | string }}       <!-- 整数转字符串 -->
{{ $float := "123.45" | float }}     <!-- 字符串转浮点数 -->

集合操作函数

<!-- 过滤集合 -->
{{ $posts := where .Site.RegularPages "Type" "post" }}

<!-- 排序 -->
{{ $sorted := sort .Site.RegularPages "Date" "desc" }}

<!-- 获取前几项 -->
{{ $recent := first 5 $posts }}

<!-- 分组 -->
{{ $grouped := group .Site.RegularPages "Type" }}

字符串处理函数

{{ "Hello World" | lower }}         <!-- hello world -->
{{ "hello world" | title }}         <!-- Hello World -->
{{ .Content | truncate 100 }}       <!-- 截取前100个字符 -->
{{ .Title | urlize }}               <!-- 转换为URL友好格式 -->

数学运算函数

{{ add 1 2 }}           <!-- 3 -->
{{ sub 10 3 }}          <!-- 7 -->
{{ mul 4 5 }}           <!-- 20 -->
{{ div 15 3 }}          <!-- 5 -->
{{ mod 10 3 }}          <!-- 1 -->

日期时间函数

{{ .Date.Format "2006-01-02" }}                    <!-- 格式化日期 -->
{{ now.Format "January 2, 2006" }}                 <!-- 当前时间 -->
{{ .Date.AddDate 0 0 7 | dateFormat "2006-01-02" }} <!-- 7天后 -->

比较函数

{{ eq .Type "post" }}               <!-- 等于 -->
{{ ne .Draft true }}                <!-- 不等于 -->
{{ gt .WordCount 500 }}             <!-- 大于 -->
{{ lt .ReadingTime 5 }}             <!-- 小于 -->
{{ and (not .Draft) (gt .WordCount 100) }} <!-- 逻辑与 -->

调试和开发工具

调试函数

<!-- 打印变量内容 -->
{{ printf "%#v" .Params }}

<!-- 调试输出 -->
{{ debug.Dump . }}

<!-- 错误输出 -->
{{ errorf "缺少必需的参数: %s" .Type }}

<!-- 警告输出 -->
{{ warnf "建议设置页面标题" }}

性能测试

{{ $timer := debug.Timer "section-render" }}
<!-- 一些复杂的模板逻辑 -->
{{ $timer.Stop }}

数据检查

<!-- 检查变量是否存在 -->
{{ if isset .Params "author" }}
    作者:{{ .Params.author }}
{{ end }}

<!-- 检查变量类型 -->
{{ if reflect.IsSlice .Params.tags }}
    标签数量:{{ len .Params.tags }}
{{ end }}

最佳实践

1. 模板组织

  • 使用部分模板提高代码复用性
  • 合理使用基础模板建立页面结构
  • 按功能模块组织模板文件

2. 变量命名

  • 使用有意义的变量名
  • 遵循一致的命名约定
  • 适当使用注释说明复杂逻辑

3. 性能优化

  • 避免在循环中进行复杂计算
  • 使用 partialCached 缓存部分模板
  • 合理使用条件语句减少不必要的处理

4. 错误处理

  • 使用 with 语句检查变量存在性
  • 提供合理的默认值
  • 使用 try 语句处理可能的错误

掌握这些核心概念后,您就可以有效地使用 Hugo 创建复杂而强大的静态网站了。

文章导航

章节内容

这是章节的内容页面。

章节概览