下面我将提供一个完整、详细、可直接使用的实现方案,包括HTML结构、JavaScript逻辑和PHP后端处理,这个方案兼容织梦的标签和数据结构。

(图片来源网络,侵删)
实现思路
- 前端HTML: 创建三个下拉列表(
<select>),分别用于省、市、区,并为它们设置合适的id和class,方便JS操作。 - 后端PHP: 创建一个PHP文件(
ajax_getcity.php),用于根据前端传来的省份ID或城市ID,查询数据库并返回对应的JSON格式的城市或区县数据。 - 前端JavaScript:
- 页面加载时,调用AJAX请求,获取所有省份并填充到第一个下拉列表。
- 为省份下拉列表绑定
onchange事件,当省份改变时,清空市、区下拉列表,然后调用AJAX请求获取该省份下的所有城市,并填充到第二个下拉列表。 - 为城市下拉列表绑定
onchange事件,当城市改变时,清空区县下拉列表,然后调用AJAX请求获取该城市下的所有区县,并填充到第三个下拉列表。 - 为了优化用户体验,可以为每个下拉列表添加一个“正在加载...”的提示。
第一步:准备数据库(织梦默认已支持)
织梦的数据库中已经包含了完整的地区数据,主要在 #@__areas 这张表中,表结构大致如下:
id: 地区ID(主键)reid: 父级ID,用来表示层级关系,0表示顶级(省份),某个省份的ID表示该省份下的城市,某个城市的ID表示该城市下的区县。name: 地区名称
你不需要手动创建这张表,织梦安装时已经存在。
第二步:创建前端HTML文件
在你的织梦模板文件中(article_add.htm 或 member_info.htm),找到需要添加地区联动的位置,插入以下代码。
<!-- 省份 -->
<select name="province" id="province" class="form-control" style="width: 150px; display: inline-block;">
<option value="0">请选择省份</option>
</select>
<!-- 城市 -->
<select name="city" id="city" class="form-control" style="width: 150px; display: inline-block;">
<option value="0">请选择城市</option>
</select>
<!-- 区县 -->
<select name="district" id="district" class="form-control" style="width: 150px; display: inline-block;">
<option value="0">请选择区县</option>
</select>
name属性:用于表单提交,后端PHP可以用$_POST['province']来获取值。id属性:这是JavaScript操作的关键,必须唯一。class属性:用于CSS样式美化,这里用了Bootstrap的form-control作为示例。
第三步:创建后端AJAX处理文件 (ajax_getcity.php)
在网站根目录下创建一个名为 ajax_getcity.php 的文件,这个文件负责响应前端的AJAX请求。

(图片来源网络,侵删)
<?php
/**
* 织梦地区联动AJAX处理文件
* 根据父级ID获取子级地区列表
*/
// 引入数据库配置文件,织梦通常在include目录下
require_once (dirname(__FILE__) . "/include/common.inc.php");
// 设置请求头为JSON,防止中文乱码
header("Content-Type: application/json; charset=utf-8");
// 获取前端传来的父级ID
$pid = isset($_GET['pid']) ? intval($_GET['pid']) : 0;
// 定义返回数组
$data = array();
// 如果pid有效,则查询数据库
if ($pid > 0) {
// 查询#@__areas表中reid等于pid的所有记录
// dsql是织梦的数据库操作类
$dsql = new DedeSql(false);
$dsql->SetQuery("SELECT id, name FROM `#@__areas` WHERE reid = {$pid} ORDER BY id ASC");
$dsql->Execute('al');
while ($row = $dsql->GetArray('al')) {
// 将查询结果存入返回数组
$data[] = array(
'id' => $row['id'],
'name' => $row['name']
);
}
$dsql->Close();
}
// 将PHP数组转换为JSON格式并输出
echo json_encode($data);
?>
文件说明:
require_once (dirname(__FILE__) . "/include/common.inc.php");:这行代码至关重要,它引入了织梦的核心配置文件,使得我们可以使用织梦的全局变量和数据库操作类$dsql。header("Content-Type: application/json; charset=utf-8");:告诉浏览器返回的是JSON数据,并设置字符集为UTF-8,避免中文乱码。intval($_GET['pid']):获取前端通过GET方式传来的父级ID,并用intval()函数进行类型转换,防止SQL注入。dsql->SetQuery(...):执行SQL查询,reid = {$pid}是核心,它查找所有父级ID为$pid的地区。json_encode($data):将PHP数组转换成JSON字符串,这是前后端数据交互的标准格式。
第四步:编写前端JavaScript代码
在HTML文件的 <head> 标签内或页面底部的 <script> 标签中,加入以下JavaScript代码。
<script>
document.addEventListener('DOMContentLoaded', function() {
// 获取三个下拉列表的DOM元素
var provinceSelect = document.getElementById('province');
var citySelect = document.getElementById('city');
var districtSelect = document.getElementById('district');
// AJAX请求函数,用于获取地区数据
function loadArea(selectElement, pid, callback) {
// 创建XMLHttpRequest对象
var xhr = new XMLHttpRequest();
// 指定PHP文件,并传递父级ID
xhr.open('GET', '/ajax_getcity.php?pid=' + pid, true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
// 请求成功,解析返回的JSON数据
var areas = JSON.parse(xhr.responseText);
// 清空下拉列表(保留第一个默认选项)
selectElement.innerHTML = '<option value="0">请选择</option>';
// 遍历数据并创建新的option元素
areas.forEach(function(area) {
var option = document.createElement('option');
option.value = area.id;
option.textContent = area.name;
selectElement.appendChild(option);
});
// 如果有回调函数,则执行
if (typeof callback === 'function') {
callback();
}
}
};
xhr.send();
}
// 1. 页面加载时,加载所有省份 (pid为0表示顶级)
loadArea(provinceSelect, 0);
// 2. 监听省份选择变化事件
provinceSelect.onchange = function() {
var selectedProvinceId = this.value;
// 清空市和区下拉列表
citySelect.innerHTML = '<option value="0">请选择城市</option>';
districtSelect.innerHTML = '<option value="0">请选择区县</option>';
// 如果选择了省份(而不是“请选择”),则加载对应的城市
if (selectedProvinceId !== '0') {
loadArea(citySelect, selectedProvinceId);
}
};
// 3. 监听城市选择变化事件
citySelect.onchange = function() {
var selectedCityId = this.value;
// 清空区县下拉列表
districtSelect.innerHTML = '<option value="0">请选择区县</option>';
// 如果选择了城市,则加载对应的区县
if (selectedCityId !== '0') {
loadArea(districtSelect, selectedCityId);
}
};
});
</script>
代码说明:
DOMContentLoaded:确保整个HTML文档加载完毕后再执行JS代码,避免找不到DOM元素。loadArea函数:这是一个通用的AJAX请求函数,它接收三个参数:要填充的下拉列表、父级ID、以及一个可选的回调函数,这使得代码更简洁、可复用。XMLHttpRequest:这是原生JS实现AJAX的核心对象。onchange事件:当下拉列表的选中项改变时触发,我们在事件处理函数中,根据当前选中的值,去加载下一级的数据,并清空再下级的数据,实现级联效果。this.value:在事件处理函数中,this指向触发事件的DOM元素(即<select>),this.value就是当前选中的option的value。
第五步:整合与测试
- 将HTML、
ajax_getcity.php和JS代码分别放到对应的位置。 - 确保你的织梦网站根目录下有
include/common.inc.php文件。 - 在浏览器中打开你的页面,你应该能看到:
- 页面加载后,第一个下拉列表(省份)自动填充了所有省份。
- 选择一个省份后,第二个下拉列表(城市)会自动填充该省份下的所有城市。
- 选择一个城市后,第三个下拉列表(区县)会自动填充该城市下的所有区县。
进阶优化(可选)
-
回显数据:在编辑信息时,你可能需要让这三个下拉列表显示已保存的值,你可以在页面加载后,获取到后端传递过来的
province,city,district值,然后手动设置selected属性。
(图片来源网络,侵删)// 假设这些值是从PHP后端传过来的 var savedProvinceId = "你的省份ID"; var savedCityId = "你的城市ID"; var savedDistrictId = "你的区县ID"; // 先加载省份 loadArea(provinceSelect, 0, function() { // 省份加载完后,设置默认选中的省份 if (savedProvinceId) { provinceSelect.value = savedProvinceId; // 触发省份的onchange事件,以加载对应的城市 provinceSelect.onchange(); } }); // 在城市加载的回调中设置默认城市 // ... 类似逻辑 -
使用jQuery:如果你的项目已经引入了jQuery,代码可以更简洁,将
XMLHttpRequest替换为$.ajax()或$.get()。 -
添加“加载中”提示:可以在
loadArea函数中,在发送请求前,给下拉列表添加一个“加载中...”的选项,并在请求完成后移除,提升用户体验。
这个原生JS的实现方案不依赖任何外部库(除了织梦自身),稳定且高效,非常适合在织梦项目中使用。
