Hexo Matery 主题添加多级分类
有同学提出 Matery 主题的 标签 和 分类 的展示太相似,可以说基本上是一样的。于是有了本文,尝试改成多级分类的。 假如要自己从零开始学习又不太现实, 所以就借鉴移植了 Fluid 主题的多级分类功能。为了给也想折腾的人,特此记录修改过程。
多级分类添加流程
Matery 主题是卡片式结构,为了保持原来的整体结构,新建多级分类的模块。
1、新建 category-list.ejs
在主题目录 /layout/_widget/目录下新建 category-list.ejs 文件。 内容如下:
<% var orderBy =  'name' ;  %>
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.4.1/css/bootstrap.min.css">
<script src="https://cdn.staticfile.org/twitter-bootstrap/4.4.1/js/bootstrap.min.js"></script>
<style>
.category:not(:last-child) {
  margin-bottom: 1rem;
}
.category-item {
  font-size: 1.25rem;
  font-weight: bold;
  display: flex;
  align-items: center;
}
.category-subitem {
  font-size: 1rem;
  font-weight: bold;
}
.category-collapse {
  margin-left: 1.25rem;
  width: 100%;
}
.category-count {
  font-size: 0.9rem;
  font-weight: initial;
  min-width: 1.3em;
  line-height: 1.3em;
  display: flex;
  align-items: center;
}
.category-count i {
  padding-right: 0.25rem;
}
.category-count span {
  width: 2rem;
}
.category-item-action:not(.collapsed) > i {
  transform: rotate(90deg);
  transform-origin: center center;
}
.category-item-action i {
  transition: transform 0.3s ease-out;
  display: inline-block;
  margin-left: 0.25rem;
}
.category-item-action:hover {
  z-index: 1;
  color: #38ACDF;
  text-decoration: none;
  background-color: #F8F9FA;
}
.category .row {
  margin-left: 0;
  margin-right: 0;
}
.list-group-item:first-child {
    border-top-left-radius: .25rem;
    border-top-right-radius: .25rem;
}
.category-item {
    font-size: 1.25rem;
    font-weight: 700;
    display: flex;
    align-items: center;
}
.list-group-item {
    background-color: transparent;
    border: 0;
}
.list-group-item {
    position: relative;
    display: block;
    padding: .75rem 1.25rem;
    background-color: #fff;
    /* border: 1px solid rgba(0,0,0,.125); */
}
#card-list-zzy .list-group-item:hover {
    color: #38ACDF;
    background-color: #F8F9FA;
    /*  border: 1px solid rgba(0,0,0,.125); */
}
.category-item-action i {
    transition: transform .3s ease-out;
    display: inline-block;
    margin-left: .25rem;
}
card-categories-list-spcail > div:hover{
    color:#38ACDF;
    background-color: #F8F9FA;
}
.fa {
    font-size: 1rem;
    line-height: 1;
}
.category-count {
    font-size: .9rem;
    font-weight: initial;
    min-width: 1.3em;
    line-height: 1.3em;
    display: flex;
    align-items: center;
}
.collapse:not(.show) {
    display: none;
}
.collapsing {
  position: relative;
  height: 0;
  overflow: hidden;
  @include transition($transition-collapse);
}
#card-list-zzy{
    position: relative;
    /* margin-top: -2rem; */
    transition: background-color .2s ease-in-out;
    border-radius: .5rem;
    z-index: 3;
}
</style>
  <% function render_categories(cats, depth) { %>
  <% depth = depth || 0 %>
  <% return cats.each(function(cat){ %>
    <% var subCats = site.categories.find({parent: cat._id}).sort(orderBy).filter(cat => cat.length) %>
    <% var collapsed = subCats.length === 0 %>
    <div class="<%= depth <= 0 ? 'category' : 'category-sub' %> row">
      <a
        class="<%= depth <= 0 ? 'category-item' : 'category-subitem' %> <%= collapsed ? 'collapsed' : '' %> list-group-item category-item-action col-10 col-md-11"
        id="heading-<%= cat._id %>" role="tab" data-toggle="collapse"   data-target="#collapse-<%= cat._id %>"
        aria-expanded="<%= collapsed ? 'false' : 'true' %>"
      >
        <%= cat.name %>
        <i class="fas fa-chevron-right"></i>
      </a>
      <a href="<%= url_for(cat.path) %>" class="category-count col-2 col-md-1">
        <i class="fa fa-list"></i>
        <span><%= cat.posts.length %></span>
      </a>
      <div class="category-collapse">
        <% if (subCats.length > 0) { %>
          <%- render_sub_categories(subCats, cat, depth + 1) %>
        <% } else { %>
          <%- render_posts(cat) %>
        <% } %>
      </div>
    </div>
  <% }) %>
<% } %>
<% function render_sub_categories(cats, parent, depth) { %>
  <div id="collapse-<%= parent._id %>" class=" collapse in show" role="tabpanel"
       aria-labelledby="heading-<%= parent._id %>">
    <%- render_categories(cats, depth) %>
  </div>
<% } %>
<% function render_posts(cat) { %>
  <div id="collapse-<%= cat._id %>" class="collapse in" role="tabpanel"
       aria-labelledby="heading-<%= cat._id %>">
    <% var limit = 100 ; %>
    <% var posts = cat.posts.sort(config.index_generator.order_by || '-date') %>
    <% for (var idx = 0; idx < posts.length; idx++) { %>
      <% var post = posts.data[idx] %>
      <% if (idx && limit && idx >= limit) { %>
        <a href="<%- url_for(cat.path) %>" class="list-group-item list-group-item-action">
          <span class="category-post">More...</span>
        </a>
        <% break %>
      <% } else { %>
        <a href="<%- url_for(post.path) %>" class="list-group-item list-group-item-action">
          <span class="category-post"><%= post.title %></span>
        </a>
      <% } %>
    <% } %>
  </div>
<% } %>
<div class="container" data-aos="fade-up">
    <div class="card  card-categories-list-spcail">
        <div class="card-content col-12 col-md-10 m-auto ">
            <div  id="card-list-zzy" class="">
                <div class="category-list">
                  <% cats = site.categories.find({parent: {$exists: false}}).sort(orderBy).filter(cat => cat.length) %>
                  <%- render_categories(cats) %>
                </div>
            </div>
        </div>
    </div>
</div>
2、引入 category-list.ejs
找到主题目录下 /layout/categories.ejs , 添加以下代码:
<%- partial('_widget/category-list') %>加了之后,大概是这样子:
<%- partial('_partial/bg-cover') %>
<main class="content">
    <%- partial('_widget/category-cloud') %>
    <% if (site.categories && site.categories.length > 0) { %>
    <%- partial('_widget/category-radar') %>
    <% } %>
    <%- partial('_widget/category-list') %>
</main>3、使用
在文章的头部写 categories 多级的写法:
categories:
  - 收藏资源
  - 工具网站显示分级则依次从上到下。
最后启动看效果吧~
hexo clean
hexo g
hexo s好吧,如果你不是歌追求完美的人,现在其实已经可以使用了。
咳~ 咳~ 该说正事了
接下来跟我的提示去瞧瞧,看看你这个页面的 baner 上的子标题,是不是有像右点跑偏的一点, 再看看这个页面的 footer 是不是没有原来规整了?
其实是因为这个页面引入了 bootstrap.min.css 造成了。
因为 Materialize 和 bootstrap 存在冲突。
4、重头再来
经过六个小时的摸索, 查看 Materialize 的官网用法,搞个 Demo , 然后把刚才上面的代码重新修改调试, 达到了几本可以用, 且不再冲突,因为用的是 Materialize 的样式,好吧~ 不知不觉,又折腾了一遍 bootstrap 和 Materialize 。
新的 category-list.ejs 长这样:
<% var orderBy =  'name' ;  %>
<style>
/*
.category:not(:last-child) {
  margin-bottom: 1rem;
}
*/
.category-item {
  font-size: 1.25rem;
  font-weight: bold;
  display: flex;
  align-items: center;
}
.category-subitem {
  font-size: 1rem;
  font-weight: bold;
}
.category-collapse {
  margin-left: 1.25rem;
  width: 100%;
}
.category-count {
  font-size: 0.9rem;
  font-weight: initial;
  min-width: 1.3em;
  line-height: 1.3em;
  display: flex;
  align-items: center;
}
.category-count i {
  padding-right: 0.25rem;
}
.category-count span {
  width: 2rem;
}
.category-item-action:not(.collapsed) > i {
  transform: rotate(90deg);
  transform-origin: center center;
}
.category-item-action i {
  transition: transform 0.3s ease-out;
  display: inline-block;
  margin-left: 0.25rem;
}
.category-item-action:hover {
  z-index: 1;
  color: #38ACDF;
  text-decoration: none;
  background-color: #F8F9FA;
}
.list-group-item:first-child {
    border-top-left-radius: .25rem;
    border-top-right-radius: .25rem;
}
.category-item {
    font-size: 1.25rem;
    font-weight: 700;
    display: flex;
    align-items: center;
}
.list-group-item {
    background-color: transparent;
    border: 0;
}
.list-group-item {
    position: relative;
    display: block;
    padding: .75rem 1.25rem;
    background-color: #fff;
    /* border: 1px solid rgba(0,0,0,.125); */
}
#card-list-zzy .list-group-item:hover {
    color: #38ACDF;
    background-color: #F8F9FA;
    /*  border: 1px solid rgba(0,0,0,.125); */
}
/*
.category-item-action i {
    transition: transform .3s ease-out;
    display: inline-block;
    margin-left: .25rem;
}
*/
card-categories-list-spcail > div:hover{
  color:#38ACDF;
  background-color: #F8F9FA;
}
.fa {
    font-size: 1rem;
    line-height: 1;
}
.category-count {
    font-size: .9rem;
    font-weight: initial;
    min-width: 1.3em;
    line-height: 1.3em;
    display: flex;
    align-items: center;
}
.category-content{
   border-left:0px;
   padding: .75rem 1.25rem;
}
.category-content a{
    color: black;
}
.category-content a:hover{
    color:#38ACDF;
    background-color: #F8F9FA;
 }
.category-row {
  border-color: #F8F9FA;;
  border-bottom:none;
}
#card-list-zzy{
    position: relative;
    /* margin-top: -2rem; */
    transition: background-color .2s ease-in-out;
    border-radius: .5rem;
    z-index: 3;
}
.collapsible-header{
    boder: none;
}
</style>
  <% function render_categories(cats, depth) { %>
  <% depth = depth || 0 %>
  <% return cats.each(function(cat){ %>
    <% var subCats = site.categories.find({parent: cat._id}).sort(orderBy).filter(cat => cat.length) %>
    <% var collapsed = subCats.length === 0 %>
    <li  class="<%= subCats.length > 0 ? 'active' : '' %>" >
    <div class="<%= depth <= 0 ? 'category-row' : 'category-row category-sub' %>  row collapsible-header">
      <a
        class=" <%= depth <= 0 ? 'category-item' : 'category-subitem' %> <%= subCats.length > 0 ? '' : 'collapsed' %> list-group-item category-item-action col s10 m9"
        id="heading-<%= cat._id %>" 
      >
        <%= cat.name %>
        <i class="fas fa-chevron-right"></i>
      </a>
      <a href="<%= url_for(cat.path) %>" class="category-count col s2 m3">
        <i class="fa fa-list"></i>
        <span><%= cat.posts.length %></span>
      </a>
    </div>
        <% if (subCats.length > 0) { %>
      <div class="category-content collapsible-body">
          <%- render_sub_categories(subCats, cat, depth + 1) %>
       </div>
        <% } else { %>
          <%- render_posts(cat) %>
        <% } %>
    </li>
  <% }) %>
<% } %>
<% function render_sub_categories(cats, parent, depth) { %>
        <ul class="collapsible category-row"  data-collapsible="expandable">
            <%- render_categories(cats, depth) %>
         </ul>
<% } %>
<% function render_posts(cat) { %>
  <div id="collapse-<%= cat._id %>" class="category-content collapsible-body" >
    <% var limit = 20 ; %>
    <% var posts = cat.posts.sort(config.index_generator.order_by || '-date') %>
    <% for (var idx = 0; idx < posts.length; idx++) { %>
      <% var post = posts.data[idx] %>
      <% if (idx && limit && idx >= limit) { %>
        <a href="<%- url_for(cat.path) %>" class="list-group-item list-group-item-action">
          <span class="category-post">More...</span>
        </a>
        <% break %>
      <% } else { %>
        <a href="<%- url_for(post.path) %>" class=" list-group-item list-group-item-action">
          <span class="category-post"><%= post.title %></span>
        </a>
      <% } %>
    <% } %>
  </div>
<% } %>
<div class="container" data-aos="fade-up">
    <div class="card  card-categories-list-spcail">
        <div class="card-content col s12  m12">
         <div  id="card-list-zzy" class="container ">
        <ul class="category-list collapsible "  data-collapsible="expandable">
          <% cats = site.categories.find({parent: {$exists: false}}).sort(orderBy).filter(cat => cat.length) %>
          <%- render_categories(cats) %>
        </ul>
       </div>
      </div>
    </div>
</div>
<script>
  $('.list-group-item').click(function(){
  var id = $(this).attr('href');
  if($(this).hasClass('collapsed')){
    $(this).removeClass('collapsed');
    $(this).attr("aria-expanded",true);
  }else{
    $(this).addClass('collapsed');
    $(this).attr("aria-expanded",false);
  }
  var val = $(id).css('display');
  if(val == 'block'){
    //$(id).hide();
    //$(id).slideUp();
  }else{
    //$(id).show();
    //$(id).slideDown();
  }
});
$(document).ready(function(){
    $('.collapsible').collapsible();
  });
</script>5、重新编译启动
可能还有一些样式问题,不过要睡觉了。
就自己调调吧~ 尽量用内联样式
后面调好了,文章再更新。
6、重新更新一版
重新调整样式, 添加了标题, 去掉了调试 Demo , 理论上不限制级别深, 添加了自定义显示多少最近多少篇配置参数。
新的 category-list.ejs 长这样:
<% var orderBy =  'name' ;  %>
<style>
/*
.category:not(:last-child) {
  margin-bottom: 1rem;
}
*/
.category-item {
  font-size: 1.25rem;
  font-weight: bold;
  display: flex;
  align-items: center;
}
.category-subitem {
  font-size: 1rem;
  font-weight: bold;
}
.category-collapse {
  margin-left: 1.25rem;
  width: 100%;
}
.category-count {
  font-size: 0.9rem;
  font-weight: initial;
  min-width: 1.3em;
  line-height: 1.3em;
  display: flex;
  align-items: center;
}
.category-count i {
  padding-right: 0.25rem;
}
.category-count span {
  width: 2rem;
}
.category-item-action:not(.collapsed) > i {
  transform: rotate(90deg);
  transform-origin: center center;
}
.category-item-action i {
  transition: transform 0.3s ease-out;
  display: inline-block;
  margin-left: 0.25rem;
}
.category-item-action:hover {
  z-index: 1;
  color: #38ACDF;
  text-decoration: none;
  background-color: #F8F9FA;
}
.list-group-item:first-child {
    border-top-left-radius: .25rem;
    border-top-right-radius: .25rem;
}
.category-item {
    font-size: 1.25rem;
    font-weight: 700;
    display: flex;
    align-items: center;
}
.list-group-item {
    background-color: transparent;
    border: 0;
}
.list-group-item {
    position: relative;
    display: block;
    padding: .75rem 1.25rem;
    background-color: #fff;
    /* border: 1px solid rgba(0,0,0,.125); */
}
#card-list-zzy .list-group-item:hover {
    color: #38ACDF;
    background-color: #F8F9FA;
    /*  border: 1px solid rgba(0,0,0,.125); */
}
.category-item-action i {
    transition: transform .3s ease-out;
    display: inline-block;
    margin-left: .25rem;
}
.category-item-action a{
      display: block;
      padding: .75rem 1.25rem;
}
card-categories-list-spcail > div:hover{
  color:#38ACDF;
  background-color: #F8F9FA;
}
.fa {
    font-size: 1rem;
    line-height: 1;
}
.category-count {
    font-size: .9rem;
    font-weight: initial;
    min-width: 1.3em;
    line-height: 1.3em;
    display: flex;
    align-items: center;
}
.category-content{
   border-left:0px;
   padding: .75rem 1.25rem;
}
.category-content a{
    color: black;
}
.category-content a:hover{
    color:#38ACDF;
    background-color: #F8F9FA;
    box-shadow:none;
 }
.category-row {
  border-color: #F8F9FA;;
  border-bottom:none;
  box-shadow: none;
}
#card-list-zzy{
    position: relative;
    /* margin-top: -2rem; */
    transition: background-color .2s ease-in-out;
    border-radius: .5rem;
    z-index: 3;
}
.collapsible-header{
    boder: none;
}
.collapsible{
  box-shadow:none !important;
  -webkit-box-shadow: none !important;
  border-left:none !important;
  border-right:none !important;
  border-bottom:none !important;
}
.categories-title{
    padding-top: 20px;
    /* padding-bottom: 5px; */
    margin-bottom: -10px;
}
</style>
  <% function render_categories(cats, depth) { %>
  <% depth = depth || 0 %>
  <% return cats.each(function(cat){ %>
    <% var subCats = site.categories.find({parent: cat._id}).sort(orderBy).filter(cat => cat.length) %>
    <% var collapsed = subCats.length === 0 %>
    <li  class="<%= subCats.length > 0 ? 'active' : '' %>" >
    <div class="<%= depth <= 0 ? 'category-row' : 'category-row category-sub' %>  row collapsible-header">
      <a
        class=" <%= depth <= 0 ? 'category-item' : 'category-subitem' %> <%= subCats.length > 0 ? '' : 'collapsed' %> list-group-item category-item-action col s11 m11"
        id="heading-<%= cat._id %>" 
      >
        <%= cat.name %>
        <i class="fas fa-chevron-right"></i>
      </a>
      <a href="<%= url_for(cat.path) %>" class="category-count col s1 m1">
        <i class="fa fa-list"></i>
        <span><%= cat.posts.length %></span>
      </a>
    </div>
        <% if (subCats.length > 0) { %>
      <div class="category-content collapsible-body">
          <%- render_sub_categories(subCats, cat, depth + 1) %>
       </div>
        <% } else { %>
          <%- render_posts(cat) %>
        <% } %>
    </li>
  <% }) %>
<% } %>
<% function render_sub_categories(cats, parent, depth) { %>
        <ul class="collapsible expandable category-row"  data-collapsible="expandable">
            <%- render_categories(cats, depth) %>
         </ul>
<% } %>
<% function render_posts(cat) { %>
  <div id="collapse-<%= cat._id %>" class="category-content collapsible-body" >
    <% var limit = theme.category.list || 10 ; %>
    <% var posts = cat.posts.sort(config.index_generator.order_by || '-date') %>
    <% for (var idx = 0; idx < posts.length; idx++) { %>
      <% var post = posts.data[idx] %>
      <% if (idx && limit && idx >= limit) { %>
        <a href="<%- url_for(cat.path) %>" class="list-group-item list-group-item-action">
          <span class="category-post">More...</span>
        </a>
        <% break %>
      <% } else { %>
        <a href="<%- url_for(post.path) %>" class=" list-group-item list-group-item-action">
          <span class="category-post"><%= post.title %></span>
        </a>
      <% } %>
    <% } %>
  </div>
<% } %>
<div class="container" data-aos="fade-up">
    <div class="card  card-categories-list-spcail">
        <div class="categories-title center-align">
                <i class="fas fa-bookmark"></i>   文章多级分类
        </div>
        <div class="card-content col s12  m12">
         <div  id="card-list-zzy" class="container ">
        <ul class="category-list collapsible expandable"  data-collapsible="expandable">
          <% cats = site.categories.find({parent: {$exists: false}}).sort(orderBy).filter(cat => cat.length) %>
          <%- render_categories(cats) %>
        </ul>
       </div>
    </div>
</div>   
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.8/js/materialize.min.js"></script>
<script>
$('.list-group-item').click(function(){
  if($(this).hasClass('collapsed') ){
      $(this).removeClass('collapsed');
      //$(this).parent().next().slideDown();
  }else{
      $(this).addClass('collapsed');
      //$(this).parent().next().slideUp();
  }
});
var elem = document.querySelector('.collapsible .expandable');
var instance = M.Collapsible.init(elem, {
  accordion: false
});
</script>然后在主题配置中添加配置参数:
category:
  list: 10  该值表示多级分类展开时显示最近的10篇文章列表, 不设置默认会显示10篇,修改该值即可实现自定义设置显示多少条。
效果在我的分类里,自己看看吧~
category-list.ejs 中引入了另一个版本的js
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.8/js/materialize.min.js"></script>如果去掉了这个 js 引入, 那么需要放开 js 中注释了的 $(this).parent().next().slideDown(); 和 $(this).parent().next().slideUp(); , 然后将 <li class="<%= subCats.length > 0 ? 'active' : '' %>" > 修改成 <li> ,只是效果略显不同。 展开后不再自动折叠。 如果你愿意动手,自己加个按钮, 可以搞个全部展开的按钮, 事件的关键代码如下:
function openOrClose(){
    var disVal = $(".collapsible-body").css("display");
    disVal =='none' ? $(".collapsible-body").css("display","block"); :$(".collapsible-body").css("display","none");
}
先备份,然后大胆的折腾,大胆的改~
相关文章
- Hexo搭建静态博客(一)——基础搭建
 - Hexo搭建静态博客(二)——创建页面
 - Hexo搭建静态博客(三)——主题更换
 - Hexo搭建静态博客(四)——插件安装
 - Hexo搭建静态博客(五)——踩坑问题
 - Hexo搭建静态博客(六)——项目部署
 - Hexo搭建静态博客(七)——客服与推送
 - Hexo添加Live2D二次元老婆
 - Hexo博客Valine-Admin踩坑记录
 - Hexo博客Matery主题valine升级与优化
 - Hexo博客Matery主题新手常见问题
 - Hexo博客Matery主题添加多级分类
 - Hexo博客添加思维导图渲染
 - Hexo博客Matery主题添加说说Artitalk教程
 - 静态博客-字体更换教程
 




