模板方法:对象关联的操作方式
在 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 }}
最佳实践
- 理解上下文:始终注意当前的模板上下文,合理使用 .和$
- 错误处理:对于可能失败的方法调用,使用适当的错误处理
- 性能考虑:避免在循环中重复调用昂贵的方法
- 可读性:使用有意义的变量名来存储方法的返回值
{{/* 良好的实践示例 */}}
{{ $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 模板方法系统提供了强大而灵活的数据访问和操作能力。通过掌握各种对象的方法、理解方法链式调用、合理处理错误和优化性能,你可以创建出高效且易维护的模板。记住始终关注上下文的变化,并采用防御性编程来确保模板的稳定性。