- 使用 Dede 自由列表 (
{dede:freelist}) + JavaScript (推荐,最灵活) - 使用纯 SQL 查询 (
{dede:sql}) (简洁,但灵活性稍差)
准备工作
无论使用哪种方法,你都需要确定两个关键信息:

(图片来源网络,侵删)
- 顶级分类的 ID (TopID / ID):你想调用其子分类的那个分类本身的 ID,你想在“产品展示”栏目下显示其所有子分类,产品展示”的 ID 就是你的 TopID。
- 顶级分类的目录 (typedir):顶级分类的目录路径,用于构建子分类的链接。
假设我们的“产品展示”顶级分类 ID 是 2,其目录是 /products/。
使用 {dede:freelist} + JavaScript (推荐)
这种方法的核心思想是:
- 使用
{dede:freelist}标签获取子分类数据,但将其隐藏不显示。 - 使用 JavaScript 遍历这些数据,动态生成下拉框的 HTML 代码。
- 这种方法非常灵活,可以轻松控制下拉框的样式、ID 和默认选项。
实现步骤
- 在你的模板文件(
article_product.htm)中,加入以下代码:
<!-- 1. 准备一个空的 select 容器 -->
<select id="subcat_select" name="subcat">
<option value="">-- 请选择子分类 --</option>
</select>
<!-- 2. 使用 freelist 获取数据,并隐藏显示 -->
{dede:freelist titlelen='50' row='20' col='1'}
<!-- 这里的内容会被隐藏,但数据依然可以被 JS 访问 -->
<!-- 我们通过 JS 来处理这些数据 -->
{/dede:freelist}
<!-- 3. 编写 JavaScript 来处理数据并填充下拉框 -->
<script type="text/javascript">
// 获取 freelist 标签生成的所有链接
var links = document.querySelectorAll('.product a');
// 获取我们创建的 select 元素
var selectBox = document.getElementById('subcat_select');
// freelist 没有生成链接,说明没有子分类,则隐藏下拉框
if (links.length == 0) {
selectBox.style.display = 'none';
} else {
// 遍历所有链接
links.forEach(function(link) {
// 创建一个 option 元素
var option = document.createElement('option');
// 设置 option 的值为链接的 href
option.value = link.href;
// 设置 option 的显示文本为链接的 innerText
option.text = link.innerText;
// 将 option 添加到 select 中
selectBox.appendChild(option);
});
}
</script>
代码解释
<select id="subcat_select">...</select>:这是我们最终要显示的下拉框,给它一个id方便 JavaScript 选中它。{dede:freelist titlelen='50' row='20' col='1'}:这个标签会查询顶级分类 ID 为当前栏目 ID 的所有子分类。row='20':表示最多获取 20 条记录,可以根据你的子分类数量调整。col='1':表示每行显示 1 个,这样生成的 HTML 结构比较简单。
.product a:这是freelist标签默认生成的 CSS 类和 HTML 结构,它会生成类似<div class="product"><a href="...">分类名称</a></div>的代码,我们通过querySelectorAll来获取这些<a>links.forEach(...):我们遍历所有获取到的<a>标签,为每一个标签创建一个<option>,并将其添加到<select>中。
优点:
- 非常灵活:可以完全控制下拉框的 HTML 结构、CSS 样式和默认选项。
- 符合 Dede 习惯:使用了 Dede 官方提供的标签,数据来源稳定。
使用纯 SQL 查询 ({dede:sql})
这种方法直接在模板中执行 SQL 语句来获取数据,然后通过 {dede:field} 循环输出。

(图片来源网络,侵删)
实现步骤
在你的模板文件中,加入以下代码:
<select name="subcat">
<option value="">-- 请选择子分类 --</option>
{dede:sql sql="SELECT id,typename,typedir FROM `dede_arctype` WHERE reid=~topid~ ORDER BY id"}
<option value="[field:typedir function='str_replace("{cmspath}","",@me)'/]/[field:id/].html">
[field:typename/]
</option>
{/dede:sql}
</select>
代码解释
{dede:sql ...}:这是 Dede 的 SQL 查询标签。sql="SELECT id,typename,typedir FROM ...":查询语句,从dede_arctype(分类表) 中获取id(分类ID),typename(分类名),typedir(分类目录)。WHERE reid=~topid~:这是关键。~topid~是 Dede 的一个特殊变量,会自动被替换为当前栏目的 ID。reid字段表示“父分类ID”,所以这句的意思是“查找所有父分类ID为当前栏目ID的分类”,即所有子分类。ORDER BY id:按分类 ID 排序,你也可以换成sortrank按自定义排序。[field:typename/]:输出分类的名称,作为<option>的显示文本。[field:typedir function='str_replace("{cmspath}","",@me)'/]/[field:id/].html:这是构建分类链接的技巧。typedir字段的值通常是{cmspath}/products/phone这样的形式。- 我们使用
str_replace函数去掉{cmspath},得到/products/phone。 - 然后拼接上
[field:id/].html,最终得到/products/phone/1.html这样的静态链接格式。
优点:
- 代码简洁:不需要额外的 JavaScript,模板文件更干净。
- 直接高效:直接从数据库查询,一步到位。
缺点:
- 灵活性较低:如果需要复杂的交互(如联动选择),就比较困难。
- 链接构建可能不通用:如果你的网站分类链接不是
[目录]/[ID].html这种格式,需要修改value部分的代码。
总结与选择建议
| 特性 | 方法一 (freelist + JS) |
方法二 ({dede:sql}) |
|---|---|---|
| 灵活性 | 非常高,可自定义样式和交互 | 较低,主要用于静态展示 |
| 易用性 | 需要一点 JS 基础 | 非常简单,纯模板代码 |
| 性能 | 稍慢,因为需要 JS 在客户端渲染 | 稍快,服务端直接生成 HTML |
| 适用场景 | 需要自定义样式、联动、或其他复杂交互 | 只需要一个简单的、样式固定的下拉选择框 |
推荐选择:

(图片来源网络,侵删)
- 如果你只是需要一个简单的、功能固定的下拉框,方法二 (
{dede:sql}) 是最快、最简单的选择。 - 如果你希望对下拉框有更多的控制,比如添加特定的 CSS 类、需要联动选择、或者希望代码结构更清晰,强烈推荐方法一 (
freelist+ JS)。
