核心思路
DedeCMS 的栏目调用标签 {dede:channel} 有一个非常重要的属性:son 或 type。

(图片来源网络,侵删)
{dede:channel 'top'}: 调用顶级栏目(一级栏目)。{dede:channel 'son'}: 调用指定栏目的直接子栏目(二级栏目)。{dede:channel}: 在栏目页,调用当前栏目的子栏目;在首页,调用顶级栏目。
通过组合使用这些属性,我们就可以构建出三级栏目的嵌套结构。
最常用和简洁的嵌套循环法
这是最直接、最容易理解的方法,适用于大多数场景。
适用场景
- 首页调用所有一级栏目及其下的二级、三级栏目。
- 在某个一级栏目页,调用其下的所有二级和三级栏目。
代码示例
假设我们要在首页展示一个完整的三级栏目导航。
<ul class="nav-main">
{dede:channel type='top' row='8'}
<!-- 循环调用一级栏目 -->
<li class="nav-item">
<a href="[field:typelink/]]" title="[field:typename/]]" class="nav-link">
[field:typename/]
</a>
<!-- 开始调用当前一级栏目下的二级栏目 -->
<ul class="nav-sub">
{dede:channel type='son' noself='yes'}
<!-- 循环调用二级栏目 -->
<li class="nav-sub-item">
<a href="[field:typelink/]" title="[field:typename/]">
[field:typename/]
</a>
<!-- 开始调用当前二级栏目下的三级栏目 -->
<ul class="nav-third">
{dede:channel type='son' noself='yes'}
<li class="nav-third-item">
<a href="[field:typelink/]" title="[field:typename/]">
[field:typename/]
</a>
</li>
{/dede:channel}
</ul>
</li>
{/dede:channel}
</ul>
</li>
{/dede:channel}
</ul>
代码解释
-
第一层
{dede:channel type='top'}:
(图片来源网络,侵删)type='top'告诉 DedeCMS 调用所有顶级栏目(一级栏目)。row='8'限制只显示8个一级栏目,防止过多。- 这个循环会生成所有的
<li class="nav-item">。
-
第二层
{dede:channel type='son'}:- 关键点:这个标签被放在了第一层循环的内部,它不再是调用所有顶级栏目的子栏目,而是循环调用当前正在被处理的一级栏目的子栏目(即二级栏目)。
noself='yes'表示不调用栏目本身,只调用其子栏目,这是一个好习惯。
-
第三层
{dede:channel type='son'}:- 同样,这个标签位于第二层循环的内部,所以它会循环调用当前正在被处理的二级栏目的子栏目(即三级栏目)。
noself='yes'同样适用。
使用 reid 属性(更灵活)
如果你的栏目结构比较复杂,或者你只想在特定的栏目下调用子栏目,使用 reid 属性会更清晰。
适用场景
- 当你明确知道要调用的父栏目的ID时。
- 在非顶级栏目页(如二级栏目页)调用其子栏目。
代码示例
假设你知道“产品中心”这个一级栏目的ID是 2。

(图片来源网络,侵删)
<!-- 调用ID为2的栏目(一级栏目)下的所有二级和三级栏目 -->
<div class="product-nav">
<h3>产品中心</h3>
<ul>
<!-- 第一层:调用ID为2的栏目下的所有子栏目(二级栏目) -->
{dede:channel reid='2' type='son' row='10'}
<li>
<a href="[field:typelink/]">[field:typename/]</a>
<!-- 第二层:调用当前二级栏目下的子栏目(三级栏目) -->
<ul>
{dede:channel reid='self' type='son' noself='yes'}
<li><a href="[field:typelink/]">[field:typename/]</a></li>
{/dede:channel}
</ul>
</li>
{/dede:channel}
</ul>
</div>
代码解释
-
reid='2':- 这个属性指定了父栏目的ID。
{dede:channel reid='2'}会调用ID为2的栏目的所有直接子栏目。 - 这比嵌套循环更明确,代码可读性更高。
- 这个属性指定了父栏目的ID。
-
reid='self':- 这是一个非常实用的技巧,在第二层循环中,
reid='self'表示“调用当前循环项(即二级栏目)的子栏目”。 - 这样就实现了动态地获取每个二级栏目对应的三级栏目,无需手动为每个二级栏目指定ID。
- 这是一个非常实用的技巧,在第二层循环中,
在栏目页调用当前栏目的三级栏目
这是一个非常常见的场景:进入一个一级栏目页,页面左侧或上方显示该一级栏目下的所有二级栏目,每个二级栏目再展开显示其下的三级栏目。
代码示例
在你的 /templets/default/plus/list_channel.htm 或自定义的栏目模板文件中。
<div class="sidebar">
<!-- 调用当前栏目(一级栏目)下的所有二级栏目 -->
<h3>栏目导航</h3>
<ul class="channel-list">
{dede:channel type='son' noself='yes'}
<li>
<a href="[field:typelink/]">[field:typename/]</a>
<!-- 调用当前二级栏目下的三级栏目 -->
<ul class="sub-channel-list">
{dede:channel type='son' reid='self' noself='yes'}
<li><a href="[field:typelink/]">[field:typename/]</a></li>
{/dede:channel}
</ul>
</li>
{/dede:channel}
</ul>
</div>
代码解释
-
第一层
{dede:channel type='son'}:- 因为这个代码位于一个一级栏目的模板文件中,
type='son'会自动调用当前栏目的所有子栏目(即二级栏目)。
- 因为这个代码位于一个一级栏目的模板文件中,
-
第二层
{dede:channel type='son' reid='self'}:- 同样,这个标签在二级栏目循环内部,
type='son'会调用当前二级栏目的子栏目(三级栏目),使用reid='self'是为了代码的清晰和健壮性。
- 同样,这个标签在二级栏目循环内部,
重要注意事项
-
栏目结构:
确保你的后台栏目结构是标准的“父-子”关系,三级栏目必须隶属于一个二级栏目,二级栏目必须隶属于一个一级栏目,如果不是,调用将无法正常工作。
-
typeid和reid的区别:typeid: 指定调用当前栏目,通常在列表页或内容页使用。reid: 指定调用指定ID的栏目的子栏目,通常在首页或其他固定页面使用,用于精确控制。
-
CSS 样式:
- 嵌套的HTML结构需要配合CSS样式才能正确显示(多级菜单的缩进、悬浮下拉等),上面的代码中我加入了
class名称,你可以方便地用CSS来美化它们。
- 嵌套的HTML结构需要配合CSS样式才能正确显示(多级菜单的缩进、悬浮下拉等),上面的代码中我加入了
-
性能考虑:
对于栏目数量非常多的网站,过多的嵌套循环可能会对页面加载速度产生轻微影响,但对于绝大多数中小型网站,这种影响可以忽略不计。
-
typeid在首页的使用:- 如果你想在首页调用某个特定一级栏目(ID为5)下的三级栏目,可以这样写:
{dede:channel typeid='5' type='son'} <!-- 这会调用ID为5的栏目的二级栏目 --> {dede:channel type='son' reid='self'} <!-- 这会调用上面二级栏目的三级栏目 --> {/dede:channel} {/dede:channel}但更推荐使用 方法二 的
reid属性,因为它逻辑更清晰。
- 如果你想在首页调用某个特定一级栏目(ID为5)下的三级栏目,可以这样写:
希望这些详细的解释和示例能帮助你成功实现三级栏目的嵌套调用!
