- /
- Skills/
- Hugo 使用指南/
- 在hugo中如何使用菜单/
在hugo中如何使用菜单
目录
hugo 提供了比较灵活的菜单生成方案。分为内置模式、或自定义模式。自定义模块就是用户根据自己的需要自行去生成导航栏。本文主要是分享在使用hugo内置模式菜单的使用经验。
官方的文档链接, gohugo.io/content-management/menus/ 。看完文档后有没有一种云里雾的感觉呢?
如果你也跟我一样,有这种感觉,那么说明不是你的问题,因为hugo的菜单支持比较灵活,分了好几个文档,需要结合来看。当你做为例子之后,那么一切都会变得简单。
其实 hugo 的菜单相关文档有这些:
- gohugo.io/content-management/menus, 介绍如何管理菜单
- gohugo.io/templates/menu-templates,在模板中使用菜单的示例
- gohugo.io/variables/menus, 在模板中使用菜单里的对象,这个对象决定了在模板或者 config.yaml 中可以获取或者配置什么信息
菜单对象 #
Menu Entry Properties
在了解如果配置菜单或在模板中使用菜单之前,需要先了解 hugo 为菜单设计了哪些信息项,即数据结构。 主要的是这些,名称(name, title identifier)、url、优先权重(weight)、上级菜单、下级菜单、对应页面等。可以从文档 variables/menus 上获得更多详细内容。
以上所列信息项,配置在 config.yaml 中,然后就可以在 页面模板中通过 site.Menus 获取到。
菜单辅助函数 #
hugo 为菜单对象提供了几个方便的辅助函数,如:
MENUENTRY.HasChildren
- 判断是否有下级菜单
MENUENTRY.KeyName
- 返回菜单的标识
MENUENTRY.Title
- 用于菜单页面显示
PAGE.IsMenuCurrent MENU MENUENTRY
- 判断页面是否为某个菜单对应的页面
PAGE.HasMenuCurrent MENU MENUENTRY
- 判断页面是否为某个菜单下的子菜单对应页面
以上函数,比较常用的是.HasChildren
,.Title
菜单信息配置 #
在 hugo 中,可以有两种方式来配置菜单信息。
- 在 config.yaml 中添加 menus.MENU.[MENUENTRY,MENUENTRY] 项
- 在 页面内容文章 xxx.md 的 front matter 中配置菜单子项
结合以上两种方式,可以满足非内容页面的链接与内容页面的链接。
youwu.today 提示,因为 hugo 的配置器非常灵活,支持将菜单的信息配置在config.yaml之外的menus.yaml文件中,为了方便维护管理,本站使用 menus.yaml 文件来管理本站使用到的菜单。
配置文件支持 json、yaml、toml 格式。为了方面阅读,本文使用 yaml 格式。
一个正常的 config.yaml 菜单项大概长这个样子,以本站菜单配置中的一段为例:
# menus.yaml
main:
- name: hugo section 技能
title: 有悟
url: /skill/
weight: 2
identifier: skill
params:
type: grid
...
一个菜单项就是一个 MENUENTRY。其中最重要的 identifier,url。而示例中的 main 可以是任何标识符,因为 hugo 并没有限定这个名称。你可以把它简单理解 为菜单组的名称。另外,为了某种判断,可以加上自定义参数,这些参数 hugo 是无法理解的,所以要统一放在 params 中,由用户自行决定。
如果你将菜单信息配置在 config.yaml 中,那么 yaml 中应该这样写:
# config.yaml
menu:
main:
- name: hugo section 技能
title: 有悟
url: /skill/
weight: 2
identifier: skill
params:
type: grid
...
将页面链接做为子菜单 #
在页面内容文件的 front matter 中,配置子菜单:
# front matter
...
menu:
main:
parent: "skill"
...
这里之所以产生菜单父子关联关系,是 main 和 parent 起了作用。这两项结合指向了 config.yaml 或者 menus.yaml 中的对应的菜单。就这样,hugo 会在 skill MENUENTRY 下面挂上一个子菜单,来对应这个页面。
直接配置子菜单 #
除了可以在内容文件的 front matter 挂接子菜单外,还可以直接在 config.yaml 配置子菜单。继续上面的示例:
# menus.yaml
main:
- name: hugo section 技能
title: 有悟
url: /skill/
weight: 2
identifier: skill
params:
type: grid
- name: 今日热点、热榜聚集
title: 今日
url: /hot/
weight: 1
identifier: hot
- name: 热搜
title: 热搜
url: /hot/words/
identifier: hot_words
parent: hot
weight: 101
...
这一段 yaml 片段,hugo 会生成如下结构的菜单,重点在于 parent 属性。
main
├─ skill
├─ hot
│ └─ hot_words
如果你将子菜单如 hot_words 配置在 menus.yaml中,那么 front matter 中就不要配置,因为会重复。
在模板中引用菜单信息 #
在配置了菜单信息之后,如果不在模板中使用,是起不到任何作用的。
<ul>
{{ range site.Menus.main }}
{{ if .HasChildren }}
<ul>
{{ range .Children }}
<li>
<a href="{{ .URL }}">{{ .Name }}</a>
</li>
{{ end }}
</ul>
{{ else }}
<li>
<a href="{{ .URL }}">{{ .Name }}</a>
</li>
{{ end }}
{{ end }}
</ul>
例中的 site.Menus.main 就是在模板中获取 menus.yaml 中 main 的方法。这个例子可以获取到
直接配置子菜单
中的 skill 和 hot ,并且菜单项 hot 的 .HasChildren
可以判断存在子菜单,使用 .Children
可以取到 hot_words,当然 .Children
得到的是一个 slice,需要 range 来迭代。
gohugo.io/templates/menu-templates/ 上有更加详尽的例子。