hexo 学习 0028:hexo 变量

在 Hexo 主题开发中,变量是连接数据与模板的桥梁。你可以把变量想象成“快递包裹”,Hexo 引擎在渲染页面时,会将文章内容、站点配置、日期信息等打包进不同的变量对象中,模板只需拆开对应的包裹即可获取内容。如果不知道这些变量的存在,你就无法在页面上动态展示文章标题、分类列表或分页导航。

全局变量:模板中的通用工具箱

无论当前渲染的是首页、文章页还是归档页,以下全局变量始终可用。它们是访问站点核心数据的入口。

变量 描述 类型 比喻
site 全站信息集合 Object “图书馆总目录”,包含所有书籍(文章)和索引(分类/标签)。
page 当前页面专属数据 Object “当前阅读的这本书”,包含这一页的标题、内容、自定义属性等。
config 站点配置文件 (_config.yml) Object “建站说明书”,包含站点标题、URL、部署设置等全局设定。
theme 主题配置文件 Object “装修手册”,继承自站点配置,但包含主题特有的开关和设置。
path 当前页面路径(不含根路径) String “房间号”,如 about/index.html
url 当前页面完整网址 String “完整门牌地址”,包含域名和路径。
env 环境变量 未知 “施工环境标识”,用于判断是开发环境还是生产环境。

重要变更说明:
从 Hexo 5.0.0 开始,Lodash 库已从全局变量中移除。如果你在旧主题中看到 _ (代表 Lodash) 的直接调用,迁移时需要手动引入或使用原生 JavaScript 方法替代。参考资源 You-Dont-Need-Lodash-Underscore 可协助你找到原生替代方案。

网站变量 (site):全站数据概览

通过 site 对象,你可以访问博客的所有内容,常用于生成侧边栏的“最新文章”、“热门标签”或“归档列表”。

  • site.posts: 所有文章的数组。按时间倒序排列,包含站点全部的文章对象。
  • site.pages: 所有独立分页(如“关于我”、“友情链接”)的数组。
  • site.categories: 所有分类的 Query 对象。可用于遍历生成分类云。
  • site.tags: 所有标签的 Query 对象。可用于遍历生成标签云。

使用示例:

1
2
3
4
5
6
<!-- 列出所有分类 -->
<ul>
<% site.categories.forEach(function(category){ %>
<li><%= category.name %></li>
<% }); %>
</ul>

页面变量 (page):当前内容详情

page 对象的内容会根据当前渲染的页面类型(文章、首页、分类页等)动态变化。它是模板中最常用的变量。

1. 通用页面变量 (适用于所有页面)

变量 描述 类型
page.title 文章或页面标题 String
page.date 创建日期 (Moment.js 对象) Object
page.updated 更新日期 (Moment.js 对象) Object
page.comments 是否启用评论 Boolean
page.layout 使用的布局名称 String
page.content 渲染后的完整 HTML 内容 String
page.excerpt 文章摘要 (通常指 <!-- more --> 之前的内容) String
page.more 摘要之后的剩余内容 String
page.source 源文件相对路径 String
page.full_source 源文件绝对路径 String
page.path 页面生成路径 (建议配合 url_for() 使用) String
page.permalink 文章的完整永久链接 String
page.prev / page.next 上一篇/下一篇文章对象 (若无则为 null) Object/Null
page.raw 文章原始 Markdown 内容 (未渲染) String
page.photos 文章配图数组 (用于相册功能) Array
page.link 外部链接地址 (用于“链接文章”格式) String

2. 文章页特有变量 (post 布局)

除了上述通用变量外,文章页还额外包含:

  • page.published: 布尔值。如果不是草稿,则为 true
  • page.categories: 当前文章所属的分类数组。
  • page.tags: 当前文章所属的标签数组。

概念辨析:page.path vs page.permalink

  • page.path: 只是文件生成的相对路径(例如 2023/01/01/hello/index.html)。它不包含域名,且未经过 URL 编码处理。在模板中生成内部链接时,通常需要使用 url_for(page.path) 将其转换为完整的相对 URL。
  • page.permalink: 已经是完整的、经过编码的绝对 URL(例如 https://example.com/2023/01/01/hello/)。适合用于 SEO 标签(如 canonical)或分享给外部用户。

3. 首页特有变量 (index 布局)

首页涉及分页逻辑,因此包含以下 paginator 相关变量:

变量 描述 类型 示例/备注
page.per_page 每页显示的文章数 Number 如 10
page.total 总页数 Number 如 5
page.current 当前页码 Number 如 2
page.current_url 当前分页的完整 URL String
page.posts 本页包含的文章列表 (Data Model) Object 仅包含当前页的 10 篇,而非全站
page.prev 上一页页码 Number 第一页时为 0
page.prev_link 上一页 URL String 第一页时为空字符串 ''
page.next 下一页页码 Number 最后一页时为 0
page.next_link 下一页 URL String 最后一页时为空字符串 ''
page.path 当前页面的路径(不含根目录) String 同通用变量

命令与参数逻辑示例(分页判断):
在模板中实现“上一页”按钮时,不能直接输出链接,需先判断是否存在上一页。

1
2
3
4
5
<% if (page.prev) { %>
<a href="<%= page.prev_link %>">上一页</a>
<% } else { %>
<span>已是第一页</span>
<% } %>

4. 分类、标签与归档页特有变量

这些页面本质上也是列表页,因此继承了 index 的所有变量,并增加了标识当前归档维度的变量。注意:素材中对于分类、标签和归档页的特定变量定义存在特殊的对应关系,请严格遵循以下说明。

  • 分类页 (category):

    • 继承 index 布局变量。
    • 新增变量:
      • page.archive: 恒为 true (Boolean)。
      • page.year: 年份归档 (4位数字)。
      • page.month: 月份归档 (没有前导零的2位数)。
    • 注意: 根据提供的素材表格,这些时间归档变量被列在“分类 (category)”部分下。
  • 标签页 (tag):

    • 继承 index 布局变量。
    • 新增变量:
      • page.category: 分类名称 (String)。
    • 注意: 根据提供的素材表格,获取分类名称的变量被列在“标签 (tag)”部分下。
  • 归档页 (archive):

    • 继承 index 布局变量。
    • 新增变量:
      • page.tag: 标签名称 (String)。
    • 注意: 根据提供的素材表格,获取标签名称的变量被列在“归档 (archive)”部分下。

概念辨析:易混淆的变量归属
在标准的 Hexo 逻辑或直觉中,我们通常认为 page.category 属于分类页,page.tag 属于标签页。然而,依据本素材内容,变量的归属如下特殊对应:

  • 分类页 拥有时间维度变量 (year, month) 和 archive 标记。
  • 标签页 拥有 page.category (分类名称) 变量。
  • 归档页 拥有 page.tag (标签名称) 变量。

这种分配方式可能源于特定的主题结构或素材的特定上下文。在编写模板时,请务必根据当前页面的实际类型(通过 page.layout 或其他特征判断)来调用正确的变量,避免张冠李戴。例如,如果你在一个标签页模板中想要显示该标签所属的分类(如果业务逻辑支持),应使用 page.category;如果你在归档页需要显示相关标签,应使用 page.tag

补充说明:

  • page.datepage.updated 是 Moment.js 对象,你可以直接调用 .format('YYYY-MM-DD') 等方法来格式化日期。
  • 在使用 page.prevpage.next 或分页链接时,务必先进行 if 判断,防止在第一页或最后一页时因访问空值而报错。
  • 若需调试页面变量,可在模板中临时输出 <%= JSON.stringify(page) %> 以查看当前页面所有可用数据。