在现代网站设计中,清晰、直观的导航系统不仅能极大提升用户体验,更是搜索引擎优化(SEO)不可或缺的一环。多级分类菜单,特别是三级嵌套菜单,能够有效地组织大量内容,让用户快速定位所需信息,同时也帮助搜索引擎理解网站的层级结构。作为一位资深的网站运营专家,我很清楚在AnQiCMS(安企CMS)中实现这样的功能既简单又高效。AnQiCMS凭借其灵活的模板引擎和强大的标签系统,让网站内容的展示变得游刃有余。

今天,我们就来深入探讨如何在AnQiCMS模板中巧妙地实现多级分类的嵌套显示,以三级菜单为例,助您打造结构完善、用户友好的网站导航。

理解AnQiCMS的多级分类机制

AnQiCMS在内容组织上提供了强大的分类管理功能。每个文档或产品都必须归属于一个分类,而这些分类本身又可以建立父子关系,形成层级结构。这种层级关系是实现多级菜单的基础。

在AnQiCMS的后台管理界面,您可以通过“内容管理” -> “文档分类”来创建和管理这些分类。在创建或编辑分类时,您可以指定其所属的“文档模型”(例如文章模型或产品模型),并选择其“上级分类”。当一个分类的上级分类被指定后,它就自然成为一个子分类。如果选择“顶级分类”,则该分类处于最上层。

理解 moduleIdparentId 这两个核心概念至关重要:

  • moduleId:指明了分类属于哪种内容模型(如文章模型ID为1,产品模型ID为2等)。在AnQiCMS中,不同内容模型的分类是相互独立的。
  • parentId:定义了分类的父级,parentId="0"通常表示顶级分类。当我们获取子分类时,就需要将 parentId 设置为其父分类的 Id

掌握关键模板标签:categoryList

要实现多级分类的嵌套显示,AnQiCMS提供了一个功能强大的模板标签:categoryList。这个标签能够帮助我们获取指定条件下的分类列表,并支持灵活的参数配置。

categoryList 标签的基本用法是:{% categoryList 变量名称 with moduleId="1" parentId="0" %}...{% endcategoryList %}。 其中:

  • 变量名称:用于接收返回的分类列表数据,例如 categoriessubCategories
  • moduleId:指定要获取哪个内容模型下的分类。
  • parentId:指定要获取哪个父分类下的子分类。将其设置为 "0" 将获取所有顶级分类。
  • for 循环遍历 categoryList 返回的每个分类项(item)时,我们可以访问以下关键属性:
    • item.Id:分类的唯一标识ID。
    • item.Title:分类的名称。
    • item.Link:分类的链接地址。
    • item.HasChildren:一个布尔值,指示当前分类是否包含子分类。这对于判断是否需要继续渲染下一级菜单非常有用。

掌握了 categoryList 标签及其参数,我们就可以着手构建多级嵌套菜单了。

编写模板代码:实现三级嵌套菜单

在AnQiCMS的模板文件中(通常位于template/您的模板名称/目录下),您可以利用 categoryList 标签的嵌套能力来构建三级菜单。下面是一个实现三级菜单的示例代码结构,您可以将其放置在网站的公共头部(如partial/header.html),或者任何需要展示菜单的地方。

{# 外层 ul 标签,承载整个菜单结构 #}
<ul class="main-menu">
    {# 获取顶级(一级)分类列表,假设我们获取文章模型(moduleId="1")下的顶级分类 #}
    {% categoryList categories with moduleId="1" parentId="0" %}
        {# 循环遍历每一个顶级分类 #}
        {% for item in categories %}
            {# 一级菜单项 #}
            <li class="menu-item {% if item.IsCurrent %}active{% endif %} {% if item.HasChildren %}has-submenu{% endif %}">
                <a href="{{ item.Link }}">{{ item.Title }}</a>
                {# 判断当前一级分类是否有子分类,如果有,则继续渲染二级菜单 #}
                {% if item.HasChildren %}
                    <ul class="submenu level-2">
                        {# 获取当前一级分类 (item.Id) 下的所有二级分类 #}
                        {% categoryList subCategories with parentId=item.Id %}
                            {# 循环遍历每一个二级分类 #}
                            {% for inner1 in subCategories %}
                                {# 二级菜单项 #}
                                <li class="menu-item {% if inner1.IsCurrent %}active{% endif %} {% if inner1.HasChildren %}has-submenu{% endif %}">
                                    <a href="{{ inner1.Link }}">{{ inner1.Title }}</a>
                                    {# 判断当前二级分类 (inner1.Id) 是否有子分类,如果有,则继续渲染三级菜单 #}
                                    {% if inner1.HasChildren %}
                                        <ul class="submenu level-3">
                                            {# 获取当前二级分类 (inner1.Id) 下的所有三级分类 #}
                                            {% categoryList subCategories2 with parentId=inner1.Id %}
                                                {# 循环遍历每一个三级分类 #}
                                                {% for inner2 in subCategories2 %}
                                                    {# 三级菜单项 #}
                                                    <li class="menu-item {% if inner2.IsCurrent %}active{% endif %}">
                                                        <a href="{{ inner2.Link }}">{{ inner2.Title }}</a>
                                                    </li>
                                                {% endfor %}
                                            {% endcategoryList %}
                                        </ul>
                                    {% endif %}
                                </li>
                            {% endfor %}
                        {% endcategoryList %}
                    </ul>
                {% endif %}
            </li>
        {% endfor %}
    {% endcategoryList %}
</ul>

这段代码的核心在于 categoryList 标签的层层嵌套。

  1. 第一层循环:外层的 {% categoryList categories with moduleId="1" parentId="0" %} 获取所有顶级分类(一级菜单)。
  2. 第二层循环:在每个一级菜单项内部,我们再次使用 {% categoryList subCategories with parentId=item.Id %} 获取当前一级分类 (item.Id) 下的所有子分类,这构成了二级菜单。
  3. 第三层循环:同样地,在每个二级菜单项内部,我们继续使用 {% categoryList subCategories2 with parentId=inner1.Id %} 获取当前二级分类 (inner1.Id) 下的所有子分类,从而实现了三级菜单。

每个层级都通过 {% if item.HasChildren %}{% if inner1.HasChildren %} 来判断是否需要渲染下一级子菜单,这样可以避免生成空的 <ul> 标签,保持HTML结构的整洁。同时,item.IsCurrent 属性可以帮助您判断当前分类是否为用户正在访问的页面,方便您添加 active 类来高亮显示。

请记住,上述代码只是HTML结构,您还需要配合CSS来美化菜单的样式,例如设置悬浮显示子菜单、调整颜色、字体大小等。

优化与注意事项

实现多级菜单并非仅仅是代码层面的工作,还需要考虑一些优化和运营上的细节:

  1. 性能考量:虽然AnQiCMS基于Go语言开发,性能卓越,但过于深层或庞大的菜单结构仍然可能增加数据库查询和页面渲染的负担。在设计分类时,应尽量保持合理的层级深度和分类数量。对于非必要在首屏加载的子菜单,可以考虑使用JavaScript进行懒加载或按需加载。
  2. 用户体验(UX)
    • 响应式设计:确保您的多级菜单在不同设备(PC、平板、手机)上都能良好显示和操作。在移动端,通常会采用汉堡菜单或手风琴式菜单来处理多级导航。
    • 视觉反馈:通过不同的颜色、图标或动画效果,清晰地指示用户当前所处的菜单层级,以及哪些菜单项包含子菜单。
    • 可访问性:确保菜单对所有用户,包括使用屏幕阅读器的用户,都是可访问的。使用语义化的HTML标签(nav, ul, li, a)非常重要。
  3. SEO友好
    • 清晰的URL结构:AnQiCMS支持自定义伪静态规则,这有助于生成清晰、有意义的URL,例如 /category/level1/level2/level3/article-title.html
    • 内部链接:多级菜单自然形成了强大的内部链接结构,这有助于搜索引擎爬虫发现和索引您网站的深层页面,传递页面权重。 *