Ajax实现动态的二级级联菜单
今天花了点时间用Ajax实现了一个二级级联菜单。整理总结一下。为了把重点放在Ajax和级联菜单的实现上,本文省略了数据库建表语句和操作数据库的代码!
数据库建表语句就不帖出来了。主要有两张表,区域表:district。街道表:street。区域表和街道表是一对多关系,一个区域可以有零到多个街道,一条街道属于一个区域。数据如下:

页面代码 index.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="js/js.js"></script>
<title>Insert title here</title>
</head>
<body>
<select id="district" onchange="cascade(this.value)" >
<option value="-1">请选择</option>
<c:forEach items="${districts }" var="district">
<option value="${district.id }">${district.name }</option>
</c:forEach>
</select>
<select id="street" onchange="alert(this.value)">
<option>请选择</option>
</select>
</body>
</html>
初始化主页面一级菜单列表的Servlet代码 InitServlet.java:
package cascade.servlet;
import java.io.IOException;
import java.util.List; import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import cascade.entity.District;
import cascade.service.DistrictService; public class InitServlet extends HttpServlet{ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
} protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
/*
* DistrictService ds为操作数据库的对象.
* 调用该对象的getAllDistrict()方法,可以从数据库中取得所有的区域信息,封装为List<District>对象,并返回。
* 其中District是数据库District表的实体类
* 为了把重点放在Ajax和级联菜单的实现上,本文省略了操作数据库的代码!!!
*/
DistrictService ds = new DistrictService();
List<District> districts = ds.getAllDistrict();
//List<District>对象存在request范围中,并转向到主页
req.setAttribute("districts", districts);
req.getRequestDispatcher("index.jsp").forward(req, resp);
} }
web配置文件 web.xml:
在web.xml中添加如配置代码
<servlet>
<servlet-name>init</servlet-name>
<servlet-class>cascade.servlet.InitServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>init</servlet-name>
<url-pattern>/index</url-pattern>
</servlet-mapping>
此时,在浏览器中访问 InitServlet.java (假设项目名为AjaxCascade,访问地址就是:http://localhost:8080/AjaxCascade/index)
数据库的区域数据就已经填到第一级菜单项中了。

此时页面的源代码可以看到下拉菜单(select)里每一项(option)的value也是从数据库里取到的:
<select id="district" onchange="cascade(this.value)" >
<option value="-1">请选择</option>
<option value="1001">天河区</option>
<option value="1002">越秀区</option>
<option value="1003">海珠区</option>
<option value="1005">番禺区</option>
<option value="1000">白云区</option>
<option value="1004">花都区</option>
</select>
现在开始现实街道下拉菜单(也就是页面上id为street的select)的动态获取。
我们知道,但区域菜单的值改变时,街道菜单的值也要动态的发生改变(如区域选择“天河区”,街道菜单就应该动态加上“中山大道“这一项,如区域选择“海珠区”,街道菜单就应该动态加上“昌岗路”,并删除“中山大道“)。
为了现实上面所说的功能,要为区域菜单添加 onchange 事件的处理:onchange="cascade(this.value)" 当区域菜单值发生改变时调用cascade方法,并把自己的value属性传递进去。
cascade代码如下 js.js:
//XMLHttpRequest组件
var xhs;
//区域菜单的值发生改变时调用该方法,并把区域菜单当前的value传递进来
function cascade(id){
//当id不大于0时,说明当前选择的是“请选择”这一项,则不做操作
if(id>0){
//请求字符串,把区域的id作为页面参数传到后台
var url="cascade?id="+id;
//创建XMLHttpRequest组件
xhs=new XMLHttpRequest();
//设置回调函数,processReuqest方法的定义在下面
xhs.onreadystatechange=processReuqest;
//打开与服务器的地址连接
xhs.open("post", url, true);
//发送请求
xhs.send(null);
}
} //processReuqest方法作为回调方法
function processReuqest(){
if(xhs.readyState==4){
if(xhs.status==200){
//创建新的select节点
var newSelect=document.createElement("select");
newSelect.id="street";
//为新创建的select节点添加onchange事件,以便测试用
newSelect.onchange=function test(){
alert(this.value);
};
//为新创建的select节点添加option节点
var op=document.createElement("option");
op.value=-1;
op.innerHTML="请选择";
newSelect.appendChild(op);
//得到完成请求后返回的字串符
var str = xhs.responseText;
//根据返回的字符串为新创建的select节点添加option节点
var arr1=str.split(",");
for(var i=0;i<arr1.length;i++){
var arr2=arr1[i].split("=");
var child=document.createElement("option");
child.innerHTML=arr2[1];
child.value=arr2[0];
newSelect.appendChild(child);
}
//用新select节点替换旧的select节点
var select = document.getElementById("street");
document.body.replaceChild(newSelect, select);
}
}
}
XMLHttpRequest 对象:XMLHttpRequest 对象提供了对 HTTP 协议的完全的访问,包括做出 POST 和 HEAD 请求以及普通的 GET 请求的能力。XMLHttpRequest 可以同步或异步地返回 Web 服务器的响应,并且能够以文本或者一个 DOM 文档的形式返回内容。尽管名为 XMLHttpRequest,它并不限于和 XML 文档一起使用:它可以接收任何形式的文本文档。XMLHttpRequest 对象是名为 AJAX 的 Web 应用程序架构的一项关键功能。
创建XMLHttpRequest 对象:尽管大部份浏览器都支持 new XMLHttpRequest() 来得到 XMLHttpRequest 对象,但IE浏览器和其他Web浏览器返回的 XMLHttpRequest 对象实例是不相同的,为了支持更多浏览器,建议编码时如下所示的代码创建XMLHttpRequest 实例。
function createXmlHttpRequest(){
if(window.ActiveXObject){
return new ActiveXObject("Microsoft.XMLHTTP");
}else if(window.XMLHttpRequest){
return new XMLHttpRequest();
}
}
open(method,url,async)方法:建立于服务器的连接,method参数指定请求的HTTP方法。URL 参数指定请求的地址。acync 参数指定是否使用异步请求,其值为 true 或 false。
send(content)方法:发送请求,content参数指定请求的参数。当send方法不配置参数,即xhr.send()时,在IE中能够正常运行,但在Firefox中却不能,所以,建议最好加上null 。
onreadystatechange属性:指定XMLHttpRequest对象的回调函数。onreadystatechange属性作用与文本框的onblur等属性一样,是事件处理属性,即当 XMLHttpRequest 的状态发生改变时,XMLHttpRequest 对象都会解发onreadystatechange所指定的函数。
readyState属性:XMLHttpRequest的状态信息。XMLHttpRequest对象有如下几种状态。
0:XMLHttpRequest对象没有完成初始化,此时,已经创建一个XMLHttpRequest对象,但是还没有初始化。
1:XMLHttpRequest对象开始发送请求,此时,代码已经调用open()方法并且XMLHttpRequest已经准备好把一个请求发送到服务器。
2:XMLHttpRequest对象的请求发送完成。此时,已经通过send()方法把一个请求发到服务器端,但是还没有收到一个响应。
3:XMLHttpRequest对象开始读取响应。此时,已经接收到HTTP响应头部信息,但是消息体部分还没有完全接收结束。
4:XMLHttpRequest对象读取响应结束。些时,响应已被完全接收。
status属性:HTTP的状态码,仅当readyState的值为3或4时,status属性才可用。status属性如下。
200:服务器响应正常。
400:无法找到请求的资源。
403:没有访问权限。
404:访问资源不存在。
500:服务器内部错误。
responseText属性:获得响应的文本。当readyState值为0、1、2时,reponseText包含一下空字符串。当readyState值为3时,响应中包含还未完成的响应信息。当readyState值为4时,readyState包含完整的响应信息。
接下来是后台代码的实现,从cascade方法可以看到,XMLHttpRequest对象是请求到名为cascade的地址上的。
CascadeServlet.java:
package cascade.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List; import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import cascade.entity.District;
import cascade.entity.Street;
import cascade.service.StreetService; public class CascadeServlet extends HttpServlet{ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
} protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
int id =Integer.parseInt(req.getParameter("id"));
District district=new District();
district.setId(id); /*
* StreetService ss为操作数据库的对象.
* 调用该对象的getAllStreet()方法,可以从数据库中取得所有的区域信息,封装为List<Street>对象,并返回。
* 其中Street是数据库Street表的实体类
* 为了把重点放在Ajax和级联菜单的实现上,本文省略了操作数据库的代码!!!
*/
StreetService ss=new StreetService();
List<Street> streets=ss.getAllStreet(district);
//把得到的街道对象集合拼接成字符串文本
StringBuffer sb=new StringBuffer();
for(int i=0;i<streets.size();i++){
sb.append(streets.get(i).getId()).append("=").append(streets.get(i).getName());
if(i!=streets.size()-1){
sb.append(",");
}
}
//servlet不转向或重定向到任何页面,使用resp.getWriter().print()方法可以把文本响应给XMLHttpRequest对象
PrintWriter out = resp.getWriter();
out.print(sb.toString());
out.flush();
out.close();
} }
在web.xml中的配置:
<servlet>
<servlet-name>cascade</servlet-name>
<servlet-class>cascade.servlet.CascadeServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>cascade</servlet-name>
<url-pattern>/cascade</url-pattern>
</servlet-mapping>
完工,效果如下:



Ajax实现动态的二级级联菜单的更多相关文章
- php 二级级联菜单
找了很多个级联的菜单,都不好用,自己弄个简单点的,共享下,希望有朋友用得着 <?php //建立表country,有三个字段Id,parentId,area. $pro = $_POST['pr ...
- JS动态级联菜单
JS动态级联菜单是前端常用的一个功能,特此抽时间研究了下,附上代码 <html> <head> <meta charset="utf-8" /> ...
- 使用AJAX(阿贾克斯)创建级联菜单
1. html页面 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> < ...
- javascript实现select菜单/级联菜单(用Rails.ajax实现发送请求,接收响应)
在购物网站,填写收货地址的时候,会出现XX省XX市XX区的下拉菜单,如何实现此功能?思路是什么? 功能设置: 当选择省select菜单后,市的select菜单为这个省的城市列. 当选择市菜单后,区菜单 ...
- JS实战 · 级联菜单选择省份和城市(两种)
DOM编程步骤.思路 1.定义界面: 通过html标签将数据进行封装: 2.定义一些静态样式: 利用css: 3.需要动态地完成的和用户的交互: a:明确事件源: ...
- C#动态加载树菜单
在做权限系统的时候,需要有一个树形的菜单.下图就是一个树形菜单的样式 但问题是,我们可以实现写死的树形菜单.什么是写死的?就是在前台代码中写好要加载的树形菜单是什么样子的.但是我们权限系统的要求是动态 ...
- 前台JS(Jquery)调用后台方法 无刷新级联菜单示例
前台用AJAX直接调用后台方法,老有人发帖提问,没事做个示例 下面是做的一个前台用JQUERY,AJAX调用后台方法做的无刷新级联菜单 http://www.dtan.so CasMenu.aspx页 ...
- Excel操作之级联菜单
设置级联菜单主要用的是excel的数据验证功能.下面以简单的设置城市选择框为例: 1.准备好数据 2.给所有省份起个名称(例如:省份),然后同样方法给每个省份所对应的城市以其省份命名,(例如:南京.苏 ...
- js进阶 9-12 js如何实现级联菜单 (章节测试)
js进阶 9-12 js如何实现级联菜单 (章节测试) 一.总结 一句话总结: 1.js如何实现级联菜单 ? 二维数组,以第一级菜单的文本值做键,以对应的二级菜单选项的文本做值 2.用哪个属性可以获 ...
随机推荐
- Linux三种关机/重启系统的命令
Linux提供了三种关机/重启系统的命令:shutdown.halt和reboot.这三个命令在一般情况下只有 系统的超级用户(一般是指root)才可以执行.输入没有参数的shutdown命令,两分钟 ...
- URI--http://zh.wikipedia.org/wiki/%E7%BB%9F%E4%B8%80%E8%B5%84%E6%BA%90%E6%A0%87%E5%BF%97%E7%AC%A6
维基百科,自由的百科全书 在电脑术语中,统一资源标识符(Uniform Resource Identifier,或URI)是一个用于标识某一互联网资源名称的字符串. 该种标识允许用户对网络中( ...
- 使用dbstart 和dbshut 脚本来自动化启动和关闭数据库
使用dbstart 和dbshut 脚本来自动化启动和关闭数据库:1. 登录用户root.2. 编辑你的平台的oratab 文件.打开文件/etc/oratab:文件里数据库条目为以下格式:SID:O ...
- java基础之 第一步 :jdk安装配置
Java 开发环境配置 在本章节中我们将为大家介绍如何搭建Java开发环境. window系统安装java 下载JDK 首先我们需要下载java开发工具包JDK,下载地址:http://www.ora ...
- B - A + B Again
Description There must be many A + B problems in our HDOJ , now a new one is coming. Give yo ...
- xaml控件样式大全(太有用了)C#
地址:链接:http://pan.baidu.com/s/1jGlMyEi 密码:zaeg http://blog.csdn.net/lhx527099095/article/category/943 ...
- asp.net 获取当前url地址
设当前页完整地址是:http://www.jb51.net/aaa/bbb.aspx?id=5&name=kelli "http://"是协议名 "www.jb5 ...
- mysql中,执行delete语句时出现Lock wait timeout exceeded问题
问题描述: 当我插入一条记录时,在调用save方法的时候出现了异常(记录重复了),导致了后面的commit语句不能执行了.这时我在数据库中删除重复记录时发现该表已经被锁上了.即出现错误.但过了一会再次 ...
- Python之路第十一天,高级(3)-Python操作 Memcached、Redis
Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的速度 ...
- python提取隐含结构的字符串
当我用Stanford CoreNLP和A Python wrapper for the Java Stanford Core NLP tools(NLP的python调用工具)进行句法分析时,遇到一 ...