最近抽空学习了一下前端的基础知识,在之前我也抽空看了相关知识,但是发现没有实践而且不够系统,所以索性这次借着hexo博客搭建来巩固和实践一下所学。
准备
虽然我们是开发hexo的博客主题,但是为了方便我们开发中调试和预览,所以我们还是首先得安装hexo到我们本地目录。
注意,上面的“搭建hexo主题”是我本地的一个目录。
然后发布,http://localhost:4000 查看
1
2
| cd 搭建hexo主题
hexo server
|
hexo主题
这个是hexo预置的主题landspace,接下来还需要安装hexo-server和hexo-browsersync。另外我们的主题需要pug和stylus的渲染引擎,所以如下一并安装了:
- hexo-server : hexo的服务运行环境。
- hexo-browsersync : 页面自动刷新插件。
- hexo-renderer-jade : pug的编译工具,内包括了pug的渲染引擎。
- hexo-renderer-stylus : stylus的渲染引擎。
1
| npm install hexo-server hexo-browsersync hexo-renderer-jade hexo-renderer-stylus --save-dev
|
注意,新版的hexo-renderer-jade已经包括了处理pug的渲染引擎。
主题结构
通常来说一个hexo主题需要包括下面元素:
- 首页 Home
- 归档页 Archive
- 标签页 Tag
- 分类页 Category
- 文章页 Post
- 页面详情页 Page
这些页面文件都要放到layout目录里。构建的时候将会读取里面的内容进行编译。像CSS,JS,IMG这些都可以算作是资源文件,构建的时候作为引用的资源。这些都放到source目录里。
生成结构
生成Hexo主题的话,用Yeoman是很方便的。如果系统里没有首先先安装一下npm install yo -g,然后再安装一下npm install generator-hexo-theme -g。(注意全局安装可能需要权限)于是我们就拥有了一个可以生成主题目录结构的脚手架工具。
进入之前创建好的Hexo的博客目录,找到themes文件夹,进入。然后yo hexo-theme,这样就会自动生成对应选项,根据选项我们选择pug和stylus,给这个主题命名为temp。然后就会生成一个还不错的项目目录结构。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| .
├── _config.yml # 主题配置文件
├── layout # 布局文件夹
│ ├── archive.pug # 归档页
│ ├── category.pug # 分类页
│ ├── includes # 复用的公共页
│ │ ├── layout.pug # 页面布局
│ │ ├── pagination.pug # 翻页模板
│ │ └── recent-posts.pug # 文章列表模板
│ ├── index.pug # 主页
│ ├── page.pug # 页面详情页
│ ├── post.pug # 文章详情页
│ └── tag.pug # 标签页
└── source # 资源文件夹
├── css # CSS
│ └── temp.styl
├── favicon.ico # 站点图标
└── js # JS
└── temp.js
|
配置根目录的_config.xml来设置主题为dp2px
启动hexo服务

查看我们的主题页面如下(为了看起来直观,我拷贝了文章到_post目录):

可以看到首页没有任何样式,接下来我们就需要来完善这些页面的布局和样式了。
配置首页链接
我也是初次使用pug,所以看的不是很明白,没关系,我们来先做一下熟悉的事情,配置首页的菜单和链接。
1
2
3
4
5
6
7
| # main menu navigation
menu:
首页: /
关于: /about
归档: /archives
标签: /tags
分类: /categories
|
然后用我们最熟悉的命令创建tags和categories目录
1
2
3
4
| >>> $ hexo new page tags
INFO Created: ~/Documents/搭建hexo主题/source/tags/index.md
>>> $ hexo new page categories
>>> INFO Created: ~/Documents/搭建hexo主题/source/categories/index.md
|
OK!接下来我们分别打开这两个index.md文件并分别添加一个type: tags 和 type: categories
1
2
3
| title: categories
date: 2018-10-24 19:24:07
type: categories
|
来开始编辑我们第一个pug页面,打开themes/dp2px/page.pug,追加如下代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| extends includes/layout.pug
block content
if page.type === 'tags'
.tag-cloud
.tag-cloud__title= page.title
| -
span.tag-cloud__amount= site.tags.length
.tag-cloud-tags!= tagcloud({min_font: 12, max_font: 30, amount: 200, color: true, start_color: '#A4D8FA', end_color: '#0790E8'})
else if page.type === 'categories'
.category-lists
.category__title= page.title
| -
span.category__amount= site.categories.length
div!= list_categories()
else
article#page
h1= page.title
!= page.content
div!= paginator()
|
上面的tagcloud()函数是官方提供的生成标签云的函数,参考链接:https://hexo.io/zh-cn/docs/helpers.html#tagcloud
同样list_categories()函数也是官方提供的生成分类列表的函数,参考链接:https://hexo.io/zh-cn/docs/helpers.html#list-categories
这样我们的tags页面和categories页面就可以显示出来了。

各个pug文件的关系分析
index.pug
首先我们打开index.pug文件
1
2
3
4
5
| extends includes/layout.pug
block content
include includes/recent-posts.pug
div!= paginator()
|
看到这个index.pug继承了layout.pug。
对layout中的block content进行了覆盖,引入了recent-posts.pug
paginator()函数是官方提供生成分页链接的,可以设置它的样式,参考链接:https://hexo.io/zh-cn/docs/helpers.html#paginator
recent-posts.pug
在index.pug中我们看到content中引入了recent-posts.pug
1
2
3
4
5
6
7
8
9
| if page.posts.length > 0
#recent-posts
h1 Recent Posts
each post in page.posts.sort('date', -1).limit(10).toArray()
.recent-post-item
a(href=config.root + post.path)= post.title
if post.date
time(datetime=post.date.toJSON())= date(post.date, date_format)
|
我们看到这里主要是遍历了page.posts.在hexo中有很多预置变量,page就是。
变量 | 描述 |
---|
site | 网站变量 |
page | 针对该页面的内容以及 front-matter 所设定的变量。 |
config | 网站配置 |
theme | 主题配置。继承自网站配置。 |
_ (单下划线) | 函数库 |
path | 当前页面路径(不含根路径) |
url | 当前页面完整网址 |
env | 环境变量 |
关于其他变量的详细请查看官方文档:https://hexo.io/zh-cn/docs/variables
上面的page.posts是页面文章对象,我们看到使用limit(10)拿出了前10个文章显示。
所以,recent-posts.pug是首页最近发布的文章列表。
layout.pug
layout.pug是hexo主题页面中最重要的页面,因为几乎所有页面都继承自它。它提供了一个基础的页面结构模板。
最上面定义了一个pageTitle变量,并根据条件赋值
1
2
3
4
5
6
7
| - var pageTitle = page.title || config.subtitle || ''
- if (is_archive()) pageTitle = 'Archives'
- if (is_tag()) pageTitle = 'Tag: ' + page.tag
- if (is_category()) pageTitle = 'Category: ' + page.category
- if (is_month()) pageTitle += ': ' + page.month + '/' + page.year
- if (is_year()) pageTitle += ': ' + page.year
- pageTitle += ' [ ' + config.title + ' ]'
|
其中 is_archive()、is_tag()这几个函数都是预置函数,判断页面类型的。
接下来定义了head头
1
2
3
4
5
6
7
8
| head
meta(charset='UTF-8')
title= pageTitle
if theme.stylesheets !== undefined && theme.stylesheets.length > 0
//- stylesheets list from config.yml
each url in theme.stylesheets
link(rel='stylesheet', href=url)
link(rel="icon", href=config.root + 'img/favicon.png')
|
可以看到样式文件通过themes下面的_config.yml中的theme.stylesheets来配置。
接下来body中定义了页面菜单、内容模板、以及页脚说明、最后通过theme.scripts加载了js文件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| body
#menu-outer
nav#menu-inner
each url, label in theme.menu
a(href=url)= label
#content-outer
#content-inner
if body
div!= body
else
block content
#bottom-outer
#bottom-inner
span Site construction by
span= ' ' + config.author + ' '
span using
a(href='http://hexo.io')
span hexo blog framework
span .
br
a(href=config.root) Home
if theme.scripts !== undefined && theme.scripts.length > 0
//- scripts list from config.yml
each url in theme.scripts
script(src=url)
|
所以,对于我们来说核心的任务是完成这个layout.pug的布局和样式。