7.1 更多布局内容的方法

7.1 更多布局内容的方法 #

应用程序中有多种类型的页面,每种页面都有不同的外观。 例如,博客页面通常具有边栏,其中包含有关博客文章的其他信息。 各种类型的页面可以具有不同的CSS样式和不同的HTML结构,以适应其独特的设计。 我们在第6章中使用的一种不同样式页面的方法是对创建的每个页面类别使用新的内容类型。 虽然内容类型是提供隔离特定类型内容的呈现代码的机制的有效概念, Hugo中还有其他方法可以以不同的设计渲染内容-参数化的front matter或新布局。 所有这三种方法都有它们的用例、优缺点,我们可以在同一个网站中同时使用它们。 对于Acme Corporation网站,我们用于使用条款页面 (第6.1.4节) 的网页设计非常简单。 它不能很好地处理博客和新闻部分的内容页面。 我们需要对这些页面进行更精细的设计。 在News页面中所需的更改可以通过CSS来实现,而对于博客页面,我们想要添加一个侧边栏,这涉及到添加HTML内容。 让我们看看与Hugo一起实现这一目标的各种方式。

7.1.1 参数化front matter以区分新闻页面界面 #

当我们在两种不同类型的页面之间有微小的HTML更改时,我们可能不想创建新的内容类型。 我们可以公开一个变量,模板代码可以用来提供差异化的HTML。 使用条件语句if和else,如果需要,我们可以编写不同的HTML内容。 这样,较小的HTML更改就存在于同一文件中,并且我们不需要在磁盘上管理单独的文件。 我们可以最大限度地实现代码重用,而且我们不需要为了防止重复而将代码分成多个partials。 对于Acme Corporation网站上的新闻页面,我们不需要进行很多更改。 这些页面附带我们需要应用的封面图片。 请记住从第六章开始。页面上下文中的资源是指该页面的页面捆绑包中的资源。 我们可以使用with或if检查来确保如果资源不存在,则不会生成额外的HTML。 然后,我们可以将其添加到现有的single.html中,如下面的清单所示。

Listing 7.1 A cover image for the News page (layouts/modern/single.html)
Listing7.1

Acme Corporation网站的新闻部分(图7.2)中的页面与我们到目前为止开发的页面具有类似的HTML结构,并且所有更改都体现在CSS样式中。 由于HTML基本相同,因此切换CSS类的条件语句方法更适合此用例。 虽然我们可以将front matter中的类名作为变量,并通过调用$.Param函数使用它, 我们可以通过多种方式获取这些信息,而无需在网站的内容区域中编写任何内容。 如果我们没有设置内容类型,我们可以通过.Type属性为本例使用内容类型。

图7.2通过使用section信息切换CSS样式,以不同的UI呈现新闻节。 (图片来自Pixabay的tookapic。)

我们可以使用页面的文件夹位置来查找其section。 如果我们为新闻页面运行 {{path.Base (path.Dir .Page.FirstSection.File.Path)}},我们将获得新闻section。 .Page.FirstSection指向新闻section的_index页面,我们可以使用.Page.FirstSection在其路径中找到文件夹名。 请注意,我们也可以将CurrentSection用于新闻页面,但这将破坏博客section的社区subsection。 我们可以使用这个文件夹位置来更改News页面的HTML类,并使其不同于其它页面,如清单7.2所示。

TIP 最大限度地减少在front matter输入数据的需求可以帮助保持内容区域的简单。 在创建内容时,我们必须考虑的front matter元数据越少越好。 我们做了一次主题,但我们不断向网站添加内容。
Listing 7.2 Adding the page section name (layouts/modern/single.html)
{{define "bodyClass"}}
{{ path.Dir .Page.FirstSection.File.Path) }} page
{{end}}
TIP 在定义块中显示网站标题部分的一个条目是很好的。 对于特定于页面的元数据或提供特定于页面的CSS/JavaScript文件,可以重写此功能,从而使主题可扩展。 我们甚至可以使用cover.* 这样的命名约定来加载额外的CSS/JS文件。

单个页面模板可以自动找到该部分的名称,并提供相应的CSS类以及这些更改。 由于此代码存在于Hugo中现代类型的Single Page模板中,因此我们需要将新闻section中的所有页面都分配给此内容类型。 我们将需要在新闻section的每个页面中添加type: modern。 考虑到可能有数百个新闻页面,这是大量的工作。 然而,对于新页面,原型 (在第5.4.3节中讨论) 可以帮助预先定义它们, 但文本仍将是必需的,这可能会导致印刷错误和其他错误。

7.1.2 使用级联属性将属性应用于多个页面的front matter #

Hugo的一项核心原则是减少工作并最大程度地防止代码重复。 在一个部分的所有页面之间共享一个属性对于网站来说是很常见的。 Hugo认识到这一点,并提供了一种机制,可以一次编写此属性并将其应用于所有页面。 Hugo有一个名为casade的front matter属性(图7.3),它的子属性作为front matter属性应用于该部分中的所有页面。

图7.3 cascade属性允许我们为front matter变量提供值,我们可以在整个部分中使用这些值。 在图中,local指定前面的键,而cascade设置与级联的子键相同的键。 顶级 _index文件指定适用于该文件及其子页面的子部分的级联。 /C 发出层叠重写,以便其子树从此节中获取层叠值。 /C2 不使用覆盖,因此,从/C进行级联。 在/C2b中,我们有一个接管该属性的本地覆盖。 在/D中,我们不覆盖cascade属性,但是/D2进行局部覆盖。 /E既有特定索引页的本地覆盖,也有/E1使用的子页的级联。 Section /F仅具有本地覆盖,并且其根的属性遵循/f1。

层叠的概念与CSS中的概念相同,后者代表层叠样式表。 我们在顶层定义一个通用属性,然后在需要重写时定义一个特定属性。 更具体的属性会覆盖泛型属性。 我们甚至可以做一个本地覆盖,其中级联属性适用于子页面,但不适用于当前页面,因为当前页面前面的属性具有更高的优先级。

在新闻section的_index页面上,让我们通过如清单7.3所示的cascade属性启用类型modern。 我们将把它还原为news/_index页面,因为现代类型没有分支列表页面的HTML布局。 默认情况下,casade属性应用于部分中的所有页面,包括子索引页面(list.html)和单个页面(single.html)。

Listing 7.3 The modern type in all content pages (content/news/_index.md)
cascade:  type: 
  modern
type: _default
NOTE 我们可以在front matter的根级别类型字段中使用垃圾字符串。 如果磁盘上不存在前面内容中指定的类型,Hugo将返回到_default文件夹来查找布局。
CODE CHECKPOINT https://chapter-07-01.hugoinaction.com, and source code: https://github.com/hugoinaction/hugoinaction/tree/chapter-07-01.

新闻部分中的每个页面都已使用cascade属性分配给modern的内容类型。 一旦启用了这一功能,我们就可以看到新闻section中的子页面使用News页面的新的CSS样式呈现。 下一组需要不同设计的页面是博客页面。

NOTE 我们仍然可以通过在front matter中手动指定它来覆盖CASCADE属性; 例如,如果我们把类型: _default在新闻部分中的任何页面中,该特定页面都使用默认内容类型呈现,即使它位于设置了层叠内容类型modern的新闻部分中。 我们可以在图7.3中查看级联和重写的各种排列。

7.1.3 为博客内容提供不同的布局 #

博客部分的设计包括一个侧边栏 (图7.4)。 随着时间的推移,我们预计博客在设计上将与新闻页面或常规网页背道而驰。 将代码与不相关的页面保持在一起不是可扩展的解决方案。 当我们有两个以上的条件语句时,事情可能会变得复杂,特别是如果这些条件语句中的内容非常庞大的话。 如果要为各种内容共享具有不同生成的HTML的基本模板,则需要创建一个新的布局。

图7.4带有侧边栏的博客页面是通过向现代内容类型的网页添加新布局而创建的。 (Pexels在Pixabay上的图片。)

网页/叶bundle的默认布局是单一布局,因此我们有一个名为single.html的文件。 这是我们提供对基础模板的覆盖的地方。 但我们并不局限于这种布局。 我们可以把它覆盖到我们想要的任何东西。 内容类型中的布局共享该内容类型中的所有模板,包括呈现挂钩。 表7.1将内容类型与布局进行比较。

Table 7.1 Content type vs. layout Table7.1

我们希望在博客部分有一个侧栏,以提供有关博客帖子的更多信息。 我们可以在前面的内容中提供标签之类的信息,在索引页中使用的摘要之类的信息以及在前面的内容中提供其他属性。 除此之外,Hugo还可以使用.ReadingTime属性生成一组其他元数据,例如使用.ReadingTime属性生成大约的读取时间,使用.WordCount属性生成大约的字数。

让我们在modern文件夹中创建一个名为blog.html的新文件 (https://github.com/hugoinfollowing/hugoinfollowing/tree/chapter-07-resources/01)。 在这个文件中,我们将定义博客页面的正文块以包括一个侧边栏。 下面的清单在提供Hugo生成的信息的HTML