dede如何嵌套获取顶级栏目及子栏目列表?

99ANYc3cd6
预计阅读时长 19 分钟
位置: 首页 DEDE建站 正文
  1. 获取所有顶级栏目:使用 {dede:channelartlist} 标签,这个标签专门用于获取顶级栏目。
  2. 循环获取每个顶级栏目下的子栏目:在 {dede:channelartlist} 的循环体内,使用 {dede:type} 标签来获取当前顶级栏目([field:id])下的所有子栏目。

下面我将为您提供两种最常用和最稳定的方法:使用 channelartlisttype,以及使用 SQL 查询,强烈推荐第一种方法,因为它更符合 DedeCMS 的模板设计理念,也更易于维护。

dede 嵌套获取顶级栏目及子栏目列表
(图片来源网络,侵删)

使用 {dede:channelartlist}{dede:type} 标签(推荐)

这是最标准、最灵活的方法。channelartlist 负责循环顶级栏目,type 负责在循环内部获取子栏目。

第1步:准备模板文件

在你的模板文件夹中(通常是 /templets/default/),创建一个新的模板文件,nav_sub.htm

第2步:编写模板代码

将以下代码复制到 nav_sub.htm 文件中,代码中包含了详细的注释,方便你理解每个部分的作用。

{dede:channelartlist typeid='0' currentstyle='active'}
  <li class="nav-item">
    <!-- 
      顶级栏目链接
      [field:typelink/] 是顶级栏目的链接地址
      [field:typename/] 是顶级栏目的名称
      currentstyle 属性用于设置当前栏目所在项的样式,这里我们给一个 'active' 类
    -->
    <a href="[field:typelink/]" class="nav-link [field:global name=typeid runphp='yes']@me=(@me=='[field:id]')?'active':'';[/field:global]">
      [field:typename/]
    </a>
    <!-- 
      子栏目列表容器
      使用 {dede:sql} 或 {dede:channel} 来获取子栏目
      这里我们使用 {dede:channel},因为它更简洁,专门用于获取子栏目
    -->
    <ul class="subnav-list">
      {dede:channel type='son' noself='yes'}
        <!-- 
          子栏目链接
          [field:typelink/] 是子栏目的链接
          [field:typename/] 是子栏目的名称
        -->
        <li>
          <a href="[field:typelink/]">[field:typename/]</a>
        </li>
      {/dede:channel}
    </ul>
  </li>
{/dede:channelartlist}

第3步:参数说明

  • {dede:channelartlist typeid='0' currentstyle='active'}

    dede 嵌套获取顶级栏目及子栏目列表
    (图片来源网络,侵删)
    • typeid='0':表示获取所有顶级栏目,如果你想指定只获取某些顶级栏目,可以写成 typeid='1,3,5',1, 3, 5 是顶级栏目的 ID。
    • currentstyle='active':这是一个非常有用的属性,当用户访问某个顶级栏目或其下的任意页面时,这个顶级栏目对应的 <li> 会自动应用 active 样式,你可以通过 CSS 来定义 active 类的样式,例如改变背景色或文字颜色。
  • {dede:channel type='son' noself='yes'}

    • type='son':这是关键参数,表示获取当前顶级栏目(由外层 channelartlist 提供)的所有直接子栏目
    • noself='yes':表示不获取栏目本身,因为我们已经在上面显示了顶级栏目的链接,这里就不需要重复显示了,如果你想去掉这个属性,顶级栏目本身也会出现在子列表中。

第4步:在页面中调用

在你需要显示这个嵌套导航栏的页面模板文件(head.htm)中,使用 include 标签来引入 nav_sub.htm

<div class="main-nav">
  <ul class="nav-list">
    {dede:include filename='nav_sub.htm'/}
  </ul>
</div>

第5步:添加 CSS 样式

为了让子栏目列表在鼠标悬停时才显示,你需要添加一些 CSS 样式,在你的 CSS 文件中添加以下代码:

/* 主导航列表样式 */
.nav-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex; /* 使用 flex 布局让导航项横向排列 */
}
.nav-item {
  position: relative; /* 关键:为子菜单定位提供参考 */
}
.nav-link {
  display: block;
  padding: 10px 15px;
  text-decoration: none;
  color: #333;
}
/* 当前栏目激活状态 */
.nav-link.active {
  color: #ff6600; /* 示例:激活状态为橙色 */
  font-weight: bold;
}
/* 默认隐藏子菜单 */
.subnav-list {
  list-style: none;
  margin: 0;
  padding: 0;
  position: absolute; /* 绝对定位,相对于父级 .nav-item */
  top: 100%; /* 显示在父级链接的下方 */
  left: 0;
  background-color: #fff;
  border: 1px solid #ddd;
  box-shadow: 0 2px 5px rgba(0,0,0,0.1);
  display: none; /* 默认隐藏 */
  z-index: 1000;
}
/* 鼠标悬停在父级上时,显示子菜单 */
.nav-item:hover .subnav-list {
  display: block; /* 鼠标悬停时显示 */
}
/* 子菜单链接样式 */
.subnav-list li a {
  display: block;
  padding: 8px 15px;
  text-decoration: none;
  color: #555;
  white-space: nowrap; /* 防止文字换行 */
}
.subnav-list li a:hover {
  background-color: #f0f0f0;
}

使用 SQL 查询(适用于复杂场景)

如果你需要对栏目数据进行更复杂的筛选和处理,可以使用 {dede:sql} 标签直接执行 SQL 查询,这种方法更灵活,但可读性稍差。

模板代码示例

{dede:sql sql="SELECT id,typename,typedir FROM `dede_arctype` WHERE reid=0 AND ishidden<>1 ORDER BY sortrank ASC"}
  <li class="nav-item">
    <a href="[field:typedir function='str_replace("{cmspath}", "", "@me")'/]" class="nav-link">
      [field:typename/]
    </a>
    <ul class="subnav-list">
      {dede:sql sql="SELECT id,typename,typedir FROM `dede_arctype` WHERE reid=[field:id/] AND ishidden<>1 ORDER BY sortrank ASC"}
        <li><a href="[field:typedir function='str_replace("{cmspath}", "", "@me")'/]">[field:typename/]</a></li>
      {/dede:sql}
    </ul>
  </li>
{/dede:sql}

代码说明

  1. 外层循环{dede:sql sql="..."} 查询 reid=0 的所有栏目,reid 为 0 的就是顶级栏目。
  2. 顶级栏目链接[field:typedir/] 返回的是包含 {cmspath} 的完整路径,我们使用 function='str_replace("{cmspath}", "", "@me")' 来移除它,得到正确的相对链接。
  3. 内层循环:在 channelartlist 循环中,我们使用 [field:id/] 获取当前顶级栏目的 ID,并将其作为参数传递给内层的 SQL 查询,WHERE reid=[field:id/] 就实现了获取子栏目的目的。
  4. 子栏目链接:同样处理 typedir 字段以获得正确链接。

总结与建议

特性 方法一 (channelartlist + type) 方法二 (sql 查询)
易用性 ,标签化,符合 DedeCMS 模板哲学 ,需要写 SQL 语句,容易出错
可维护性 ,代码清晰,结构分明 ,SQL 与 HTML 混合,不易阅读和修改
灵活性 中等,能满足大部分需求 ,可以执行任何复杂的 SQL 逻辑
性能 良好 良好,但要注意 SQL 查询效率

对于绝大多数情况,请优先选择方法一,它更安全、更易于维护,并且是 DedeCMS 社区普遍推荐的实践方式。

只有在方法一无法满足你的特殊需求时(需要根据其他表的数据来筛选栏目),才考虑使用方法二。

-- 展开阅读全文 --
头像
织梦主页如何添加用户登录模块?
« 上一篇 12-04
dede5.7保存栏目更改失败怎么办?
下一篇 » 12-04

相关文章

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