Hexo主题中实现多级分类

大部分的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-3list-4吧,所以这种方式不可取,那么就要从html标签身上动手了,很自然就可以想到无序列表标签,一级分类下包含一个<ul>标签的二级分类。然而设置样式的时候只需要对所有liul设置缩进就行了。

那么问题就来了,页面结构的逻辑怎么写?这个就不用担心了,因为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或者这里

Comments
Write a Comment