dede织梦多级下拉菜单如何实现?

99ANYc3cd6
预计阅读时长 25 分钟
位置: 首页 DEDE建站 正文
  1. 纯CSS方法:实现起来最简单,无需JS,但只能实现纯下拉,交互性稍弱。
  2. CSS + JavaScript方法:可以实现“鼠标悬停显示/点击显示”等更丰富的交互效果,是目前最主流和推荐的方法。

准备工作:获取顶级栏目

无论使用哪种方法,我们首先需要获取顶级栏目,然后在这些顶级栏目下查找它们的子栏目。

dede 织梦 二级三级下拉分类菜单
(图片来源网络,侵删)

在织梦中,顶级栏目的 topid 属性为 0,我们可以通过 typeid 参数来指定父栏目,从而获取其子栏目。


纯CSS实现下拉菜单

这种方法的核心是利用CSS的 hover 伪类来控制子菜单的显示和隐藏。

第1步:修改模板文件

在你需要显示导航栏的模板文件中(通常是 head.htmtemplets/default/head.htm),找到导航栏的HTML结构,并将其修改为以下格式:

<div id="nav">
    <ul>
        {dede:channel type='top' row='8'}
        <li>
            <a href="[field:typeurl/]">[field:typename/]</a>
            <!-- 开始判断是否有子栏目 -->
            [field:sonlist runphp='yes']
                global $dsql;
                $typeid = @me;
                $sql = "SELECT id,typename,typedir FROM `dede_arctype` WHERE reid='$typeid' ORDER BY sortrank";
                $sonids = '';
                $dsql->SetQuery($sql);
                $dsql->Execute();
                while($row = $dsql->GetArray()){
                    $sonids .= "<li><a href='/".str_replace('{cmspath}','',$row['typedir'])."/'>".$row['typename']."</a></li>\r\n";
                }
                if($sonids != ''){
                    @me = '<ul class="sub-nav">'.$sonids.'</ul>';
                }else{
                    @me = '';
                }
            [/field:sonlist]
        </li>
        {/dede:channel}
    </ul>
</div>

代码解释:

dede 织梦 二级三级下拉分类菜单
(图片来源网络,侵删)
  • {dede:channel type='top' row='8'}: 获取顶级栏目,最多显示8个。
  • [field:typeurl/]: 栏目链接。
  • [field:typename/]: 栏目名称。
  • [field:sonlist runphp='yes']: 这是核心部分,它为每一个顶级栏目都执行一次PHP代码。
    • global $dsql;: 调用数据库操作类。
    • $typeid = @me;: 获取当前顶级栏目的ID。
    • SELECT ... WHERE reid='$typeid': 查询所有 reid(父栏目ID)等于当前顶级栏目ID的子栏目。
    • if($sonids != ''): 判断查询结果是否为空,如果不为空,则生成一个 <ul class="sub-nav">...</ul> 的结构;如果为空,则什么都不输出。

第2步:编写CSS样式

在模板的CSS文件(通常是 style.csstemplets/default/style/dedecms.css)中,添加以下样式:

/* 基础导航样式 */
#nav {
    width: 100%;
    background-color: #333; /* 导航背景色 */
    font-family: Arial, sans-serif;
}
#nav ul {
    list-style: none; /* 去掉列表前的点 */
    margin: 0;
    padding: 0;
    display: flex; /* 使用Flex布局让菜单项水平排列 */
    justify-content: center; /* 居中对齐 */
}
#nav li {
    position: relative; /* 关键:为下拉菜单定位提供参考 */
    margin: 0 10px;
}
#nav li a {
    display: block;
    color: #fff;
    padding: 15px 20px;
    text-decoration: none;
    text-align: center;
}
#nav li a:hover {
    background-color: #555; /* 鼠标悬停时的背景色 */
}
/* --- 二级下拉菜单样式 --- */
#nav li > ul.sub-nav {
    /* 默认隐藏 */
    display: none; 
    position: absolute; /* 绝对定位,相对于父级li */
    top: 100%; /* 定位在父级li的底部 */
    left: 0;
    background-color: #444;
    min-width: 160px;
    box-shadow: 0 8px 16px rgba(0,0,0,0.2);
    z-index: 1000;
}
/* 鼠标悬停在父级li上时,显示二级菜单 */
#nav li:hover > ul.sub-nav {
    display: block;
}
/* 二级菜单的列表项样式 */
#nav .sub-nav li {
    width: 100%;
    margin: 0;
}
#nav .sub-nav li a {
    text-align: left;
    padding: 10px 15px;
}
#nav .sub-nav li a:hover {
    background-color: #555;
}
/* --- 三级下拉菜单样式 --- */
#nav .sub-nav li > ul {
    display: none;
    position: absolute;
    top: 0;
    left: 100%; /* 定位在二级菜单的右侧 */
    background-color: #555;
}
#nav .sub-nav li:hover > ul {
    display: block;
}

CSS解释:

  • #nav li { position: relative; }: 这是实现下拉菜单的关键,它让子菜单可以相对于 li 元素进行定位。
  • #nav li > ul.sub-nav { display: none; }: 默认隐藏所有二级菜单。
  • #nav li:hover > ul.sub-nav { display: block; }: 当鼠标移动到 li 上时,它的直接子元素 ul.sub-nav(二级菜单)会显示出来。
  • 三级菜单的原理和二级菜单完全一样,只是定位的父级变成了二级菜单的 li,并且通过 left: 100% 让它出现在二级菜单的右侧。

CSS + JavaScript实现(推荐)

纯CSS方法在移动端上体验不佳(鼠标悬停不触发),且无法实现点击收起/展开,结合JS可以解决这些问题。

第1步:修改模板文件(HTML结构)

JS方法通常需要一个固定的结构来方便操作,我们可以稍微简化一下HTML,通过JS来动态判断并生成子菜单。

dede 织梦 二级三级下拉分类菜单
(图片来源网络,侵删)
<div id="nav">
    <ul>
        {dede:channel type='top' row='8'}
        <li>
            <a href="[field:typeurl/]">[field:typename/]</a>
            <!-- 子菜单容器,JS会动态填充内容 -->
            <ul class="sub-nav"></ul>
        </li>
        {/dede:channel}
    </ul>
</div>

第2步:编写CSS样式

CSS部分基本和第一种方法一样,但我们可以移除 hover 的部分,改用 .active 类来控制显示。

/* 基础样式和之前一样,这里省略... */
/* 子菜单默认隐藏 */
#nav li > ul.sub-nav {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    background-color: #444;
    min-width: 160px;
    box-shadow: 0 8px 16px rgba(0,0,0,0.2);
    z-index: 1000;
}
/* 当父级li拥有 .active 类时,子菜单显示 */
#nav li.active > ul.sub-nav {
    display: block;
}
/* 三级菜单样式也和之前一样,通过 .active 类控制 */
#nav .sub-nav li > ul {
    display: none;
    position: absolute;
    top: 0;
    left: 100%;
    background-color: #555;
}
#nav .sub-nav li.active > ul {
    display: block;
}

第3步:编写JavaScript代码

在模板文件的底部(</body> 标签之前)引入或编写JS代码。

<script>
document.addEventListener('DOMContentLoaded', function() {
    // 获取所有顶级导航项
    const navItems = document.querySelectorAll('#nav > ul > li');
    navItems.forEach(item => {
        const link = item.querySelector('a');
        const subNav = item.querySelector('.sub-nav');
        // 如果存在子菜单,则为其添加事件
        if (subNav && subNav.children.length > 0) {
            // 鼠标悬停事件
            item.addEventListener('mouseenter', () => {
                item.classList.add('active');
            });
            item.addEventListener('mouseleave', () => {
                item.classList.remove('active');
            });
            // 点击事件(可选,用于移动端)
            link.addEventListener('click', function(e) {
                // 如果是在移动端,可以阻止默认跳转,显示子菜单
                // if (window.innerWidth <= 768) {
                //     e.preventDefault();
                //     item.classList.toggle('active');
                // }
            });
        }
    });
});
</script>

JS解释:

  1. document.addEventListener('DOMContentLoaded', ...):确保DOM元素完全加载后再执行脚本。
  2. document.querySelectorAll('#nav > ul > li'):选择所有顶级菜单项。
  3. forEach:遍历每一个菜单项。
  4. item.addEventListener('mouseenter', ...):当鼠标进入一个菜单项时,给它添加 .active 类。
  5. item.addEventListener('mouseleave', ...):当鼠标离开时,移除 .active 类。
  6. CSS中定义的 .active 类会触发 display: block,从而显示子菜单。

如何选择?

  • 如果你的网站是纯PC端,且追求最简单的实现:选择方法一(纯CSS)
  • 如果你的网站需要兼容移动端,或者希望有更灵活的交互(比如点击展开):强烈推荐方法二(CSS + JavaScript),这是目前业界最标准和通用的做法。

重要提示:在实际项目中,请务必根据你自己的网站主题样式来调整CSS中的颜色、字体、间距等属性,以达到最佳视觉效果。

-- 展开阅读全文 --
头像
织梦后台如何上传已写好的HTML文件?
« 上一篇 12-07
malloc与calloc有何区别?
下一篇 » 12-07
取消
微信二维码
支付宝二维码

目录[+]