首页 » 资讯中心 » 文档

ThinkTemplate 循环调用多级子栏目(顶级、二级、三级)

文档 作者:求元工坊 发布时间:2026-10-16 阅读:29

求元工坊CMS 通过 GlobalView 中间件将栏目树注入到所有前台模板,模板中直接使用 $navList 变量即可循环调用多级子栏目(顶级栏目下二级、三级...N级栏目)。

栏目树 | 多级子栏目循环调用

求元工坊CMS 的栏目数据以树形结构存储,子栏目存放在父级栏目的 children 键中,通过 volist 嵌套即可逐级展开。

一、栏目树数据结构

$navList 是一个多维数组,每个栏目包含以下字段:

字段说明
id栏目ID
name栏目名称
alias栏目别名(如 home/doc)
url栏目链接(已生成绝对地址)
cate_type栏目类型(1文章、5图片等)
children子栏目数组(无子栏目时为 null)

二、调用顶级(一级)栏目

2.1 基本写法

{volist name="navList" id="nav"}
  <li><a href="{$nav.url}">{$nav.name}</a></li>
{/volist}

注解:$navList 本身就是顶级栏目数组,直接 volist 遍历即可输出一级导航。

2.2 带当前栏目高亮

{volist name="navList" id="nav"}
  <li>
    <a href="{$nav.url}" {if condition="isset($current_cate_id) && $current_cate_id == $nav['id']"}class="active"{/if}>
      {$nav.name}
    </a>
  </li>
{/volist}

注解:通过 $current_cate_id(由控制器传入)判断当前栏目,添加 active 高亮样式。

三、循环调用二级子栏目

3.1 基本写法(volist 嵌套)

{volist name="navList" id="nav"}
  <li>
    <a href="{$nav.url}">{$nav.name}</a>
    
    <!-- 二级子栏目开始 -->
    {if condition="!empty($nav['children'])"}
    <ul class="sub-menu">
      {volist name="nav['children']" id="child"}
      <li><a href="{$child.url}">{$child.name}</a></li>
      {/volist}
    </ul>
    {/if}
    <!-- 二级子栏目结束 -->
  </li>
{/volist}

注解:外层 volist 遍历顶级栏目,内层 volist 遍历 $nav['children'] 输出二级子栏目。使用 !empty() 判断避免空数组报错。

3.2 简化写法(不判断空值)

{volist name="navList" id="nav"}
  <li>
    <a href="{$nav.url}">{$nav.name}</a>
    {volist name="nav['children']" id="child"}
    <ul>
      <li><a href="{$child.url}">{$child.name}</a></li>
    </ul>
    {/volist}
  </li>
{/volist}

注意:当 children 为 null 时,volist 不会执行循环体,但会输出空的 <ul> 标签。建议始终加上 !empty() 判断。

四、循环调用三级(及更多级)子栏目

4.1 三级栏目写法

{volist name="navList" id="nav"}
  <li>
    <a href="{$nav.url}">{$nav.name}</a>
    
    <!-- 二级子栏目开始 -->
    {if condition="!empty($nav['children'])"}
    <ul class="sub-menu">
      {volist name="nav['children']" id="child"}
      <li>
        <a href="{$child.url}">{$child.name}</a>
        
        <!-- 三级子栏目开始 -->
        {if condition="!empty($child['children'])"}
        <ul class="sub-sub-menu">
          {volist name="child['children']" id="grandchild"}
          <li><a href="{$grandchild.url}">{$grandchild.name}</a></li>
          {/volist}
        </ul>
        {/if}
        <!-- 三级子栏目结束 -->
      </li>
      {/volist}
    </ul>
    {/if}
    <!-- 二级子栏目结束 -->
  </li>
{/volist}

注解:三级栏目存放在二级栏目的 children 中,通过 $child['children'] 继续下钻。理论上支持无限级嵌套,但建议导航菜单最多展示三级。

五、实际应用场景

5.1 顶部导航菜单(带下拉)

<nav class="main-nav">
  <ul class="nav-list">
    {volist name="navList" id="nav"}
    <li class="nav-item {if condition="!empty($nav['children'])"}has-children{/if}">
      <a href="{$nav.url}">{$nav.name}</a>
      {if condition="!empty($nav['children'])"}
      <ul class="dropdown">
        {volist name="nav['children']" id="child"}
        <li><a href="{$child.url}">{$child.name}</a></li>
        {/volist}
      </ul>
      {/if}
    </li>
    {/volist}
  </ul>
</nav>

5.2 侧边栏栏目树

<aside class="sidebar">
  <div class="cate-tree">
    {volist name="navList" id="nav"}
    <div class="tree-node">
      <a href="{$nav.url}" class="node-link">{$nav.name}</a>
      {if condition="!empty($nav['children'])"}
      <div class="tree-children">
        {volist name="nav['children']" id="child"}
        <a href="{$child.url}" class="child-link">{$child.name}</a>
        {if condition="!empty($child['children'])"}
        <div class="tree-grandchildren">
          {volist name="child['children']" id="grandchild"}
          <a href="{$grandchild.url}" class="grandchild-link">{$grandchild.name}</a>
          {/volist}
        </div>
        {/if}
        {/volist}
      </div>
      {/if}
    </div>
    {/volist}
  </div>
</aside>

5.3 面包屑导航

<div class="breadcrumb">
  <a href="{$siteWww}/">首页</a>
  {if condition="isset($breadcrumb)"}
    {volist name="breadcrumb" id="crumb"}
      <span class="separator">&gt;</span>
      <a href="{$crumb.url}">{$crumb.name}</a>
    {/volist}
  {/if}
</div>

注解:面包屑数据由控制器传入,格式为 ['首页' => '/', '文档' => '/doc', 'ThinkTemplate' => '/doc/thinktemplate']。

六、注意事项

  1. 始终判断 children 是否为空:使用 !empty($item['children']) 判断,避免输出空的 <ul> 标签或报错。
  2. 字段访问使用数组下标:在 volist 嵌套中,子栏目字段使用 {$child['name']} 而非 {$child.name}。
  3. url 字段已生成绝对地址:GlobalView 中间件已处理 url 字段,直接输出即可,无需再调用 site_url()。
  4. 层级变量命名建议:一级用 nav、二级用 child、三级用 grandchild,避免命名冲突。
  5. 建议最多展示三级:导航菜单层级过深会影响用户体验,建议超过三级的栏目通过列表页展示。

七、与 XYHCMS 的对比

特性求元工坊CMSXYHCMS
栏目标签全局变量 $navList自定义标签 <yang:catlist>
子栏目字段childrenchild
循环标签{volist}<volist> 或 <foreach>
URL 获取直接输出 {$nav.url}需过滤器 {$v|get_url}
无限级支持理论上支持需手动嵌套

本文档适用于求元工坊CMS v1.0 及以上版本。更多模板语法请参考 ThinkTemplate SSR 数据渲染指南、模板算术运算符使用指南 和 模板条件判断语句(if 标签)。