核心思路
无论使用哪种方法,核心思路都是一样的:

(图片来源网络,侵删)
- 找到二级栏目:首先获取到当前栏目的所有二级子栏目。
- 遍历二级栏目:对每一个二级栏目,再获取其所有的三级子栏目。
- 调用三级栏目下的文章:对每一个三级栏目,使用
{dede:arclist}标签来调用该栏目下的文章。
最常用和推荐的嵌套循环法
这种方法最灵活,可以完全自定义输出样式,并且性能较好,它通过 {dede:channel} 和 {dede:arclist} 标签的嵌套来实现。
场景假设
我们的栏目结构如下:
- 一级栏目:网站首页
- 二级栏目:新闻中心
- 三级栏目:公司新闻
- 三级栏目:行业动态
- 三级栏目:媒体报道
- 二级栏目:产品中心
- 三级栏目:产品A
- 三级栏目:产品B
我们想在“新闻中心”这个二级栏目页面上,分别列出“公司新闻”、“行业动态”和“媒体报道”这三个三级栏目下的文章。
实现代码
将以下代码放置在你想显示的模板文件中(news_list.htm)。
<h2>新闻中心</h2>
{dede:channel type='son' currentstyle=''}
<h3><a href='[field:typeurl/]'>[field:typename/]</a></h3>
<ul>
{dede:arclist titlelen='40' row='5'}
<li>
<a href="[field:arcurl/]">[field:title/]</a>
<span>[field:pubdate function="MyDate('Y-m-d',@me)"/]</span>
</li>
{/dede:arclist}
</ul>
{/dede:channel}
代码详解
-
外层循环:
{dede:channel type='son' ...}type='son':这是关键参数,表示调用当前栏目的直接子栏目,如果把这个标签放在“新闻中心”栏目页,它就会循环出“公司新闻”、“行业动态”、“媒体报道”这三个三级栏目。currentstyle='':这里我们留空,因为我们不希望当前栏目有特殊样式,而是直接进入循环。[field:typeurl/]:获取该三级栏目的链接地址。[field:typename/]:获取该三级栏目的名称。
-
内层循环:
{dede:arclist ...}- 这个标签被放在了
{dede:channel}循环的内部,这意味着,它会为每一个三级栏目执行一次。 titlelen='40'长度,限制为40个字符。row='5':每个三级栏目下调用5篇文章。[field:arcurl/]:文章链接。[field:title/]。[field:pubdate ...]:文章发布日期,并用自定义函数MyDate格式化为年-月-日。
- 这个标签被放在了
最终效果: 页面会依次显示“公司新闻”下的5篇文章,然后是“行业动态”下的5篇,最后是“媒体报道”下的5篇。
使用 dede:channelartlist 高级方法
{dede:channelartlist} 是一个更强大的标签,通常用于制作首页或频道页,它可以一次性获取指定层级的所有栏目及其内容,但对于三级栏目,用法上需要一些变通。
实现代码
{dede:channelartlist typeid='2'}
{dede:channel type='son' noself='yes'}
<h3><a href='[field:typeurl/]'>[field:typename/]</a></h3>
<ul>
{dede:arclist titlelen='40' row='5' channelid='[field:id/]'}
<li>
<a href="[field:arcurl/]">[field:title/]</a>
</li>
{/dede:arclist}
</ul>
{/dede:channel}
{/dede:channelartlist}
代码详解
-
外层:
{dede:channelartlist typeid='2'}typeid='2':这里指定要操作的二级栏目的ID,你需要将2替换成你自己的“新闻中心”栏目的ID,这个标签会获取ID为2的栏目及其所有子栏目(即三级栏目)。
-
中间层:
{dede:channel type='son' noself='yes'}- 在
channelartlist内部,这个channel标签会循环channelartlist指定的栏目的所有子栏目,也就是我们的三级栏目。 noself='yes':排除当前栏目本身(虽然在这里作用不大,但是个好习惯)。
- 在
-
内层:
{dede:arclist ...}channelid='[field:id/]':这个参数是关键!它显式地告诉arclist标签,要调用[field:id/](即当前正在循环的三级栏目)下的文章,如果不加这个,arclist可能会调用错误栏目下的内容。
这种方法比第一种更直接,但需要明确指定二级栏目的ID,灵活性稍差。
通过SQL直接查询(最灵活,但需谨慎)
如果你对PHP和SQL有一定了解,并且需求非常复杂(例如需要跨栏目、按特定条件筛选),可以直接使用SQL查询。
实现代码
{dede:sql sql='
SELECT
c.id, c.typename, c.typeurl,
a.id as aid, a.title, a.pubdate, a.arcurl
FROM
`dede_arctype` c
LEFT JOIN
`dede_archives` a ON c.id = a.typeid
WHERE
c.reid IN (SELECT id FROM dede_arctype WHERE reid = 二级栏目ID)
ORDER BY
a.pubdate DESC
'}
<h3>[field:typename/]</h3>
<ul>
<li>
<a href="[field:arcurl/]">[field:title/]</a>
<span>[field:pubdate function="MyDate('Y-m-d',@me)"/]</span>
</li>
</ul>
{/dede:sql}
代码详解
dede_arctype是织梦的栏目表。dede_archives是织梦的文章主表。c.reid IN (SELECT id FROM dede_arctype WHERE reid = 二级栏目ID):这是SQL的核心。c.reid表示当前栏目(三级)的父级ID。(SELECT id FROM dede_arptype WHERE reid = 二级栏目ID)会查询出所有父级ID为“二级栏目ID”的栏目的ID,也就是所有三级栏目的ID。- 整个WHERE子句的意思就是:找出所有属于“二级栏目ID”下的三级栏目,并关联它们下的文章。
- 注意:你需要将代码中的
二级栏目ID替换成你实际的数字ID。
这种方法功能最强大,但可读性差,且如果SQL写错可能导致网站性能问题或报错。 建议只在其他方法无法满足需求时使用。
总结与建议
| 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 嵌套循环法 | 最常用、最灵活、可读性好、性能稳定 | 需要理解标签嵌套逻辑 | 绝大多数情况下的首选,特别是需要自定义输出样式时。 |
| channelartlist | 代码结构清晰,适合处理多栏目 | 需要指定二级栏目ID,灵活性稍差 | 当你知道明确的二级栏目ID,且希望代码结构更“规范”时。 |
| SQL查询法 | 功能最强大,可实现复杂查询 | 可读性差,有性能风险,对新手不友好 | 需要跨栏目、按复杂条件筛选数据,且其他方法无法实现时。 |
对于绝大多数用户来说,强烈推荐使用【方法一:嵌套循环法】,它足够强大且易于理解和维护。
