使用系统内置标签(最简单、最常用)
DedeCMS提供了 {dede:channel} 标签,专门用于栏目列表的调用,通过设置其属性,可以轻松实现调用当前栏目的子栏目。

(图片来源网络,侵删)
核心标签:{dede:channel}
关键属性:
typeid='当前栏目ID': 指定要从哪个栏目开始调用其子栏目,通常这里填写{dede:field.id/}来获取当前页面的栏目ID。type='son': 这是最关键的一个属性,表示调用typeid指定栏目的直接子栏目。row='数字': 设置要显示的子栏目数量,row='10'显示10个子栏目,不设置则显示所有。col='数字': 设置每行显示几列,col='2'会将子栏目分成两列显示,通常与row配合使用。currentstyle='当前栏目样式': 为当前所在的栏目(高亮栏目)设置一个特殊的HTML样式。currentstyle='<li class="on"><a href=~typelink~>~typename~</a></li>'。
示例1:调用当前栏目的所有直接子栏目(无序列表)
这是最基础、最常用的场景,假设你的左侧菜单是一个无序列表 <ul>。
在模板文件中(如 index.htm 或 article_list.htm)的侧边栏位置加入以下代码:
<h3>子栏目列表</h3>
<ul>
{dede:channel type='son' typeid='~typeid~'}
<li>
<a href="[field:typelink/]">[field:typename/]</a>
</li>
{/dede:channel}
</ul>
代码解释:
{dede:channel type='son' typeid='~typeid~'}:type='son': 告诉DedeCMS,我需要的是子栏目。typeid='~typeid~': 这是一个动态写法,~typeid~会被解析为当前页面的栏目ID,你也可以直接写死ID,如typeid='5',表示调用ID为5的栏目的子栏目。
[field:typelink/]: 输出栏目的链接地址。[field:typename/]: 输出栏目的名称。
示例2:为当前栏目添加高亮样式
为了让用户知道自己当前在哪个栏目下,通常需要高亮显示它,这时就需要用到 currentstyle 属性。

(图片来源网络,侵删)
<h3>子栏目列表</h3>
<ul>
{dede:channel type='son' typeid='~typeid~' currentstyle="<li class='current'><a href='~typelink~'>~typename~</a></li>"}
<li>
<a href="[field:typelink/]">[field:typename/]</a>
</li>
{/dede:channel}
</ul>
代码解释:
currentstyle="<li class='current'><a href='~typelink~'>~typename~</a></li>":{dede:channel}循环到的这个栏目正好是当前栏目,那么它就不会使用默认的<li>模板,而是使用currentstyle中定义的模板。~typelink~和~typename~是currentstyle中专用的变量,代表当前栏目的链接和名称。
CSS样式(供参考):
ul li a { display: block; padding: 5px 10px; text-decoration: none; }
ul li.current a { background-color: #f00; color: #fff; font-weight: bold; }
使用自定义SQL查询(更灵活)
当系统自带的标签无法满足你的需求时(你需要调用子栏目的文章数,或者按特定条件筛选子栏目),你可以使用自定义SQL。
核心标签:{dede:sql}
思路:
- 获取当前栏目的ID。
- 在
dede_arctype表中查询所有topid等于当前栏目ID的记录。 - 循环输出结果。
示例:调用当前栏目的子栏目,并显示每个子栏目的文章数
这个功能是 {dede:channel} 标签本身不支持的,所以非常适合用SQL来实现。

(图片来源网络,侵删)
在模板文件中加入以下代码:
<h3>子栏目列表 (含文章数)</h3>
<ul>
{dede:sql sql="SELECT id, typename, ispart, defaultname, addtable FROM `dede_arctype` WHERE topid=~typeid~ ORDER BY sortrank"}
<li>
<a href="[field:typedir function='str_replace("{cmspath}","",$value)'/]">[field:typename/]</a>
<!-- 如果是外部链接,则显示链接,否则显示栏目主页链接 -->
[field:ispart runphp='yes']
if(@me == 1) {
@me = " <a href='[field:defaultname/]' target='_blank'>»</a>";
} else {
@me = " <a href='[field:typedir function='str_replace("{cmspath}","",$value)'/]' target='_blank'>»</a>";
}
[/field:ispart]
<!-- 调用子栏目下的文章数 -->
(共 <a href="[field:typedir function='str_replace("{cmspath}","",$value)'/]">~[field:id function="GetTotalArc(@me)"/]~</a> 篇)
</li>
{/dede:sql}
</ul>
代码解释:
{dede:sql sql="..."}: 执行自定义的SQL查询语句。SELECT id, typename, ispart, defaultname, addtable FROM dede_arctype WHERE topid=~typeid~ ORDER BY sortrank:- 从
dede_arctype(栏目表) 中查询字段。 WHERE topid=~typeid~:topid字段存储的是栏目的父级ID。~typeid~同样会被替换为当前栏目ID,这样就实现了查找子栏目的目的。ORDER BY sortrank: 按后台设置的排序方式进行排序。
- 从
[field:typename/]: 输出栏目名。[field:typedir function='str_replace("{cmspath}","",$value)'/]: 这是一个非常重要的处理。typedir字段默认包含{cmspath}(网站根目录),我们需要将它替换掉,才能得到正确的绝对路径。[field:ispart runphp='yes']...[/field:ispart]:ispart字段判断是否为外部链接,如果是(值为1),则使用defaultname(外部链接地址);如果不是,则使用栏目主页地址。~[field:id function="GetTotalArc(@me)"/]~: 这是调用DedeCMS内置函数GetTotalArc()来统计某个ID下的文章总数。 是{dede:sql}标签中执行函数的语法。
总结与对比
| 特性 | {dede:channel} |
{dede:sql} |
|---|---|---|
| 易用性 | 非常高,标签化,无需写SQL。 | 较低,需要了解SQL语句和表结构。 |
| 灵活性 | 较低,功能固定,只能调用基本信息。 | 非常高,可以自由组合字段,实现复杂逻辑。 |
| 性能 | 优,系统已做优化。 | 良好,但需注意SQL查询效率,避免复杂查询。 |
| 适用场景 | 99%的常规子栏目调用需求。 | 需要调用附加信息(如文章数、简介)、条件筛选、跨表查询等复杂场景。 |
给你的建议:
- 如果只是简单地显示一个子栏目导航列表,请务必使用方法一 (
{dede:channel}),它更简单、更安全、也更符合DedeCMS的设计规范。 - 如果需要在子栏目列表中显示文章数、是否为外部链接、栏目简介等额外信息,或者有其他特殊要求,那么方法二 (
{dede:sql}) 是你的不二之选。
希望这份详细的教程能帮助你解决问题!
