大部分的Hexo主题都将文章的分类放在了sidebar上面,并且都是支持多级分类的,然而默认的light主题并没有实现多级分类的功能,主要原因应该是该主题太老了,没人更新了,但是偏偏就有像我这样喜欢它的简洁风格的人。
有折腾就有收获,下面就来了解一下Hexo中是如何实现多级分类的。
还是以light-ch主题为例。首先看一下最终效果如下图:
上面提到分类一般放到sidebar上,于是在主题中找到layout/_widget/category.ejs
文件,light主题最开始的代码如下:
<% if (site.categories.length){ %>
<div class="widget tag">
<h3 class="title"><%= __('categories') %></h3>
<% site.categories.sort('name').each(function(item){ %>
<li><a href="<%- config.root %><%- item.path %>"><%= item.name %></a><small><%= item.posts.length %></small></li>
<% }); %>
</div>
<% } %>
这里将site.categories
的所有分类,按照名字的顺序进行遍历,并显示在列表标签下,从这段代码可以看出,实现分类列表的主要原理就是这样。
然而这样并不能区分多级分类,因为多级分类名也会按照同样的等级以及样式显示在<li>
标签下,不能跟一级分类区分开来。那么该如何区分呢?我最初的想法是通过判断一个列表是否有下阶分类,并通过设置不同的class
类名来区分,如下代码所示。
<% if (site.categories.length){ %>
<div class="widget tag">
<h3 class="title"><%= __('categories') %></h3>
<% site.categories.sort('name').each(function(item){ %>
<% if(item.parent) {%>
<li><a class = "list-2"href="<%- config.root %><%- item.path %>"><%= item.name %></a><small><%= item.posts.length %></small></li>
<% }else{%>
<li><a href="<%- config.root %><%- item.path %>"><%= item.name %></a><small><%= item.posts.length %></small></li>
<% } %>
<% }); %>
</div>
<% } %>
这里在分类的循环遍历里加了一个判断语句,当遍历到某个分类的时候,先判断它是否有父分类,也就是判断它是否为二级分类。如果是二级分类,放到带有class="list-2"
的列表标签下,这样就跟一级分类区分开了,然后通过css
,将list-2
设置个margin-left
值,进行缩进就OK了。
然而当有3级、4级分类怎么办?总不能list-3
、list-4
吧,所以这种方式不可取,那么就要从html标签身上动手了,很自然就可以想到无序列表标签,一级分类下包含一个<ul>
标签的二级分类。然而设置样式的时候只需要对所有li
下ul
设置缩进就行了。
那么问题就来了,页面结构的逻辑怎么写?这个就不用担心了,因为Hexo有封装好的帮助函数list_categories()
。有了这个帮助函数就简单了,改写category.ejs
代码如下:
<% if (site.categories.length){ %>
<div class="widget tag">
<h3 class="title"><%= __('categories') %></h3>
<%- list_categories(site.categories) %>
</div>
<% } %>
页面结构搞定了,在source/css/_partial/sidebar.styl
中添加样式代码就行了。
.category-list
font-size 0.9em
padding 15px 20px
.category-list-count
margin-left 8px
font-size 0.8em
color color-meta
&:before
content '('
&:after
content ')'
ul, ol, dl
list-style none
ul, ol, dl
margin-left 20px
li:before
content '> '
这里的样式显示的效果就如上图那样,你可以自定义出你的样式。
补充:
list_categories([categories], [options])
帮助函数可以添加参数。
例如当你不想显示多级分类了,不必去修改每篇文章的前置申明,只需设置depth参数就行了。
list_categories(site.categories,{depth: 1})
这样就只会显示一级分类了。用法可以参考一下官方Docs