去年明河曾写了个多级联动的类:使用jquery实现ajax省、市、县三级联动,有朋友向偶反应bug不少,于是这二天重构了之前写的类,写成了一个jquery插件。
示例依旧演示了省市县联动,这次明河加上了国家,组成了四级联动,其实这个插件一样可以作用于类别等的联动,而且还是不限级数的。
由于seriesComboBoxs存在明显缺陷,明河重构了个新的联动插件,请点此查看。
2010-07-14 V0.2 更新如下:
- 修正最后一个选择框依旧请求数据的问题
- 修正了选择框重复加载的问题
2010-05-12 V0.11 更新如下:
- 支持json、xml二种数据源
- 增加了事件
- 修正了原来类的几个大bug
- 对API做了调整,增加了新的便利API

使用教程
1、导入地区数据库(mysql)
数据库文件为region.sql,此数据库来源于ecshop,明河不再使用旧的数据库,ecshop的这份数据库还是非常全的。
2、连接数据库
请打开get_region.php,找到:
- $hostname = 'localhost';// 数据库服务器
- $username = 'root'; // 数据库用户名
- $password = '123'; // 数据库密码
- $dbname = 'ld'; // 数据库名
按照本地服务器的情况,自行修改。
接下来以第一个最简单的例子讲解调用
3、引入jquery、seriesComboBoxs 还有css
- <script src="js/jquery-1.4.2.min.js"></script>
- <script src="js/jquery.seriesComboBoxs.js"></script>
- <link href="style/css/base.css" rel="stylesheet" type="text/css" />
- <link href="style/css/demo.css" rel="stylesheet" type="text/css" />
创建四个选择框
- <table width="700" border="0" cellspacing="0" cellpadding="0" class="tab1">
- <tr>
- <td>国家</td>
- <td><select class="comboBox" id="country" name="country" width="100">
- <option value="">请选择你的国家</option>
- </select>
- </td>
- <td>省份</td>
- <td><select class="comboBox" id="province" name="province" width="100">
- <option value="">请选择你的省份</option>
- </select>
- </td>
- <td>城市</td>
- <td><select class="comboBox" id="city" name="city" width="100" >
- <option value="">请选择你的城市</option>
- </select>
- </td>
- <td>区县</td>
- <td><select class="comboBox" id="county" name="county" width="100" >
- <option value="">请选择你的区县</option>
- </select>
- </td>
- </tr>
- </table>
4、初始化插件
- $.seriesComboBoxs({selects : ["#country","#province","#city","#county"],
- ajaxOptions : {"url" : "get_region.php"} });
这里用到二个参数:
- selects 数组,选择框对象名数组,插件会根据数组一直循环下去
- ajaxOptions ajax配置,最关键的是url,即是后台获取数据的脚本路径
5、参数说明
| 参数名 | 数据类型 | 默认参数 | 说明 |
| selects | Array |
选择框对象数组 | |
| ajaxOptions | Object |
ajax配置 |
|
| defaultParentId | Number | 0 | 默认父级id |
| defaultLoadSelectIndex | Number | 0 | 默认读取数据的选择框的索引值,指的是在selects数组的索引值 |
| jsonField | Object | 前端处理后台返回的json数据时所处理的字段(采用默认的即可) | |
| xmlField | Object | 前端处理后台返回的xml数据时所处理的字段(采用默认的即可) | |
| listeners | Object | 事件监听 |
6、事件说明
- render 在组件调用完成后触发
- optionClick 当点击选择框项时触发
- afterLoad 在读取完数据后触发
事件的使用请看第三个例子
- var ComboBox = $.seriesComboBoxs({selects : ["#province3","#city3","#county3"],
- ajaxOptions : {"url" : "get_region.php"},
- defaultParentId : 1,
- listeners : {
- render : function(){
- $(".select-column:not(:first)").hide();
- },
- optionClick : function(index,$option,aSelect){
- var _i = index + 1;
- $(aSelect[_i]).parent(".select-column").show();
- }
- }});
这个例子演示了只有你点击选择框的项后才显示子级的选择框
明河还准备了一个属性aSelectText,包含了选择框的值,这是一个数组
- $("#getText").click(function(){
- alert(ComboBox.aSelectText.join(""));
- })
返回合并后的字符串。
7、get_region.php关键代码说明
后台接受2二个参数:
- parent_id :父级的id
- data_type : 生成的数据类型(默认是json)
留意输出json时我有用到网上的一个函数JSON(),参见include/JSON.php
之所以使用自定义的函数,原因在于php的原生json函数没办法显示中文。
用法如下:
- while ($row = mysql_fetch_array($result)) {
- $json[] = JSON($row);
- }
有问题或发现bug可以在此页面留言,谢谢。

想法不错 写的也很好
我能否把你的代码 改成 省市县乡村 用到项目里面?
恩,可以的,只要维持数据源结构不变即可。
你的这个3级联动做的不错,但是有BUG,选完一遍之后,你在从新选择后,选到最后一级时会后台会加载N次,firebug调试一下,修复之后应该挺不错
原来如此,好的,谢谢提醒。
@fly, jquery提供有数据缓存的功能,这个作为优化建议,应该不难实现。
我已经有加了数据缓存了,不会重复请求。
firebug 开启来,你按顺序多选择几遍,你就发现问题了,很影响效率的,赶紧修复。
问题已经修复了,最新版本为V0.2,你可以到页面中下载新的压缩包
demo没有更新么?这个站点非常好,可以学到很多东西,站长加油,以后我会经常来看看,一起偏重EXT,现在看到就想吐,jquery真的很好,很强大
呃..Demo无效呢…博主..闭关出来看到本信息能给个可用Demo不~~~
非常感谢提醒!这是我的失误,数据库连接信息被我覆盖掉了,现在已经修复了。
@明河共影,- -! 少了哪段代码…博主是不是没有更新Demo?
不是少了代码,在php页面中的数据库连接出错了。已经更新demo了啊,我今天早上刚试过了呢
@明河共影, – -! 我是这样配置的…
数据库: 36ria_com
主机: localhost
用户名: 36ria_com
密码: com2274
function runSQL($rsql) {
$hostname = ‘localhost’;// 数据库服务器
$username = ’36ria_com’; // 数据库用户名
$password = ‘com2274′; // 数据库密码
$dbname = ’36ria_com’; // 数据库名
@MOPVHS, 贵站上的Demo是可以用了..惭愧的是放在虚拟机中实验,我找不出哪里不对~~
…….要使用你本机的数据库,你的本机数据库信息跟我一样?不可能吧。
@明河共影, 是特意新创的数据库…如有雷同纯属巧合….- -!
呵呵,你用firebug查看下后台脚本有没有xml数据返回。
如何设定一些默认值??
如何設定默認值??
呵呵,挺不错,先赞一个,日后再来看文章
你好,我用的是asp的,已经修改为asp版本的。 但是有一个问题。
我使用这个在用户选择所在地。
当提交后,修改时如何结合你的这个程序呢?还请多多指教~
大致上明白你的意思,我写的这个插件没直接提供这种功能,不过可以利用我提供的API来实现这个功能,具体的写法会复杂些,我将在下一个版本中追加新的更为便利的API。
补充: 博主是否提供的有对应修改的时候的 初始化 设置呢?
谢谢啦
下载包里资料不全,能不能提供下全面的资料呢
必要的说明在页面都有了,不知道chinahuhai 想要哪方面的资料,我好提供给你。前二天有个逸乐的朋友给我提了问题,让我想到我写的这个插件有个致命的错误,日后这个插件会重构。
如何设置默认值???
目前没办法设置默认值,这是我的一个失误,下个版本将加入该功能。
最近一个项目中要用到这个地区三级选择功能,在网上找了一下,发现你这个有说明有代码有数据有更新,就准备采用你这个了。谢谢你的辛勤与共享。不过仔细看过代码后发现一些问题,想与你讨论一下。
先介绍一下我的背景,我算一个资深的编程了,不过以前一直使用Perl,这回赶鸭子上PHP, 以前也没使用过Ajax 与 Jason,如果说错了请见谅。
1、最严重问题:发现一个安全隐患,没有判断传递回的参数合法性,可能被SQL注入攻击,数据库完全被控制。
2、看了一下Ajax返回的数据,发现严重冗余。由于这个功能会被频繁使用,传递数据当然需要尽量小。但我发现你的返回数据格式:{“0″:”2″,”region_id”:”2″,”1″:”1″,”parent_id”:”1″,”2″:”北京”,”region_name”:”北京”,”3″:”1″,”region_type”:”1″,”4″:”0″,”agency_id”:”0″}
觉得似乎这样就行:{“0″:”2″,”1″:”北京”} (不熟悉Jason,不知道是否是Jason的要求)。我测试了一下,发现不返回parent_id,region_type 好像没影响使用。还有点不明白为什么数据(如北京)返回两遍?
3、建议还是别同时维持 XML 和 Jason 数据格式, 使用一种就行了,而专注于功能改进。如大家急需的初始值设置。
4、现在是每次选择后去请求一个parent_id下的部分数据,感觉开始加载时一次性返回全部数据可能更好。虽然第一次传输数据会变大,但后续选择不再请求数据,会明显加快,在网络较慢,或需重复使用此功能时明显有优势。而且对服务器的压力小很多。由于这种数据很少变动,返回数据也应有较长的有效期。最好在程序里加一个有效期设置,这样可以调试时马上过期,正式使用后再设长一点。
5、小问题:SQL数据表是teashop_region, 而程序里数据表是region,没法运行,而且数据表名没写在设置地方,估计难住了很多初学者, 我是查看MySQL查询记录才发现错误的,加一个数据表名设置吧。
6、那个区域数据还是不全(如缺少浙江金华义乌),不新(如缺少天津滨海新区)。建议大家使用这个最新最权威的:国国家统计局公布的最新县及县以上行政区划代码(截止2009年12月31日) http://www.stats.gov.cn/tjbz/xzqhdm/t20100623_402652267.htm 。不过需要大家自己想办法导入数据库并变换格式。
非常非常感谢Fox的回复,是明河开博以来看到的最详细最好的回复。提的意见非常到位。关于返回的json数据问题,是这样的,因为我写的php是直接将查询的整个结果集转换成json格式,所以,会出现冗余的问题(xml不会,因为xml我只取结果集的2个字段数据),实际上返回的数据格式只要是{“parent_id”:”1″,”region_name”:”北京”,”region_id”:”2″},前台的处理字段是可以控制的,有个配置参数:jsonField,默认值为{region_id : “region_id”,region_name : “region_name”,parent_id : “parent_id”},这里的字段需要跟后台返回的数据相对应。
@明河共影,
谢谢夸奖,开心
parent_id 也需要返回吗?我没返回parent_id,测试了好像能正常使用,不知是否在另外地方用到?
返回的内容还是有两遍,例如我的 {“0″:”110000″,”aid”:”110000″,”1″:”北京市”,”aname”:”北京市”},如何去掉多余,变成 {“aid”:”110000″,”aname”:”北京市”}? PHP才开始用,没看明白代码如何去掉一遍。
还发现了一点小问题:例如选择了 广东/广州/天河区, 第一个再改选江苏, 这时候如果提交,就成了 江苏/ /天河区,导致逻辑问题。如果有人偷懒只记录最后一个选项,问题就大了。因此在改选择时需要先清空后续选择。
parent_id就是该地区结果集的父地区的id。如果你php生成的json是类似 {“aid”:”110000″,”aname”:”北京市”},那么插件的参数jsonField设置为:{region_id : “aid”, aname: “region_name”,parent_id : “parent_id”}。
发现了问题所在,是mysql_fetch_array搞得鬼。我想当然以为这函数与Perl里面的作用一样,杯具了,习惯思维害死人。实际上PHP不同,缺省是同时返回关联型数组和数值型数组,导致Jason有两遍数据返回。
修正,只需要加入参数MYSQL_ASSOC即可
while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
$json[] = JSON($row);
}
终于返回了我要的数据格式:{“aid”:”110000″,”aname”:”北京市”}
之所以同时支持xml和json,也是朋友向我反映需要不同的数据格式。
初始值设置,这是我写这个插件时,想法上面的一个错误导致没法处理初始值,日后我将重构seriesComboBoxs ,那时候将支持初始值设置。
一次性返回全部数据也是一种处理方式,其实各有优缺点。下个版本我打算同时支持二种加载数据的方式。
数据表的问题,是我的一个失误,呵呵会加以改正,区域数据不全,地区数据库我找了很久,没有找到最好的,只好用ecshop的地区数据库……
@明河共影,
需要的话,我可将整理好的区域数据email给你给大家共享。不过我的变动比较多,不知你是否适合:
1、国内数据就是来自国国家统计局公布的最新县及县以上行政区划代码(截止2009年12月31日),并使用它的ID
2、对一些较长的名称做了手工处理,例如ABCD族自治县改为了AB县便于显示
2、添加了台湾、香港、澳门详细数据,都是3级, 香港/香港岛/湾仔区
3、加了一个国外项与省并列,也是3级:国外/北美洲/美国
恩,好的,你可以发到riahome@126.com上,谢谢了。
文件已经发送。也许另外人也对此有兴趣,你可放在此页面让大家下载。现把文件前面的说明也贴在这吧:
=======
中国三级区域数据库(含港澳台详细及外国国家名)
数据整理 by Fox
Ver. 1.0
更新时间:2010/8/17
数据格式:SQL导出,UTF-8 编码,数据表名 region
数据总量:3774条
数据来源及说明:
1、中华人民共和国国家统计局2010-06-23公布的 最新县及县以上行政区划代码(截止2009年12月31日)
http://www.stats.gov.cn/tjbz/xzqhdm/t20100623_402652267.htm
(全部数据采用,仅对其中部分较长的名称按照习惯做了处理,如 黔西南布依族苗族自治州 => 黔西南州,
彭水苗族土家族自治县 => 彭水县,但在另一列保留了原正规名称便于你其它处理)
2、添加了香港详细区域,也分为3级, 香港 > 香港岛 > 湾仔区
3、添加了台湾详细区域,分为3级
4、添加了澳门详细区域,分为3级
5、添加了外国国家, 分为3级,国外 > 北美洲 > 美国
首先向楼主说一声谢谢!!
但是
你的演示实例中所用的js插件,和下载文件中的不一致吧!
演示文件中的js插件,是ld.js,能更新一下吗?下载的这个版本当更改省份时,县级的没有清空!
能发到我的邮箱吗?!! onroadkeepgoing@126.com谢谢
…….源文件,上次重装系统已经弄丢了,没有了……
下载没有文件啊