无限级联动下拉框地区分类选择的实现

Posted by jintang on 2012-09-14

一、功能概要

不多说,先上图:

这种地址下来选择框经常都会在开发中遇到,那么如果我们对这种地址的选择方式提出两个要求:

  1. 选择的地区信息是需要动态变更的,即是可以通过后台添加地区信息,并从数据库中动态地读取出来;
  2. 当选择某一省或某一市的时候,该地址下的子地区也需要同时动态更新,并且是三级联动更新的。

如果能够实现以上的两个需求,那么无论是从地区分类的管理上或者是用户的体验上都是非常实用和容易被人接受的。

下面就分享一下我是如何实现这个功能。

二、开发思路

实现这个功能,我们需要几样东西:

  1. 一个存放地址分类的 数据表。
  2. 当选择某一地区信息时,用于触发加载该分类的子分类数据的 事件及 事件处理函数。
  3. 请求子类数据的地址及对应的获得子类的 请求函数。

我想先来整理一下思路:

  1. 设计存放地址分类的数据表 ;
  2. 先从视图出发,构造“带有触发加载子类下拉框事件”的顶级分类的下拉框;
  3. 编写事件函数,确定子类数据请求地址,使用ajax动态向请求子类数据 ;
  4. 编写请求函数。

三、代码解析

附件中代码的安装方法:

  1. 先创建数据库,默认为area,把sql目录下的category.sql导入到area数据库中
  2. 修改database_connect.php中的数据库信息为对应的数据库信息。
  3. 浏览器请求运行index.php

以下针对各个文件的代码解释:

1. 数据库结构 category.sql

代码:

1
2
3
4
5
6
7
 CREATE TABLE IF NOT EXISTS `category` (
`cate_id` int(11) NOT NULL AUTO_INCREMENT,
`parent_id` int(11) NOT NULL DEFAULT '0',
`name` varchar(128) NOT NULL,
PRIMARY KEY (`cate_id`),
UNIQUE KEY `cate_id` (`cate_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=25 ;

说明:cate_id 用于存放当期地区分类的id,parent_id用于存放父类id,name为地区分类的名字

2. database_connect.php

代码:

1
2
3
4
5
6
7
8
9
10
11
<?php
$host = 'localhost';
$database = 'area';
$login = 'root';
$pass = '';

$dbconnect = mysql_connect($host, $login, $pass);
if (!$dbconnect) { die("数据库链接出错!"); }
mysql_query("set names utf8", $dbconnect);
mysql_select_db($database, $dbconnect);
?>

这里不多说,就是链接数据库,大家都懂

3. getArea.php

该文件用于处理动态请求,接收请求提交的cate_id,然后返回该cate_id下的子类数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php

include "database_connect.php"; // 包含数据库链接操作文件

$cate_id = isset($_POST['cate_id']) ? (int)$_POST['cate_id'] : -1; // 获得提交参数cate_id

$sql = "SELECT `cate_id`, `parent_id`, `name` FROM category WHERE `parent_id` = {$cate_id};"; // 把参数cate_id作为父类id查找其子类所有地区分类

$result = mysql_query($sql, $dbconnect);

while($row = mysql_fetch_array($result))
{
$categories[] = $row; // 把结果放如一维数组中
}

if (!empty($categories)) {
echo json_encode($categories); // 把结果以json加密,以json对象返回结果
} else {
return false;
}

?>

4. index.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">

<title>Multi Area Select</title>

<script type="text/javascript" charset="utf-8" src="js/jquery-1.7.min.js"></script>

</head>
<body>

<?php

/**
* database connect
*/
include "database_connect.php";

/**
* 查找顶级地址分类(parent_id = 0)
*/
$sql = "SELECT `cate_id`, `parent_id`, `name` FROM category WHERE `parent_id` = 0;";
$result = mysql_query($sql, $dbconnect);
while($row = mysql_fetch_array($result))
{
$categories[] = $row;
}

?>

<!-- 此处必须加上onchange事件和事件函数ajaxGetArea(),以便当选择时触发 -->
<select onchange="ajaxGetArea(this)" name="cate_id" id="area">

<?php foreach ($categories as $cate): ?>
<option value="<?php echo $cate['cate_id']?>"><?php echo $cate['name'];?></option>
<?php endforeach;?>

</select>

<script type="text/javascript">

jQuery(function($) {
ajaxGetArea($("#area")); // 先执行一次,以便显示所有地区信息
});

/**
* 动态加载地区信息
* @params obj
*/
function ajaxGetArea(obj)
{
/**
* 请求地址
*/
var link = "getArea.php";
/**
* 请求数据
*/
$.post(
link,
{
/**
* 参数
*/
cate_id : $(obj).val()
},
function(data)
{
/**
* 清除子类的select
*/
$(obj).nextAll("select").each(function() {
$(this).remove();
});

if (data) {

/**
* 构造子类select的html
*/
var select = null;
select = "<select name=\"cate_id\" onchange=\"ajaxGetArea(this)\">"; // 此处注意添加onchange事件
$.each(data, function(key, item) {
select += "<option value="+item.cate_id+">"+item.name+"</option>";
});
select += "</select>";

/**
* 插入到右侧
*/
$(obj).after(select);

/**
* 触发下一个子类select的动态加载
*/
$(obj).next('select').trigger('change', function() {
ajaxGetArea($(this)); // 此处实现递归
});

/**
* 更新name的位置
*/
$(obj).removeAttr('name');
$(obj).next('select').attr('name', 'cate_id');
}
},
'json'
);
}

</script>

</body>
</html>

四、总结

功能以简单的方式实现,实现了基本的地址分类选择,是常见和常用的功能。
实现方法总体来说只分两个点:

  1. 动态请求地址分类数据
  2. 获得数据后变更当前数据,同时以递归的方式实现多级联动