场景分析
我们通常说的“二级栏目”,指的是在网站的顶级栏目(一级栏目)下建立的子栏目,我们的目标是:
- 列出所有一级栏目。
- 在每个一级栏目下,列出它的所有二级栏目。
- 在每个二级栏目下,调用该二级栏目下的文章列表。
这通常需要一个循环嵌套的结构:外层循环一级栏目,内层循环二级栏目,并在最内层调用文章。
最常用和推荐的方法(channelartlist + list)
这是最经典、最符合织梦逻辑的方法。channelartlist 用于调用指定层级的栏目(如一级栏目),并在其内部使用 list 标签来调用当前栏目(二级栏目)下的文章。
适用场景
当你需要在一个页面上,同时展示所有一级栏目及其下属的二级栏目和文章时。
模板代码示例
将以下代码放在你想要显示的模板文件中(通常是首页 index.htm 或自定义的栏目列表页)。
{dede:channelartlist typeid='0' row='8'}
<!-- 循环一级栏目 -->
<h2>{dede:field name='typename'/}</h2>
<div class="top-cate">
<!-- 循环当前一级栏目下的所有二级栏目 -->
{dede:channel type='son' noself='yes'}
<div class="sub-cate">
<h3>{dede:field name='typename'/}</h3>
<!-- 调用当前二级栏目下的文章列表 -->
{dede:list pagesize='5'}
<li>
<a href="[field:arcurl/]">[field:title/]</a>
<span>[field:pubdate function="MyDate('Y-m-d', @me)"/]</span>
</li>
{/dede:list}
<!-- 如果该二级栏目下没有文章,显示提示 -->
{dede:if empty=''}
<p>该栏目下暂无文章</p>
{/dede:if}
</div>
{/dede:channel}
</div>
<!-- 用于分隔不同的顶级栏目 -->
<hr style="margin: 20px 0;">
{/dede:channelartlist}
代码详解
-
{dede:channelartlist typeid='0' row='8'}typeid='0': 表示调用所有顶级栏目(一级栏目),如果你想指定某个一级栏目,可以填写其ID,如typeid='5'。row='8': 表示调用的一级栏目数量。- 这个标签会循环执行,每次循环代表一个一级栏目,在循环体内,可以通过
{dede:field name='typeid'/}获取当前一级栏目的ID。
-
{dede:channel type='son' noself='yes'}- 这个标签必须放在
channelartlist的循环内部。 type='son': 表示调用当前父栏目(即一级栏目)的子栏目(即二级栏目)。noself='yes': 表示不调用栏目本身,只调用其子栏目。- 这个标签会再次循环,每次循环代表一个二级栏目。
- 这个标签必须放在
-
{dede:list pagesize='5'}- 这个标签必须放在
channel标签的循环内部。 - 它的作用是调用当前栏目(即二级栏目)下的文章列表。
pagesize='5': 表示每页显示5篇文章。- 常用字段:
[field:title/]: 文章标题[field:arcurl/]: 文章链接[field:pubdate/]: 发布日期,通常配合function格式化,如function="MyDate('Y-m-d', @me)"[field:description/]: 文章摘要[field:litpic/]: 文章缩略图
- 这个标签必须放在
在二级栏目页调用本栏目的文章
如果你的需求是点击进入一个二级栏目页面后,只显示这个二级栏目下的文章,那么方法更简单,不需要嵌套循环。
适用场景
标准的二级栏目列表页模板 list_article.htm。
模板代码示例
在 list_article.htm 文件中,直接使用 list 标签即可。
<h1>{dede:field name='typename'/}</h1>
<p>栏目描述:{dede:field name='description'/}</p>
<ul class="article-list">
{dede:list pagesize='10'}
<li>
<a href="[field:arcurl/]" title="[field:title/]">[field:title/]</a>
<span class="date">[field:pubdate function="MyDate('Y-m-d', @me)"]</span>
</li>
{/dede:list}
</ul>
<!-- 分页标签 -->
<div class="page-nav">
{dede:pagelist listsize='4'/}
</div>
代码详解
{dede:field name='typename'/}和{dede:field name='description'/}: 分别用于获取当前栏目的名称和描述。{dede:list pagesize='10'}: 这里的list标签非常智能,它会自动识别当前所在的栏目ID,并调用该ID下的所有文章。{dede:pagelist/}: 调用分页导航。
使用SQL直接查询(灵活但需谨慎)
如果你有非常复杂的查询需求,或者对性能有极致要求,可以直接在模板中使用 dede:sql 标签执行SQL语句。
警告: 直接使用SQL有安全风险,请务必确保你的SQL语句是安全的,并且不要对用户输入进行直接拼接。
适用场景
你需要调用某个特定二级栏目(ID为 10)下的文章,并且只显示包含“织梦”关键词的文章。
模板代码示例
{dede:sql sql="SELECT id, title, arcurl, pubdate FROM `dede_archives` WHERE typeid = 10 AND title LIKE '%织梦%' ORDER BY pubdate DESC LIMIT 0, 10"}
<li>
<a href="[field:arcurl/]">[field:title/]</a>
<span>[field:pubdate function="MyDate('Y-m-d', @me)"]</span>
</li>
{/dede:sql}
代码详解
sql="...": 这里写你的SQL查询语句。dede_archives: 这是织梦存储文章核心数据的表。typeid = 10: 筛选条件,只获取栏目ID为10的文章。[field:字段名/]: 在dede:sql标签内,用于输出查询结果中的字段值。
总结与建议
| 方法 | 优点 | 缺点 | 推荐场景 |
|---|---|---|---|
方法一 (channelartlist + list) |
最标准、最安全、最灵活,符合织梦的设计哲学。 | 标签嵌套,初学者可能需要理解其工作原理。 | 首页、频道页,需要展示多级栏目和文章的复杂布局。 |
方法二 (list) |
最简单、最直接,模板代码清晰。 | 只能在栏目列表页使用,功能单一。 | 标准的二级栏目列表页 (list_article.htm)。 |
方法三 (dede:sql) |
灵活性极高,可以实现任何复杂的查询逻辑。 | 有安全风险,性能不如织梦内置标签,可读性差。 | 特殊的、非标准的查询需求,且开发者对SQL和安全非常熟悉。 |
对于99%的日常需求,强烈推荐使用方法一,它不仅能解决问题,而且代码结构清晰,易于维护,是织梦开发的最佳实践。
