使用jQuery+HttpHandler+xml模拟一个三级联动的例子


Posted in Javascript onAugust 09, 2011

如下是实现过程:
第一步:准备xml文件,并放置在网站根目录下,名为Area.xml

<?xml version="1.0" encoding="utf-8" ?> 
<area> 
<province id="1" name="北京"> 
<city id="1" name="北京"> 
<county id="1" name="东城区" /> 
<county id="2" name="西城区" /> 
</city> 
</province> 
<province id="2" name="河北省"> 
<city id="1" name="石家庄市"> 
<county id="1" name="正定县" /> 
<county id="2" name="灵寿县" /> 
</city> 
<city id="2" name="邯郸市"> 
<county id="1" name="邯郸县" /> 
<county id="2" name="永年县" /> 
</city> 
</province> 
<province id="3" name="海南省"> 
<city id="1" name="海口市"> 
<county id="1" name="龙华区" /> 
<county id="2" name="秀英区" /> 
<county id="3" name="美兰区" /> 
</city> 
<city id="2" name="三亚市"> 
<county id="1" name="天涯镇" /> 
<county id="2" name="凤凰镇" /> 
</city> 
</province> 
</area>

第二步:创建与xml文件中定义的元素对应的实体类。
<province/>对应province类
public class Province 
{ 
private string id; 
/// <summary> 
/// 编号 
/// </summary> 
public string Id 
{ 
get { return id; } 
set { id = value; } 
} 
private string name; 
/// <summary> 
/// 名称 
/// </summary> 
public string Name 
{ 
get { return name; } 
set { name = value; } 
} 
}

<city/>对应City类:
public class City 
{ 
private string id; 
/// <summary> 
/// 编号 
/// </summary> 
public string Id 
{ 
get { return id; } 
set { id = value; } 
} 
private string name; 
/// <summary> 
/// 名称 
/// </summary> 
public string Name 
{ 
get { return name; } 
set { name = value; } 
} 
}

<county/>对应county类:
public class County 
{ 
private string id; 
/// <summary> 
/// 编号 
/// </summary> 
public string Id 
{ 
get { return id; } 
set { id = value; } 
} 
private string name; 
/// <summary> 
/// 名称 
/// </summary> 
public string Name 
{ 
get { return name; } 
set { name = value; } 
} 
}

第三步:编写服务器端处理程序类:Handler.cs
/// <summary> 
2 /// 处理程序 
3 /// </summary> 
4 public class Handler : IHttpHandler 
5 { 
6 
7 private static XDocument doc; 
8 private string filePath = HttpContext.Current.Server.MapPath("~/Area.xml"); 
9 //javascript序列化类 
private static JavaScriptSerializer jss = new JavaScriptSerializer(); 
public void ProcessRequest(HttpContext context) 
{ 
context.Response.ContentType = "text/plain"; 
string result = "failure";//默认返回结果为失败 
HttpRequest req = context.Request; 
string province = req["province"];//获取用户选择的省的编号 
string city = req["city"];//获取用户选择的市的编号 
string county = req["county"];//获取用户选择的县的编号 
string type = req["type"];//获取用户需要获取的省市县列表的类型 
InitDoc(); 
if (type.HasValue()) 
{ 
switch (type.ToLower()) 
{ 
case "province"://如果用户需要获取省级列表 
result = jss.Serialize(GetProvinceList()); 
break; 
case "city"://如果用户需要获取的是市级列表 
result = jss.Serialize(GetCityListByProvince(province)); 
break; 
case "county"://如果用户需要获取的是县级列表 
result = jss.Serialize(GetCountyListByCity(province, city)); 
break; 
default: 
break; 
} 
} 
//将结果以文本的格式返回给客户端 
context.Response.Write(result); 
} 
/// <summary> 
/// 初始化文档对象 
/// </summary> 
private void InitDoc() 
{ 
if (doc == null) 
{ 
doc = XDocument.Load(filePath); 
} 
} 
/// <summary> 
/// 初始化省级列表 
/// </summary> 
private List<Province> GetProvinceList() 
{ 
List<Province> list = new List<Province>(); 
if (doc != null) 
{ 
XElement root = doc.Root; 
foreach (var prov in root.XPathSelectElements("province")) 
{ 
list.Add(new Province() 
{ 
Id = prov.Attribute("id").Value, 
Name = prov.Attribute("name").Value 
}); 
} 
} 
return list; 
} 
/// <summary> 
/// 根据省级编号获取市级编号 
/// </summary> 
/// <param name="provId">省级编号</param> 
private List<City> GetCityListByProvince(string provId) 
{ 
List<City> list = new List<City>(); 
if (doc != null) 
{ 
XElement root = doc.Root; 
//xpath表达式:/area/province[@id='1']/city 
string queryPath = "/area/province[@id='" + provId + "']/city"; 
foreach (var city in root.XPathSelectElements(queryPath)) 
{ 
list.Add(new City() 
{ 
Id = city.Attribute("id").Value, 
Name = city.Attribute("name").Value 
}); 
} 
} 
return list; 
} 
/// <summary> 
/// 根据省级编号和市级编号获取县级编号 
/// </summary> 
/// <param name="provId">省级编号</param> 
/// <param name="cityId">市级编号</param> 
private List<County> GetCountyListByCity(string provId, string cityId) 
{ 
List<County> list = new List<County>(); 
if (doc != null) 
{ 
XElement root = doc.Root; 
string queryPath = "/area/province[@id='" + provId + "']/city[@id='" + cityId + "']/county"; 
foreach (var county in root.XPathSelectElements(queryPath)) 
{ 
list.Add(new County() 
{ 
Id = county.Attribute("id").Value, 
Name = county.Attribute("name").Value 
}); 
} 
} 
return list; 
} 
public bool IsReusable 
{ 
get 
{ 
return false; 
} 
} 
}

在这里,查询xml我采用的是System.Xml.XPath命名空间下的XPathSelectElements(string xpath)方法和XPathSelectElement(string xpath)方法,在根据省级编号获取市级编号的方法里面,我使用了xpath表达式(假设传入的省级编号为1):/area/province[@id='1']/city,这个表达式以“/”开头,表示使用绝对路径,因为area为根节点所以从area开始,接着它下面有province元素,当我想获取area下所有province元素中id属性值为1的province元素时,我可以使用/area/province[@id='1'],即在province后面加上[@id='1']这个条件,这时我就获取到了area下id属性为1的province元素了。接着我要获取该province元素下所有的city,那么只需在后面加上/city即可,所以最终的xpath表达式为:/area/province[@id='1']/city。
还有,因为此查询的xml是在当前网站的根目录,如果是在其它地方,那么在查询的时候要加上namespace
将从xml文件中读取到的值组装成对应的实体对象只后,我使用了System.Web.Script.Serialization命名空间下的JavaScriptSerializer类中的Serialize方法将得到的实体对象序列化成json数据返回给客户端。
第四步:编写html和js。
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
<title>省市县三级联动下拉列表</title> 
<script src="Scripts/jquery-1.4.1.min.js" type="text/javascript"></script> 
<script type="text/javascript"> 
$(function () { 
$.post("/Handler.ashx", { "type": "province" }, function (data, status) { 
if (status == "success") { 
if (data != "failure") { 
data = $.parseJSON(data); //解析服务器返回的json数据 
for (var i = 0; i < data.length; i++) { 
var value = data[i].Id + ":" + data[i].Name; //设置option选项的值,格式为:"编号:名称" 
$("#province").append("<option value='" + value + "'>" + data[i].Name + "</option>"); 
} 
} 
} 
}, "text"); 
$("#province").change(function () { 
var selectValue = $(this).val(); //获取选择的省级option的值 
var provId = selectValue.split(':')[0]; //取出编号 
var provTxt = selectValue.split(':')[1]; //取出名称 
$("#txtProvince").html(provTxt); //显示选择的省的名称 
$("#city").html("<option>==请选择市==</option>"); //当省级改变时将市级清空 
$("#county").html("<option>==请选择县==</option>"); //当省级改变时将县级清空 
$.post("/Handler.ashx", { "province": provId, "type": "city" }, function (data, status) { 
if (status == "success") { 
if (data != "failure") { 
data = $.parseJSON(data); 
for (var i = 0; i < data.length; i++) { 
var value = data[i].Id + ":" + data[i].Name; 
$("#city").append("<option value='" + value + "'>" + data[i].Name + "</option>"); 
} 
} 
} 
}, "text"); 
}); 
$("#city").change(function () { 
var provId = $("#province").val().split(':')[0]; 
var selectValue = $(this).val(); //同上 
var cityId = selectValue.split(':')[0]; //同上 
var cityTxt = selectValue.split(':')[1]; //同上 
$("#txtCity").html(cityTxt); //显示选择的市的名称 
$("#county").html("<option>==请选择县==</option>"); //同上 
$.post("/Handler.ashx", { "province": provId, "city": cityId, "type": "county" }, function (data, status) { 
if (status == "success") { 
if (data != "failure") { 
data = $.parseJSON(data); 
for (var i = 0; i < data.length; i++) { 
var value = data[i].Id + ":" + data[i].Name; 
$("#county").append("<option value='" + value + "'>" + data[i].Name + "</option>"); 
} 
} 
} 
}, "text"); 
}); 
$("#county").change(function () { 
$("#txtCounty").html($(this).val().split(':')[1]); //显示选择的县的名称 
}); 
}); 
</script> 
</head> 
<body> 
<!--省--> 
<select id="province" name="province"> 
</select> 
<!--市--> 
<select id="city" name="city"> 
</select> 
<!--县--> 
<select id="county" name="county"> 
</select> 
<br /> 
<span id="txtProvince" style="color: #ff0000;"></span>- <span id="txtCity" style="color: #ff0000;"></span>- <span id="txtCounty" style="color: #ff0000;"></span> 
</body> 
</html>

关于使用jQuery与服务器通信,我使用的是$.post方法,该方法的具体使用可以参考jQuery官方文档,这里我想说的是,遍历后通过对象.属性访问时,这个属性的名字是区分大小写的,这个名字是服务器端定义的名字,因为服务器序列化的是服务器端的实体对象。
在这个例子中,关键点就是如何使用XPath表达式,如何调用System.Xml.XPath命名空间下的XPathSelectElements(string xpath)方法。
最终结果如下图:
使用jQuery+HttpHandler+xml模拟一个三级联动的例子
代码13,31,50行可以优化。
不建议多次修改DOM结构,可以拼接字符串后一次append
数据源是xml,我会用xslt来解析xml直接输出<option>,这样就不用再前台拼接字符串了。要求所有节点ID不能有相同。
<select id="province" name="province" next="#city"> 
</select> 
<select id="city" name="city" next="#county"> 
<option>==请选择市==</option> 
</select> 
</form> 
<select id="county" name="county"> 
<option>==请选择县==</option> 
</select> <script type="text/javascript"> 
$("#province,#city").change(function () { 
var nextSelect = $(this.getAttribute("next")); 
//if (nextSelect.size() > 0) { 
nextSelect.find("option:gt(0)").remove(); 
var _id = $(this).find("option:selected").val(); 
var query = { parentId: _id }; 
$.get("/Handler.ashx", query, function (data, status) { 
//... 
nextSelect.append("<option>...</option>...."); 
}); 
//} 
}); 
</script>
Javascript 相关文章推荐
jQuery中DOM树操作之使用反向插入方法实例分析
Jan 23 Javascript
JS组件Bootstrap Table表格行拖拽效果实现代码
Aug 27 Javascript
js确认框confirm()用法实例详解
Jan 07 Javascript
AngularJS页面访问时出现页面闪烁问题的解决
Mar 06 Javascript
JS实现支持Ajax验证的表单插件
Mar 24 Javascript
javascript动画之模拟拖拽效果篇
Sep 26 Javascript
JavaScript中动态向表格添加数据
Jan 24 Javascript
jQuery图片瀑布流的简单实现代码
Mar 15 Javascript
在 Angular-cli 中使用 simple-mock 实现前端开发 API Mock 接口数据模拟功能的方法
Nov 28 Javascript
ES6小技巧之代替lodash
Jun 07 Javascript
vue实现pdf文档在线预览功能
Nov 26 Javascript
js实现小时钟效果
Mar 25 Javascript
js 分页全选或反选标识实现代码
Aug 09 #Javascript
js字符串的各种格式的转换 ToString,Format
Aug 08 #Javascript
Jquery ajax传递复杂参数给WebService的实现代码
Aug 08 #Javascript
jquery学习笔记 用jquery实现无刷新登录
Aug 08 #Javascript
基于jQuery实现的水平和垂直居中的div窗口
Aug 08 #Javascript
关于hashchangebroker和statehashable的补充文档
Aug 08 #Javascript
基于jQuery的前端数据通用验证库
Aug 08 #Javascript
You might like
投票管理程序
2006/10/09 PHP
php session应用实例 登录验证
2009/03/16 PHP
zf框架的校验器使用使用示例(自定义校验器和校验器链)
2014/03/13 PHP
php修改上传图片尺寸的方法
2015/04/14 PHP
php 生成签名及验证签名详解
2016/10/26 PHP
php 解决扫描二维码下载跳转问题
2017/01/13 PHP
thinkPHP5框架auth权限控制类与用法示例
2018/06/12 PHP
JS无限极树形菜单,json格式、数组格式通用示例
2013/07/30 Javascript
让html页面不缓存js的实现方法
2014/10/31 Javascript
jQuery实现冻结表头的方法
2015/03/09 Javascript
JS实现保留n位小数的四舍五入问题示例
2016/08/03 Javascript
js 数字、字符串、布尔值的转换方法(必看)
2017/04/07 Javascript
浅谈Node.js 沙箱环境
2018/05/15 Javascript
微信小程序画布圆形进度条显示效果
2020/11/17 Javascript
Vue中的v-for指令不起效果的解决方法
2018/09/27 Javascript
vue使用showdown并实现代码区域高亮的示例代码
2019/10/17 Javascript
[36:05]DOTA2亚洲邀请赛 3.31 小组赛 A组 Liquid vs Optic
2018/04/01 DOTA
Python使用htpasswd实现基本认证授权的例子
2014/06/10 Python
对Python新手编程过程中如何规避一些常见问题的建议
2015/04/01 Python
Python的Django框架中的数据库配置指南
2015/07/17 Python
Python实用技巧之利用元组代替字典并为元组元素命名
2018/07/11 Python
Python实现爬取马云的微博功能示例
2019/02/16 Python
python requests证书问题解决
2019/09/05 Python
.dcm格式文件软件读取及python处理详解
2020/01/16 Python
Python requests模块基础使用方法实例及高级应用(自动登陆,抓取网页源码)实例详解
2020/02/14 Python
Python telnet登陆功能实现代码
2020/04/16 Python
浅析pandas随机排列与随机抽样
2021/01/22 Python
法律系毕业生自荐信范文
2014/03/27 职场文书
《三个小伙伴》教学反思
2014/04/11 职场文书
幼儿园大班家长评语
2014/04/17 职场文书
2014年化验室工作总结
2014/11/21 职场文书
食品质检员岗位职责
2015/04/08 职场文书
2015年机关党委工作总结
2015/05/23 职场文书
董事长助理工作总结2015
2015/07/23 职场文书
2016国培学习心得体会
2016/01/08 职场文书
2016年度师德标兵先进事迹材料
2016/02/26 职场文书