DedeCMS 的多级导航主要依赖于其强大的 channelartlist 和 type 标签,下面我将从基础到进阶,分步讲解如何实现一个常见的多级导航菜单。

(图片来源网络,侵删)
核心思路
- 获取一级栏目:使用
{dede:channelartlist}标签,这个标签专门用于获取顶级栏目及其子栏目。 - 循环一级栏目:在
{dede:channelartlist}内部,通过{dede:type}标签来获取每个一级栏目的信息(如名称、链接等)。 - 获取二级及以下栏目:在
{dede:type}标签内部,可以再次嵌套使用{dede:channel}标签来获取当前一级栏目下的所有二级栏目。 - CSS 样式美化:通过编写 CSS 来控制导航的层级关系、悬停效果和下拉菜单的显示/隐藏。
第一步:准备 HTML 结构
我们需要一个清晰的 HTML 结构来表示多级菜单,通常我们会使用 <ul> 和 <li> 列表。
<!-- 这是一个常见的多级导航菜单结构 -->
<div class="main-nav">
<ul class="nav-list">
<!-- 一级栏目 1 -->
<li class="nav-item">
<a href="#一级栏目1链接">一级栏目 1</a>
<!-- 如果有二级栏目,则显示下拉菜单 -->
<ul class="sub-nav">
<li><a href="#二级栏目1-1链接">二级栏目 1-1</a></li>
<li><a href="#二级栏目1-2链接">二级栏目 1-2</a></li>
</ul>
</li>
<!-- 一级栏目 2 (无子栏目) -->
<li class="nav-item">
<a href="#一级栏目2链接">一级栏目 2</a>
</li>
<!-- 一级栏目 3 (有三级栏目) -->
<li class="nav-item">
<a href="#一级栏目3链接">一级栏目 3</a>
<ul class="sub-nav">
<li class="nav-item">
<a href="#二级栏目3-1链接">二级栏目 3-1</a>
<ul class="sub-nav">
<li><a href="#三级栏目3-1-1链接">三级栏目 3-1-1</a></li>
<li><a href="#三级栏目3-1-2链接">三级栏目 3-1-2</a></li>
</ul>
</li>
<li><a href="#二级栏目3-2链接">二级栏目 3-2</a></li>
</ul>
</li>
</ul>
</div>
第二步:使用 DedeCMS 标签填充数据
我们用 DedeCMS 的模板标签来替换上面的静态 HTML。
获取顶级栏目(一级导航)
{dede:channelartlist} 是实现多级导航的利器,它会获取所有顶级栏目,并为每个顶级栏目生成一个独立的区块,方便我们调用其子栏目。
常用属性:

(图片来源网络,侵删)
typeid: 指定调用的顶级栏目ID,多个ID用英文逗号隔开,如果为空,则调用所有顶级栏目。row: 调用的栏目数量。
获取子栏目
在 {dede:channelartlist} 的循环体内,我们可以使用以下标签:
{dede:type}: 获取当前栏目的信息(名称、链接等)。{dede:channel}: 在指定栏目下获取其子栏目列表。
完整的 DedeCMS 模板代码示例
下面是一个完整的、常用的多级导航模板代码,它支持二级导航,并带有判断逻辑(有子栏目才显示下拉菜单)。
<div class="main-nav">
<ul class="nav-list">
{dede:channelartlist typeid='top' row='8'}
<li class="nav-item">
<!-- 获取当前一级栏目的链接和名称 -->
<a href="{dede:type typeid='top'}[field:typeurl/]{/dede:type}">
{dede:type typeid='top'}[field:typename/]{/dede:type}
</a>
<!-- 获取当前一级栏目下的所有二级栏目 -->
{dede:channel type='son' noself='yes'}
<!-- 这里的 {dede:channel} 循环的是二级栏目 -->
<!-- 我们需要为每个二级栏目也创建一个 <li> -->
<!-- 为了结构清晰,我们通常只在一级栏目下判断是否有子栏目,然后一次性输出整个 <ul> -->
<!-- 更常见的写法是使用一个 {dede:channel} 循环来构建整个下拉菜单 -->
<!-- 更优化的写法:一次性获取并输出子栏目列表 -->
{dede:channelartlist}
<!-- 这个内层的 channelartlist 是为了演示,实际中直接用 {dede:channel} 更高效 -->
<!-- 我们这里用 {dede:channel} 来实现 -->
{/dede:channelartlist}
<!-- 以下是推荐的标准写法 -->
<ul class="sub-nav">
{dede:channel type='son' row='10' noself='yes'}
<li><a href="[field:typeurl/]">[field:typename/]</a></li>
{/dede:channel}
</ul>
</li>
{/dede:channelartlist}
</ul>
</div>
代码解释:
-
{dede:channelartlist typeid='top' row='8'}:
(图片来源网络,侵删)typeid='top':明确指定只调用顶级栏目。row='8':最多调用8个顶级栏目。- 这个标签会循环每一个顶级栏目。
-
<li class="nav-item">...</li>: 每个一级栏目都是一个列表项。 -
<a href="{dede:type...}">...</a>:{dede:type}标签用于获取当前循环栏目的信息。[field:typeurl/]是栏目链接。[field:typename/]是栏目名称。typeid='top'确保我们获取的是当前顶级栏目的信息,即使在更复杂的嵌套中也能保证正确。
-
{dede:channel type='son' row='10' noself='yes'}:- 这个标签放在
{dede:channelartlist}的循环内部,表示获取当前顶级栏目的子栏目。 type='son': 指定获取子栏目。row='10': 最多显示10个子栏目。noself='yes': 不显示栏目本身(虽然这里获取的就是子栏目,加上更严谨)。- 这个标签会循环每一个二级栏目。
- 这个标签放在
-
<ul class="sub-nav">...</ul>:- 这个
<ul>列表包含了所有二级栏目,只有当{dede:channel}循环有输出时(即存在子栏目),这个列表才会被创建。
- 这个
第三步:CSS 样式实现下拉效果
有了 HTML 结构和 DedeCMS 标签填充数据后,最后一步就是用 CSS 来控制样式,特别是下拉菜单的显示和隐藏。
/* 基础样式 */
.main-nav {
background-color: #333;
}
.nav-list {
list-style: none;
margin: 0;
padding: 0;
display: flex; /* 使用 flex 布局让一级导航横向排列 */
}
.nav-item {
position: relative; /* 关键:为下拉菜单定位 */
}
.nav-item a {
display: block;
padding: 15px 20px;
color: #fff;
text-decoration: none;
}
.nav-item a:hover {
background-color: #555;
}
/* 二级导航(下拉菜单)样式 */
.sub-nav {
/* 默认隐藏 */
display: none;
position: absolute; /* 关键:相对于父级 .nav-item 进行定位 */
top: 100%; /* 定位在一级菜单的下方 */
left: 0;
background-color: #444;
list-style: none;
margin: 0;
padding: 0;
min-width: 160px; /* 设置一个最小宽度 */
z-index: 1000; /* 确保下拉菜单在内容之上 */
}
/* 当鼠标悬停在一级菜单项上时,显示二级菜单 */
.nav-item:hover > .sub-nav {
display: block;
}
/* 三级导航样式(如果需要) */
.sub-nav .nav-item {
position: relative;
}
.sub-nav .nav-item > .sub-nav {
top: 0;
left: 100%; /* 定位在二级菜单的右侧 */
}
CSS 关键点:
position: relative: 在一级菜单的<li class="nav-item">上设置position: relative;,这是为了让其内部的绝对定位元素(下拉菜单)能够相对于它自身定位。position: absolute: 在二级菜单的<ul class="sub-nav">上设置position: absolute;,这样它就可以脱离正常的文档流,被“浮动”在一级菜单的旁边。display: none: 默认情况下,隐藏所有下拉菜单。hover伪类:.nav-item:hover > .sub-nav是核心,它表示“当鼠标悬停在.nav-item上时,其直接子元素.sub-nav的display属性变为block”,从而显示下拉菜单。>子选择器: 使用>子选择器非常重要,它可以避免影响其他层级的菜单,确保只有当前一级菜单的直接子菜单才会被显示。
总结与注意事项
- 栏目类型:确保你的多级栏目是在后台“栏目管理”中正确建立的顶级栏目和子栏目。
- 性能考虑:
{dede:channelartlist}会进行多次数据库查询,如果栏目非常多,可能会对页面加载速度有轻微影响,但对于常规网站,这完全足够。 - 灵活运用:上面的例子是二级导航,如果要做三级,只需在二级栏目的
<li>中再嵌套一个{dede:channel type='son'...}循环,并用相应的 CSS 控制其位置(通常是left: 100%)即可。 - 模板引擎:DedeCMS 使用的是自己的模板引擎,请确保所有标签都正确闭合,并且使用了正确的字段名(如
[field:typename/])。
通过以上三个步骤(HTML 结构 -> DedeCMS 标签 -> CSS 样式),你就可以轻松地在 DedeCMS 中实现一个功能完善、样式美观的多级导航菜单。
