dede 二级下拉菜单如何实现?

99ANYc3cd6
预计阅读时长 20 分钟
位置: 首页 DEDE建站 正文
  1. 纯 CSS 下拉菜单 (推荐) - 无需修改 PHP,只需修改 CSS 和模板 HTML,最简单、最稳定。
  2. 基于 channelartlist 标签的下拉菜单 - 适用于需要调用自定义栏目并带有特定样式的场景。

准备工作:获取栏目数据

无论使用哪种方法,我们首先需要获取栏目的 HTML 结构,织梦的 channel 标签非常适合这个任务。

打开你的模板文件,通常是 templets/default/header.htmtemplets/你的模板目录/header.htm

<nav><div class="menu"> 等菜单容器内,使用以下代码来生成一个基础的、无样式的菜单列表:

{dede:channel type='top' row='8'}
    <a href="[field:typeurl/]">[field:typename/]</a>
{/dede:channel}

这会生成类似这样的 HTML:

<a href="/">首页</a>
<a href="/a/">栏目一</a>
<a href="/b/">栏目二</a>
<a href="/c/">栏目三</a>
...

我们的目标就是在这个基础上,为有子栏目的项添加下拉菜单。


纯 CSS 下拉菜单 (最推荐)

这种方法的核心思想是:用 CSS 来控制子菜单的显示和隐藏,完全不需要改动 PHP 逻辑。

第 1 步:修改模板 HTML 结构

我们需要修改 channel 标签,让它能够识别出哪些栏目有子栏目,并为其包裹一个 <li> 标签,子栏目则放在这个 <li><ul> 里。

header.htm 中,将菜单部分的代码替换为以下代码:

<ul id="nav">
    {dede:channel type='top' row='8'}
        <li>
            <a href="[field:typeurl/]">[field:typename/]</a>
            <!-- 这里是判断是否有子栏目的关键 -->
            {dede:son typeid='[field:id/]'}
                <ul class="sub-nav">
                    {dede:arclist typeid='[field:id]' row='10'}
                        <li><a href="[field:arcurl/]">[field:title/]</a></li>
                    {/dede:arclist}
                </ul>
            {/dede:son}
        </li>
    {/dede:channel}
</ul>

代码解释:

  1. <ul id="nav">...</ul>:我们给菜单加了一个 id 方便 CSS 选择。
  2. {dede:channel type='top' row='8'}:调用顶级栏目。
  3. <li>...</li>:为每个顶级栏目项包裹一个 <li>
  4. <a href="...">...</a>:栏目链接。
  5. {dede:son typeid='[field:id/]'}...{/dede:son}:这是核心!这个标签会判断当前顶级栏目 [field:id/] 是否有子栏目,如果有,就会执行其中的内容。
  6. <ul class="sub-nav">...</ul>:如果存在子栏目,我们就创建一个子菜单列表 ul,并给它一个 class sub-nav
  7. {dede:arclist ...}:在子菜单 ul 内部,使用 arclist 标签来调用该顶级栏目下的文章列表作为子菜单项,你也可以继续使用 {dede:channel} 来调用二级栏目。

第 2 步:编写 CSS 样式

在你的 CSS 文件(通常是 templets/default/style/dedecms.css 或你的主样式文件)中,添加以下 CSS 代码:

/* 1. 重置和基础样式 */
#nav, #nav ul {
    list-style: none;
    margin: 0;
    padding: 0;
    background-color: #333; /* 菜单背景色 */
}
#nav > li {
    float: left; /* 让菜单项横向排列 */
    position: relative; /* 关键:为绝对定位的子菜单提供参照 */
}
#nav > li > a {
    display: block;
    padding: 10px 15px;
    color: #fff;
    text-decoration: none;
}
/* 2. 鼠标悬停效果 */
#nav > li > a:hover {
    background-color: #555;
}
/* 3. 子菜单样式 - 默认隐藏 */
#nav ul.sub-nav {
    position: absolute; /* 关键:将子菜单从文档流中脱离 */
    top: 100%; /* 将子菜单放在父菜单项的下方 */
    left: 0;
    width: 200px; /* 子菜单宽度 */
    background-color: #444;
    display: none; /* 默认隐藏子菜单 */
    box-shadow: 0 2px 5px rgba(0,0,0,0.2);
}
/* 4. 当鼠标悬停在父级 li 上时,显示子菜单 */
#nav > li:hover > ul.sub-nav {
    display: block; /* 鼠标悬停时显示 */
}
/* 5. 子菜单项的样式 */
#nav ul.sub-nav li {
    width: 100%;
}
#nav ul.sub-nav li a {
    display: block;
    padding: 10px 15px;
    color: #fff;
    text-decoration: none;
    border-bottom: 1px solid #555;
}
#nav ul.sub-nav li a:hover {
    background-color: #555;
}

CSS 解释:

  • position: relative; 在父级 li 上设置,这样里面的 position: absolute; 的子菜单才能相对于它定位。
  • position: absolute; 让子菜单 ul 脱离正常文档流,我们可以用 topleft 精确定位它的位置。
  • top: 100%; 确保子菜单出现在父级菜单项的下方。
  • display: none; 默认让子菜单不可见。
  • #nav > li:hover > ul.sub-nav 是选择器的精髓,它的意思是:当鼠标悬停 (hover) 在 #nav 的直接子级 li 上时,选择这个 li 的直接子级 ul class 是 sub-nav 的元素,并将其 display 设置为 block,从而实现下拉效果。

完成以上两步,一个纯 CSS 的二级下拉菜单就做好了,这种方法性能好,易于维护,是前端开发的最佳实践。


基于 channelartlist 的下拉菜单

channelartlist 标签是专门用于制作复杂导航栏的,它可以直接循环顶级栏目,并在循环内嵌套调用其子栏目。

第 1 步:修改模板 HTML 结构

同样在 header.htm 中,将菜单部分替换为:

<ul id="nav">
    {dede:channelartlist typeid='top' row='8'}
        <li>
            <a href="{dede:field name='typeurl'/}">{dede:field name='typename'/}</a>
            <ul class="sub-nav">
                {dede:channel type='son' noself='yes'}
                    <li><a href="[field:typeurl/]">[field:typename/]</a></li>
                {/dede:channel}
            </ul>
        </li>
    {/dede:channelartlist}
</ul>

代码解释:

  • {dede:channelartlist typeid='top' row='8'}:循环调用顶级栏目。
  • <a href="{dede:field name='typeurl'/}">{dede:field name='typename'/}</a>:输出当前顶级栏目的链接和名称。
  • {dede:channel type='son' noself='yes'}:在 channelartlist 的循环内部,这个标签会自动调用当前顶级栏目(即 {dede:field name='id'})的子栏目。noself='yes' 表示不显示栏目本身。
  • 这个方法生成的 HTML 结构和方法一完全一样,所以可以直接套用方法一的 CSS。

何时使用方法二?

  • 当你的顶级栏目和二级栏目的样式、结构完全一致时,使用 channelartlist 代码更简洁。
  • 如果顶级栏目和二级栏目需要不同的样式(一级是文字,二级是带图标的卡片),channelartlist 的嵌套结构会更清晰。

总结与建议

特性 方法一 (纯 CSS + channel) 方法二 (channelartlist)
实现难度 简单,只需修改 HTML 和 CSS 简单,模板标签稍复杂
灵活性 极高,可以完全自定义 HTML 结构 较高,但受限于标签本身的结构
性能 最佳,纯 CSS 效率最高 良好,但需要服务器解析嵌套标签
适用场景 绝大多数场景,特别是需要高度定制化设计的网站 快速构建标准化的多级导航栏

强烈推荐使用方法一,因为它更灵活、性能更好,并且是现代前端开发的通用标准,方法二可以作为备选,当你发现 channelartlist 的结构能完美匹配你的设计需求时再使用。

希望这个详细的教程能帮到你!如果在操作中遇到问题,可以检查一下你的 CSS 是否正确加载,以及浏览器开发者工具中 HTML 和 CSS 的状态。

-- 展开阅读全文 --
头像
c c 最难的编程语言
« 上一篇 02-27
dede自定义表单如何添加日历功能?
下一篇 » 02-27

相关文章

取消
微信二维码
支付宝二维码

目录[+]