使用 {dede:channelartlist} 标签(最推荐、最灵活)
这是织梦官方推荐的处理栏目及其子栏目的方式,它专门用于循环一级栏目,并在每个一级栏目下循环其子栏目,要获取第一个子栏目,我们只需要在子栏目的循环中取第一个即可。

(图片来源网络,侵删)
适用场景:当你的主导航栏有多个一级栏目,并且每个一级栏目下都有子栏目,你只想在每个一级栏目下显示其第一个子栏目作为链接。
代码示例:
{dede:channelartlist typeid='0' row='8'}
<li>
<!-- 这部分是显示一级栏目本身 -->
<a href="{dede:field name='typeurl'/}">{dede:field name='typename'/}</a>
<!-- 这部分是显示第一个子栏目 -->
<ul>
{dede:channel type='son' noself='yes'}
<!-- 这里的 runphp='yes' 是关键,我们用它来判断是否是第一个 -->
[field:typename runphp='yes']
$GLOBALS['firstson'] = ($GLOBALS['firstson'] + 1);
if ($GLOBALS['firstson'] == 1) {
// 如果是第一个,则输出完整的 <li> 标签和内容
@me = "<li><a href='{@me}'>".@me."</a></li>";
} else {
// 如果不是第一个,则输出空字符串,实现只显示第一个的效果
@me = "";
}
[/field:typename]
{/dede:channel}
</ul>
</li>
{/dede:channelartlist}
代码解析:
{dede:channelartlist typeid='0' row='8'}:typeid='0': 表示调用所有顶级栏目。row='8': 表示调用8个顶级栏目。
{dede:field name='typeurl'/}和{dede:field name='typename'/}: 分别获取当前一级栏目的链接和名称。{dede:channel type='son' noself='yes'}:type='son': 指定调用当前一级栏目的所有子栏目。noself='yes': 不显示栏目本身。
[field:typename runphp='yes']...[/field:typename]:runphp='yes': 启用PHP代码执行。$GLOBALS['firstson'] = ($GLOBALS['firstson'] + 1);: 我们使用一个全局变量$GLOBALS['firstson']来计数,每次循环一个子栏目,它就加1。if ($GLOBALS['firstson'] == 1): 判断计数器是否为1,也就是是否是第一个子栏目。@me = "...";: 如果是第一个,就把完整的HTML代码(<li><a href='{field:typeurl}'>{field:typename}</a></li>)赋值给当前字段,注意,这里需要把field:typeurl和field:typename也用 包起来,或者直接用@me来获取子栏目的URL和名称(在runphp中,@me代表当前字段的原始值,即子栏目名称,但URL需要用{@me}这种方式获取,更稳妥的做法是直接用{field:typeurl}和{field:typename}在模板里,但这里为了逻辑判断,我们把HTML也放在了PHP代码里)。@me = "";: 如果不是第一个,就清空输出。
使用 {dede:sql} 标签(直接数据库查询,最直接)
如果你只需要调用一个特定父栏目的第一个子栏目,或者不希望使用复杂的嵌套循环,直接用SQL查询数据库会非常高效。

(图片来源网络,侵删)
适用场景:调用某个固定父栏目(比如ID为1的栏目)下的第一个子栏目。
代码示例:
{dede:sql sql='SELECT id,typename,typedir FROM dede_arctype WHERE reid = 1 AND ishidden = 0 ORDER BY id ASC LIMIT 1'}
<a href="[field:typedir function='str_replace("{cmspath}","",$url)'/]">[field:typename/]</a>
{/dede:sql}
代码解析:
{dede:sql sql='...'}: 执行自定义的SQL语句。SELECT id,typename,typedir FROM dede_arctype: 从dede_arctype表(织梦的栏目表)中选择需要的字段。WHERE reid = 1: 这是关键。reid字段表示“父栏目ID”。reid = 1就表示查询父栏目ID为1的所有子栏目。你需要把1替换成你自己的父栏目ID。AND ishidden = 0: 排除隐藏的栏目。ORDER BY id ASC LIMIT 1:ORDER BY id ASC按栏目ID升序排列,LIMIT 1只取第一条记录,也就是第一个子栏目。[field:typedir ...]和[field:typename/]: 输出查询结果中的栏目链接和名称。function='str_replace("{cmspath}","",$url)': 这是一个常用的处理函数,用于去除typedir字段中默认包含的{cmspath}标签,得到完整的URL路径。
使用 {dede:channel} 标签配合 limit 属性(最简洁)
如果你只是想调用顶级栏目下的第一个子栏目,并且不考虑复杂的嵌套,这个方法最简单。
适用场景:调用顶级栏目(reid=0)下的第一个子栏目。
代码示例:
{dede:channel type='son' reid='0' row='1'}
<a href="[field:typelink/]">[field:typename/]</a>
{/dede:channel}
代码解析:
{dede:channel type='son' reid='0' row='1'}:type='son': 调用子栏目。reid='0': 指定父栏目ID为0,即顶级栏目。row='1': 只调用1条记录,也就是第一个子栏目(织梦默认按栏目ID排序)。
[field:typelink/]: 输出栏目的完整链接。[field:typename/]: 输出栏目的名称。
总结与选择建议
| 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
方法一: channelartlist |
最灵活,能循环所有一级栏目并分别获取其第一个子栏目,逻辑清晰。 | 代码稍复杂,需要理解 runphp 和全局变量的用法。 |
网站主导航栏,每个一级栏目下显示一个“热门子栏目”或“子栏目入口”。 |
方法二: sql |
最直接、性能最高,可以精确控制查询条件。 | 需要了解数据库表结构,硬编码了父栏目ID,不够灵活。 | 调用某个特定栏目下的第一个子栏目,比如侧边栏的“产品分类”下的第一个产品类别。 |
方法三: channel |
最简洁,代码量最少。 | 功能有限,只能调用顶级栏目下的第一个,无法处理嵌套结构。 | 简单的场景,比如页脚或某个模块中只显示一个顶级子栏目链接。 |
对于绝大多数“首页主导航”的需求,强烈推荐使用方法一 ({dede:channelartlist}),因为它最符合织梦的设计逻辑,也最易于维护和扩展。
