zoukankan      html  css  js  c++  java
  • 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:

     1 package cascade.servlet;
     2 import java.io.IOException;
     3 import java.util.List;
     4 
     5 import javax.servlet.ServletException;
     6 import javax.servlet.http.HttpServlet;
     7 import javax.servlet.http.HttpServletRequest;
     8 import javax.servlet.http.HttpServletResponse;
     9 
    10 import cascade.entity.District;
    11 import cascade.service.DistrictService;
    12 
    13 
    14 public class InitServlet extends HttpServlet{
    15 
    16     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    17         doPost(req, resp);
    18     }
    19 
    20     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    21         req.setCharacterEncoding("UTF-8");
    22         resp.setCharacterEncoding("UTF-8");
    23         /*
    24          * DistrictService  ds为操作数据库的对象.
    25          * 调用该对象的getAllDistrict()方法,可以从数据库中取得所有的区域信息,封装为List<District>对象,并返回。
    26          * 其中District是数据库District表的实体类 
    27          * 为了把重点放在Ajax和级联菜单的实现上,本文省略了操作数据库的代码!!!
    28          */
    29         DistrictService ds = new DistrictService();
    30         List<District> districts = ds.getAllDistrict();
    31         //List<District>对象存在request范围中,并转向到主页
    32         req.setAttribute("districts", districts);
    33         req.getRequestDispatcher("index.jsp").forward(req, resp);
    34     }
    35     
    36 }

    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:

     1 //XMLHttpRequest组件
     2 var xhs;
     3 //区域菜单的值发生改变时调用该方法,并把区域菜单当前的value传递进来
     4 function cascade(id){
     5     //当id不大于0时,说明当前选择的是“请选择”这一项,则不做操作
     6     if(id>0){
     7         //请求字符串,把区域的id作为页面参数传到后台
     8         var url="cascade?id="+id;
     9         //创建XMLHttpRequest组件
    10         xhs=new XMLHttpRequest();
    11         //设置回调函数,processReuqest方法的定义在下面
    12         xhs.onreadystatechange=processReuqest;
    13         //打开与服务器的地址连接
    14         xhs.open("post", url, true);
    15         //发送请求
    16         xhs.send(null);
    17     }
    18 }
    19 
    20 //processReuqest方法作为回调方法
    21 function processReuqest(){
    22     if(xhs.readyState==4){
    23         if(xhs.status==200){
    24             //创建新的select节点
    25             var newSelect=document.createElement("select");
    26             newSelect.id="street";
    27             //为新创建的select节点添加onchange事件,以便测试用
    28             newSelect.onchange=function test(){
    29                 alert(this.value);
    30             };
    31             //为新创建的select节点添加option节点
    32             var op=document.createElement("option");
    33             op.value=-1;
    34             op.innerHTML="请选择";
    35             newSelect.appendChild(op);
    36             //得到完成请求后返回的字串符
    37             var str = xhs.responseText;
    38             //根据返回的字符串为新创建的select节点添加option节点
    39             var arr1=str.split(",");
    40             for(var i=0;i<arr1.length;i++){
    41                 var arr2=arr1[i].split("=");
    42                 var child=document.createElement("option");
    43                 child.innerHTML=arr2[1];
    44                 child.value=arr2[0];
    45                 newSelect.appendChild(child);
    46             }
    47             //用新select节点替换旧的select节点
    48             var select = document.getElementById("street");
    49             document.body.replaceChild(newSelect, select);
    50         }
    51     }
    52 }

    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:

     1 package cascade.servlet;
     2 import java.io.IOException;
     3 import java.io.PrintWriter;
     4 import java.util.List;
     5 
     6 import javax.servlet.ServletException;
     7 import javax.servlet.http.HttpServlet;
     8 import javax.servlet.http.HttpServletRequest;
     9 import javax.servlet.http.HttpServletResponse;
    10 
    11 import cascade.entity.District;
    12 import cascade.entity.Street;
    13 import cascade.service.StreetService;
    14 
    15 
    16 public class CascadeServlet extends HttpServlet{
    17 
    18     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    19         doPost(req, resp);
    20     }
    21 
    22     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    23         req.setCharacterEncoding("UTF-8");
    24         resp.setCharacterEncoding("UTF-8");
    25         int id =Integer.parseInt(req.getParameter("id"));
    26         District district=new District();
    27         district.setId(id);
    28         
    29         /*
    30          * StreetService  ss为操作数据库的对象.
    31          * 调用该对象的getAllStreet()方法,可以从数据库中取得所有的区域信息,封装为List<Street>对象,并返回。
    32          * 其中Street是数据库Street表的实体类 
    33          * 为了把重点放在Ajax和级联菜单的实现上,本文省略了操作数据库的代码!!!
    34          */
    35         StreetService ss=new StreetService();
    36         List<Street> streets=ss.getAllStreet(district);
    37         //把得到的街道对象集合拼接成字符串文本
    38         StringBuffer sb=new StringBuffer();
    39         for(int i=0;i<streets.size();i++){
    40             sb.append(streets.get(i).getId()).append("=").append(streets.get(i).getName());
    41             if(i!=streets.size()-1){
    42                 sb.append(",");
    43             }
    44         }
    45         //servlet不转向或重定向到任何页面,使用resp.getWriter().print()方法可以把文本响应给XMLHttpRequest对象
    46          PrintWriter out = resp.getWriter();
    47          out.print(sb.toString());
    48          out.flush();
    49          out.close();
    50     }
    51     
    52 }

    在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>

    完工,效果如下:

  • 相关阅读:
    网络系列之
    网络系列之
    Linux命令系列之
    Linux命令系列之
    Linux命令系列之
    Linux命令系列之
    Linux命令系列之
    Linux命令系列之
    Linux命令系列之
    Linux命令系列之
  • 原文地址:https://www.cnblogs.com/likailan/p/3328761.html
Copyright © 2011-2022 走看看