这里我们以最常见的“省-市-区”三级联动为例,为你提供两种主流的实现方法:

(图片来源网络,侵删)
- 使用织梦自带的联动菜单功能(推荐,最简单)
- 使用Ajax + JSON实现动态加载(更灵活,用户体验更好)
准备工作:创建联动菜单数据
无论使用哪种方法,首先你都需要在织梦后台创建好联动菜单的数据。
-
登录织梦后台 -> 核心 -> 联动菜单 -> 增加联动菜单。
- 菜单名称:填写
省份。 - 菜单目录:填写
province(这是系统识别的标识,不能重复)。 - 分类信息表:选择
flink(系统默认表,也可以选dede_sys_enum,但flink是专门为联动菜单设计的)。 - 点击 确定。
- 菜单名称:填写
-
为省份菜单添加数据:
- 点击刚刚创建的
省份菜单。 - 点击 增加选项。
- 选项名称:
广东省 - 选项值:
guangdong - 父选项:
无(顶级菜单) - 排序:
1 - 点击 确定,用同样的方法添加
北京市,上海市等。
- 点击刚刚创建的
-
创建市级菜单:
- 再次回到 增加联动菜单。
- 菜单名称:
城市 - 菜单目录:
city - 分类信息表:选择
flink。 - 父栏目:选择
省份(这一步是关键,表示城市菜单的数据依赖于省份菜单)。 - 点击 确定。
-
为城市菜单添加数据:
- 点击
城市菜单。 - 点击 增加选项。
- 选项名称:
广州市 - 选项值:
guangzhou - 父选项:
广东省(这里要选择它对应的父级省份) - 排序:
1 - 点击 确定,用同样的方法添加
深圳市,东莞市等,为每个省份下的城市都添加一遍。
- 点击
-
创建区级菜单:
- 重复以上步骤,创建一个菜单目录为
area的区域菜单,并设置其父菜单为城市。 - 然后为每个城市添加对应的区/县数据,例如为
广州市添加天河区,越秀区等。
- 重复以上步骤,创建一个菜单目录为
完成以上步骤后,你的联动菜单数据就准备好了。
使用织梦自带的联动菜单标签
这是最直接的方法,适用于简单的表单,但缺点是页面加载时所有选项都已存在,只是通过CSS隐藏,数据量大会影响页面加载速度。
适用场景:后台表单、对性能要求不高的前端表单。
标签语法:
{dede:global name='phpmywind'}
<!-- 省份 -->
<select name='province' id='province'>
<option value='0'>请选择省份</option>
{dede:linkage type='province'}
<option value='[field:value/]'>[field:typename/]</option>
{/dede:linkage}
</select>
<!-- 城市 -->
<select name='city' id='city'>
<option value='0'>请选择城市</option>
{dede:linkage type='city'}
<option value='[field:value/]'>[field:typename/]</option>
{/dede:linkage}
</select>
<!-- 区域 -->
<select name='area' id='area'>
<option value='0'>请选择区域</option>
{dede:linkage type='area'}
<option value='[field:value/]'>[field:typename/]</option>
{/dede:linkage}
</select>
{/dede:global}
实现联动(CSS控制):
为了让联动生效,你需要配合一点CSS和JavaScript来控制,织梦自带了JS文件 js/linkage.js。
-
引入JS文件:在页面
<head>部分引入。<script type="text/javascript" src="{dede:global.cfg_cmspath/}/js/linkage.js"></script> -
添加联动JS代码:
<script type="text/javascript"> // 省份改变时,更新城市 document.getElementById('province').onchange = function() { // 清空城市和区域的选项 document.getElementById('city').options.length = 1; document.getElementById('area').options.length = 1; // 调用织梦联动函数 // 参数1: 下拉框ID, 参数2: 父级菜单的值 GetLinkage('city', this.value); }; // 城市改变时,更新区域 document.getElementById('city').onchange = function() { // 清空区域的选项 document.getElementById('area').options.length = 1; // 调用织梦联动函数 GetLinkage('area', this.value); }; </script>
完整示例:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">织梦联动菜单示例</title>
<script type="text/javascript" src="{dede:global.cfg_cmspath/}/js/jquery.min.js"></script>
<script type="text/javascript" src="{dede:global.cfg_cmspath/}/js/linkage.js"></script>
</head>
<body>
<h3>请选择您的所在地区:</h3>
{dede:global name='phpmywind'}
<!-- 省份 -->
<select name='province' id='province'>
<option value='0'>请选择省份</option>
{dede:linkage type='province'}
<option value='[field:value/]'>[field:typename/]</option>
{/dede:linkage}
</select>
<!-- 城市 -->
<select name='city' id='city'>
<option value='0'>请选择城市</option>
{dede:linkage type='city'}
<option value='[field:value/]'>[field:typename/]</option>
{/dede:linkage}
</select>
<!-- 区域 -->
<select name='area' id='area'>
<option value='0'>请选择区域</option>
{dede:linkage type='area'}
<option value='[field:value/]'>[field:typename/]</option>
{/dede:linkage}
</select>
{/dede:global}
<script type="text/javascript">
// 省份改变时,更新城市
document.getElementById('province').onchange = function() {
document.getElementById('city').options.length = 1;
document.getElementById('area').options.length = 1;
GetLinkage('city', this.value);
};
// 城市改变时,更新区域
document.getElementById('city').onchange = function() {
document.getElementById('area').options.length = 1;
GetLinkage('area', this.value);
};
</script>
</body>
</html>
使用Ajax + JSON实现动态加载(推荐)
这种方法性能更好,用户体验更佳,它只在需要时通过Ajax请求从服务器获取子级数据,而不是一次性加载所有数据。
核心思路:
- 在模板中放置三个空的
<select>。 - 页面加载时,通过Ajax请求并填充“省份”列表。
- 当“省份”选择改变时,发送Ajax请求,传递省份ID,获取并填充“城市”列表。
- 当“城市”选择改变时,发送Ajax请求,传递城市ID,获取并填充“区域”列表。
实现步骤:
-
创建一个PHP文件处理Ajax请求: 在你的模板目录下(如
/templets/default/),创建一个文件,linkage.php。<?php /** * 织梦联动菜单Ajax处理文件 * 用法: /linkage.php?&linkage=province * /linkage.php?&linkage=city&parent=guangdong */ require_once(dirname(__FILE__) . "/../include/common.inc.php"); // 引入织梦核心文件 $linkage = isset($linkage) ? trim($linkage) : ''; $parent = isset($parent) ? intval($parent) : 0; if (empty($linkage)) { echo json_encode(array('code' => 1, 'msg' => '联动菜单类型不能为空')); exit; } // 查询联动菜单数据 $dsql->SetQuery("SELECT e.*,e.ename as typename FROM `#@__flink` e WHERE e.ejoin='{$parent}' AND e.etype='{$linkage}' ORDER BY e.egroup ASC"); $dsql->Execute('linkage'); $options = array(); while ($row = $dsql->GetArray('linkage')) { $options[] = array( 'id' => $row['eid'], 'name' => $row['typename'], 'value' => $row['ename'] ); } echo json_encode(array('code' => 0, 'data' => $options)); exit; ?>注意:
ejoin字段存储的是父级菜单的eid,ename是选项的值,typename是选项的名称,如果你的数据结构不同,需要调整SQL查询语句。 -
修改模板文件: 在你的HTML模板中,使用jQuery来发起Ajax请求。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>织梦Ajax联动菜单示例</title> <script type="text/javascript" src="{dede:global.cfg_cmspath/}/js/jquery.min.js"></script> </head> <body> <h3>请选择您的所在地区:</h3> <!-- 省份 --> <select name="province" id="province"> <option value="0">请选择省份</option> </select> <!-- 城市 --> <select name="city" id="city"> <option value="0">请选择城市</option> </select> <!-- 区域 --> <select name="area" id="area"> <option value="0">请选择区域</option> </select> <script type="text/javascript"> $(function(){ // 1. 页面加载时,加载省份 loadProvince(); // 2. 省份选择改变时,加载城市 $('#province').change(function(){ var provinceId = $(this).val(); if (provinceId != 0) { loadCity(provinceId); } else { $('#city').html('<option value="0">请选择城市</option>'); $('#area').html('<option value="0">请选择区域</option>'); } }); // 3. 城市选择改变时,加载区域 $('#city').change(function(){ var cityId = $(this).val(); if (cityId != 0) { loadArea(cityId); } else { $('#area').html('<option value="0">请选择区域</option>'); } }); // 加载省份的函数 function loadProvince() { $.ajax({ url: "{dede:global.cfg_cmspath/}/templets/default/linkage.php", // 指向你的PHP文件 type: 'GET', data: { linkage: 'province' }, dataType: 'json', success: function(res) { if (res.code == 0) { var html = '<option value="0">请选择省份</option>'; $.each(res.data, function(i, item) { html += '<option value="' + item.value + '">' + item.name + '</option>'; }); $('#province').html(html); } } }); } // 加载城市的函数 function loadCity(parentId) { $.ajax({ url: "{dede:global.cfg_cmspath/}/templets/default/linkage.php", type: 'GET', data: { linkage: 'city', parent: parentId }, dataType: 'json', success: function(res) { if (res.code == 0) { var html = '<option value="0">请选择城市</option>'; $.each(res.data, function(i, item) { html += '<option value="' + item.value + '">' + item.name + '</option>'; }); $('#city').html(html); $('#area').html('<option value="0">请选择区域</option>'); // 清空区域 } } }); } // 加载区域的函数 function loadArea(parentId) { $.ajax({ url: "{dede:global.cfg_cmspath/}/templets/default/linkage.php", type: 'GET', data: { linkage: 'area', parent: parentId }, dataType: 'json', success: function(res) { if (res.code == 0) { var html = '<option value="0">请选择区域</option>'; $.each(res.data, function(i, item) { html += '<option value="' + item.value + '">' + item.name + '</option>'; }); $('#area').html(html); } } }); } }); </script> </body> </html>
总结与对比
| 特性 | 方法一 (自带标签) | 方法二 (Ajax + JSON) |
|---|---|---|
| 实现难度 | 简单,只需写标签和少量JS | 较复杂,需要创建PHP文件和编写JS |
| 性能 | 较差,一次性加载所有数据 | 优秀,按需加载,响应速度快 |
| 用户体验 | 一般,页面加载可能卡顿 | 极佳,下拉流畅,无刷新感 |
| 灵活性 | 较低,依赖织梦标签 | 极高,可自定义返回数据格式,易于扩展 |
| 适用场景 | 后台表单、数据量小的简单前端 | 所有前端场景,特别是对性能和体验要求高的地方 |
强烈推荐使用方法二,它是目前Web应用中实现联动的标准做法,能给你的网站带来更好的性能和用户体验。
