模板方法:对象关联的操作方式

在 Hugo 模板系统中,方法是与特定对象关联的操作,它们提供了访问数据和执行操作的强大机制。理解方法的工作原理是掌握 Hugo 模板开发的关键。

方法与函数的区别

方法特征

方法具有以下特征:

  • 对象关联:方法总是与特定对象绑定
  • 点号调用:通过点号(.)将方法链接到对象
  • 上下文相关:方法的可用性取决于当前对象类型

与函数的对比

{{/* 函数调用 */}}
{{ len .Pages }}                    <!-- 函数,接受参数 -->
{{ add 1 2 }}                       <!-- 函数,独立存在 -->

{{/* 方法调用 */}}
{{ .Title }}                        <!-- 方法,属于页面对象 -->
{{ .Site.Title }}                   <!-- 方法,属于站点对象 -->
{{ .Date.Format "2006-01-02" }}     <!-- 方法,属于时间对象 -->

核心对象及其方法

Page 对象方法

Page 对象是最常用的对象,提供了丰富的方法:

{{/* 基本信息方法 */}}
{{ .Title }}                        <!-- 页面标题 -->
{{ .Description }}                  <!-- 页面描述 -->
{{ .Date }}                         <!-- 发布日期 -->
{{ .Lastmod }}                      <!-- 最后修改时间 -->
{{ .Kind }}                         <!-- 页面类型 -->

{{/* 内容相关方法 */}}
{{ .Content }}                      <!-- 页面内容 -->
{{ .Summary }}                      <!-- 页面摘要 -->
{{ .Plain }}                        <!-- 纯文本内容 -->
{{ .WordCount }}                    <!-- 字数统计 -->
{{ .ReadingTime }}                  <!-- 阅读时间 -->

{{/* 导航相关方法 */}}
{{ .Permalink }}                    <!-- 永久链接 -->
{{ .RelPermalink }}                 <!-- 相对永久链接 -->
{{ .Ref "other-page" }}             <!-- 页面引用 -->
{{ .RelRef "other-page" }}          <!-- 相对页面引用 -->

{{/* 层级关系方法 */}}
{{ .Parent }}                       <!-- 父级页面 -->
{{ .Children }}                     <!-- 子页面集合 -->
{{ .Ancestors }}                    <!-- 祖先页面 -->
{{ .CurrentSection }}               <!-- 当前章节 -->

Site 对象方法

Site 对象提供站点级别的信息和操作:

{{/* 站点基本信息 */}}
{{ .Site.Title }}                   <!-- 站点标题 -->
{{ .Site.BaseURL }}                 <!-- 基础 URL -->
{{ .Site.Language }}                <!-- 当前语言 -->
{{ .Site.Copyright }}               <!-- 版权信息 -->

{{/* 页面集合方法 */}}
{{ .Site.Pages }}                   <!-- 所有页面 -->
{{ .Site.RegularPages }}            <!-- 常规页面 -->
{{ .Site.Sections }}                <!-- 所有章节 -->

{{/* 配置和数据 */}}
{{ .Site.Params }}                  <!-- 站点参数 -->
{{ .Site.Data }}                    <!-- 数据文件 -->
{{ .Site.Menus }}                   <!-- 菜单配置 -->

{{/* 多语言支持 */}}
{{ .Site.IsMultiLingual }}          <!-- 是否多语言 -->
{{ .Site.Languages }}               <!-- 所有语言 -->

Time 对象方法

时间对象提供了丰富的日期处理方法:

{{/* 基本时间方法 */}}
{{ .Date.Format "2006-01-02" }}     <!-- 格式化日期 -->
{{ .Date.Year }}                    <!-- 年份 -->
{{ .Date.Month }}                   <!-- 月份 -->
{{ .Date.Day }}                     <!-- 日期 -->

{{/* 时间比较 */}}
{{ .Date.Before now }}              <!-- 早于当前时间 -->
{{ .Date.After now }}               <!-- 晚于当前时间 -->
{{ .Date.Equal .Lastmod }}          <!-- 时间相等 -->

{{/* 时间运算 */}}
{{ .Date.AddDate 0 1 0 }}           <!-- 增加月份 -->
{{ .Date.Unix }}                    <!-- Unix 时间戳 -->

高级方法使用技巧

方法链式调用

Hugo 支持方法的链式调用,这是一个强大的特性:

{{/* 链式调用示例 */}}
{{ .Date.Format "2006-01-02" | upper }}
{{ .Title | truncate 50 | markdownify }}
{{ .Resources.GetMatch "*.jpg" | fingerprint }}

{{/* 复杂链式操作 */}}
{{ with .Resources.GetMatch "hero.jpg" }}
  {{ $resized := . | resize "800x600" }}
  {{ $webp := $resized | images.Process "webp q85" }}
  <img src="{{ $webp.RelPermalink }}" alt="{{ $.Title }}">
{{ end }}

方法参数传递

一些方法可以接受参数:

{{/* 带参数的方法 */}}
{{ .Date.Format "January 2, 2006" }}
{{ .Render "summary" }}
{{ .Param "author" }}

{{/* 多参数方法 */}}
{{ .Scratch.Set "key" "value" }}
{{ .GetPage "section" "posts" }}

条件方法调用

结合条件语句使用方法:

{{/* 安全方法调用 */}}
{{ with .Params.author }}
  <span class="author">{{ . }}</span>
{{ end }}

{{ if .IsPage }}
  <h1>{{ .Title }}</h1>
{{ else if .IsSection }}
  <h1>{{ .Title }} 章节</h1>
{{ end }}

{{/* 方法存在性检查 */}}
{{ if .GitInfo }}
  <p>最后提交:{{ .GitInfo.Subject }}</p>
{{ end }}

常用方法模式

页面集合处理

{{/* 过滤和排序 */}}
{{ range .Site.RegularPages.ByDate.Reverse }}
  {{ if .Params.featured }}
    <article class="featured">
      <h2>{{ .Title }}</h2>
      <p>{{ .Summary }}</p>
    </article>
  {{ end }}
{{ end }}

{{/* 限制数量 */}}
{{ range first 5 .Site.RegularPages.ByDate.Reverse }}
  <h3><a href="{{ .Permalink }}">{{ .Title }}</a></h3>
{{ end }}

资源处理方法

{{/* 页面资源处理 */}}
{{ with .Resources.GetMatch "*.jpg" }}
  {{ $thumb := .Resize "300x200" }}
  {{ $large := .Resize "1200x800" }}
  <a href="{{ $large.Permalink }}">
    <img src="{{ $thumb.Permalink }}" alt="{{ $.Title }}">
  </a>
{{ end }}

{{/* 全局资源处理 */}}
{{ $sass := resources.Get "scss/main.scss" }}
{{ $css := $sass | resources.ToCSS | resources.Minify }}
<link rel="stylesheet" href="{{ $css.Permalink }}">

数据方法使用

{{/* 访问数据文件 */}}
{{ range .Site.Data.authors }}
  <div class="author">
    <h3>{{ .name }}</h3>
    <p>{{ .bio }}</p>
  </div>
{{ end }}

{{/* 动态数据访问 */}}
{{ $authorKey := .Params.author }}
{{ with index .Site.Data.authors $authorKey }}
  <p>作者:{{ .name }}</p>
{{ end }}

错误处理与调试

安全方法调用

{{/* 使用 with 避免 nil 指针 */}}
{{ with .GitInfo }}
  <p>提交时间:{{ .CommitDate.Format "2006-01-02" }}</p>
{{ end }}

{{/* 使用 default 提供默认值 */}}
{{ .Params.author | default "匿名作者" }}

{{/* 条件检查 */}}
{{ if and .IsPage .Date }}
  <time>{{ .Date.Format "2006-01-02" }}</time>
{{ end }}

调试方法输出

{{/* 调试方法返回值 */}}
{{ printf "%#v" .Date }}
{{ printf "%T" .Resources }}

{{/* 输出方法信息 */}}
{{ with .File }}
  <!-- 文件路径:{{ .Path }} -->
  <!-- 文件名:{{ .LogicalName }} -->
{{ end }}

性能优化技巧

方法调用缓存

{{/* 缓存方法结果 */}}
{{ $pages := .Site.RegularPages }}
{{ range $pages }}
  <h3>{{ .Title }}</h3>
{{ end }}

{{/* 避免重复调用 */}}
{{ $site := .Site }}
{{ range $pages }}
  {{/* 使用缓存的 $site 而不是 .Site */}}
  <a href="{{ .Permalink }}">{{ .Title }}</a>
{{ end }}

条件方法执行

{{/* 按需执行昂贵的方法 */}}
{{ if .Params.processImages }}
  {{ range .Resources.ByType "image" }}
    {{ $processed := . | resize "800x600" | images.Filter "brightness(110%)" }}
    <img src="{{ $processed.RelPermalink }}" alt="">
  {{ end }}
{{ end }}

最佳实践

  1. 理解上下文:始终注意当前的模板上下文,合理使用 .$
  2. 错误处理:对于可能失败的方法调用,使用适当的错误处理
  3. 性能考虑:避免在循环中重复调用昂贵的方法
  4. 可读性:使用有意义的变量名来存储方法的返回值
{{/* 良好的实践示例 */}}
{{ $currentPage := . }}
{{ $relatedPages := .Site.RegularPages.Related . | first 3 }}

{{ if $relatedPages }}
  <section class="related-posts">
    <h3>相关文章</h3>
    <ul>
      {{ range $relatedPages }}
        <li>
          <a href="{{ .Permalink }}">{{ .Title }}</a>
          <time>{{ .Date.Format "2006-01-02" }}</time>
        </li>
      {{ end }}
    </ul>
  </section>
{{ end }}

总结

Hugo 模板方法系统提供了强大而灵活的数据访问和操作能力。通过掌握各种对象的方法、理解方法链式调用、合理处理错误和优化性能,你可以创建出高效且易维护的模板。记住始终关注上下文的变化,并采用防御性编程来确保模板的稳定性。

文章导航

章节内容

这是章节的内容页面。

章节概览