1. 程式人生 > >AJAX筆記-實現城市下拉列表聯動框

AJAX筆記-實現城市下拉列表聯動框

    學習一門新技術不外乎掌握四個點(what、how、where、why)!

一、什麼是AJAX?(what)

首先要了解什麼是同步?什麼是非同步的問題。    

   同步就是當瀏覽器提交請求到伺服器時,伺服器必須要響應瀏覽器,這樣瀏覽器才能繼續傳送請求。簡單來說就是請求1-響應1-請求2-響應2

   非同步是當瀏覽器提交請求到伺服器後,瀏覽器還未收到伺服器響應之前,瀏覽器還能繼續傳送請求。不管伺服器是否響應資訊。請求1-請求2-響應1-響應2

   AJAXAsychronous JavaScript And Xml縮寫。就是瀏覽器和伺服器進行互動的時候,瀏覽器可以不必重新整理整個頁面,實現區域性頁面與伺服器進行非同步通訊的技術。

簡單來說,AJAX是區域性重新整理的非同步通訊技術。注意:AJAX只是一種程式設計模式,並不是新的程式語言!

二、為什麼要用AJAX?(why)

1.讓瀏覽器不需要經常載入大量的靜態資料,減輕瀏覽器的負擔。

2.改善了使用者對web頁面的體驗效果。

三、JAX適合用在什麼地方(where

AJAX不用來傳遞大量資料,而只用來傳遞少量資料,在使用者的體驗上更加人性化。

AJAX是一個和伺服器無關的技術,即伺服器可使用:JavaEE.NETPHP,。。。這些技術都可以。

AJAX只管向伺服器傳送請求,同時只管接收伺服器的HTMLXMLJSON載體響應。

服務端不能使用轉發或重定向到web頁面,因為這樣會起瀏覽器全面重新整理。

即只能以“流”的方式響應給瀏覽器。

AJAX不用來傳遞大量資料,而只用來傳遞少量資料,在使用者的體驗上更加人性化。

AJAX是一個和伺服器無關的技術,即伺服器可使用:JavaEE.NETPHP,。。。這些技術都可以。

AJAX只管向伺服器傳送請求,同時只管接收伺服器的HTMLXMLJSON載體響應。

服務端不能使用轉發或重定向到web頁面,因為這樣會起瀏覽器全面重新整理。

即只能以“流”的方式響應給瀏覽器。

AJAX不用來傳遞大量資料,而只用來傳遞少量資料,在使用者的體驗上更加人性化。

AJAX是一個和伺服器無關的技術,即伺服器可使用:JavaEE.NETPHP,。。。這些技術都可以。

AJAX只管向伺服器傳送請求,同時只管接收伺服器的HTMLXMLJSON載體響應。

服務端不能使用轉發或重定向到web頁面,因為這樣會起瀏覽器全面重新整理。

即只能以“流”的方式響應給瀏覽器。

四、AJAX開發步驟(怎麼用AJAX  how)

1.建立AJAX非同步物件。例如:var ajax=createAJAX();

2.準備傳送非同步請求。例如 ajax.open(method,url);引數method表示請求方式是GET或者POST,如果是GET,無需設定AJAX請求頭,如果是POST提交,必須設定AJAX請求頭,例如:

ajax.setRequestHeader();

3.傳送請求體中的資料到伺服器。例如:ajax.send();這裡如果是GET提交,請求體內容為null,需要在url地址後面加上傳遞的引數。如果是POST提交,需要設定請求體引數。例如var content=”key=value&key=value”;

4.AJAX非同步物件不斷的監聽伺服器的狀態變化(狀態碼0,1,2,3,4),例如:ajax.onreadystatechange()=function(){}後面跟一個匿名函式。

5.在匿名函式中進行操作,在非同步物件中獲取伺服器傳遞引數,通過DOM規則,用js程式碼來操作web頁面。

注意:所有瀏覽器中都內建了非同步物件,在預設情況下,該非同步物件並沒有創建出來。需要我們自己建立。

建立AJAX非同步物件(XMLHttpRequest物件)的程式碼如下:

<script type="text/javascript">
		//建立AJAX非同步物件
		function createAJAX(){
			var ajax = null;
			try{
				//如果IE5=IE12的話
				ajax = new ActiveXObject("microsoft.xmlhttp");
			}catch(e1){
				try{
					//如果是非IE的話
					ajax = new XMLHttpRequest();
				}catch(e2){
					alert("你的瀏覽器中不支援非同步物件");
				}
			}
			return ajax;
		}
	</script>
五、AJAX工作原理

    簡單來說就是瀏覽器將原始請求傳送到AJAX非同步物件中(XMLHttpRequest物件),然後非同步物件經過包裝後,以http協議的方式傳送給伺服器,伺服器通過業務操作,以響應的方式返回給AJAX非同步物件,然後在顯示資料到瀏覽器中。


六、AJAX的實際應用

首先通過一個普通的顯示當前時間的例子來引入AJAX。

JS+Servlet技術來實現同步方式顯示當前時間的案例。

思路 設計一個input提交按鈕 請求提交到伺服器,伺服器響應資料到瀏覽器

 顯示當前時間:${requestScope.nowTime } <br/>
   <input type="button" value="同步方式顯示"><p/>
   	其他資訊文字<br/>
   	其他資訊文字<br/>
   	其他資訊文字<br/>其他資訊文字<br/>其他資訊文字<br/>
   <script type="text/javascript">
    var inputElement=document.getElementsByTagName("input")[0];
    inputElement.onclick=function(){
	     var url="${pageContext.request.contextPath}/TimeServlet?time="+new Date().getTime();
	     window.location.href=url;
    }
   </script>
/**
	 * 顯示當前時間
	 */
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String nowTime = sdf.format(new Date());
		request.setAttribute("nowTime", nowTime);
		//轉發
		request.getRequestDispatcher("/js03_time.jsp").forward(request, response);
	}

可以看出當整個點選提交按鈕時,整個頁面載入到歷史記錄中,頁面重新載入所有的資料。 

    缺點:當只需要區域性重新整理一個頁面時,其他部分沒必要跟著載入一遍。造成瀏覽器載入負擔。

可改進的地方:讓無需變化的大量資料,原封不動,不用快取到歷史欄中,無需全部重新整理,只重新整理某些需要變化的資料區域,這就用到AJAX技術。

運用AJAX+Servlet改進上面的程式碼。
<script type="text/javascript">
     document.getElementById("buttonID").onclick=function(){
       //1建立AJAX非同步物件
       var ajax = createAJAX();
        //2準備傳送請求
       var method="GET";
     var url="${pageContext.request.contextPath}/AJAXTimeServlet?id="+new Date().getTime();
       ajax.open(method,url);
       //3設定請求頭 預設是get方式提交(忽略)
       //4傳送請求體到伺服器
       ajax.send(null);
       //--------等待伺服器響應 編寫servlet
       //5非同步物件監聽伺服器響應的狀態碼
       ajax.onreadystatechange=function(){
	        if(ajax.readyState==4){
		           if(ajax.status==200){
		             //從ajax非同步物件中獲取響應資料
		              var nowTime=ajax.responseText;
		              //將結果按照dom規則,新增到web頁面指定位置
		              var spanElement=document.getElementById("spanTime");
		              spanElement.innerHTML=nowTime;
		           }
	        }
      }
    }
</script>

(2)應用二、檢查使用者名稱是否已存在資料庫中

在註冊頁面中,我們經常會填寫使用者名稱。

用非同步方式的優點: 游標離開使用者名稱文字框之後立即提交到伺服器進行查詢,提醒使用者。避免使用者填寫所有資訊提交後再進行修改使用者名稱。提高效率。


AJAX+Servlet技術:
使用者名稱:<input type="text" id="userNameID" maxlength="10">
   <span id="resSpan"></span><span id="msgID"></span>
   <script type="text/javascript">
    //游標失去焦點事件
    document.getElementById("userNameID").onblur=function(){
        //獲取表單資料
        var userName = this.value;
        //文字提示的span標籤
        var msgSpan =document.getElementById("msgID");
        //建立img標籤
	    var imgElement=document.createElement("img");
	    //定位插入圖片span標籤 設定屬性
	    var spanElement =document.getElementById("resSpan");
        msgSpan.innerHTML="";
        if(userName==""){
		        msgSpan.innerHTML="使用者名稱不能為空";
		        //設定img標籤屬性 圖片路徑 大小
	             imgElement.src="img/MsgError.gif";
	             imgElement.style.width="12px";
	             imgElement.style.height="12px";
	             
	             //清空資料
	             spanElement.innerHTML="";
	             //加入圖片
	             spanElement.appendChild(imgElement);
        }else{
        //1.建立AJAX非同步物件
        var ajax = createAJAX();
        //2.非同步物件準備傳送請求
        var method="POST";
        var url="${pageContext.request.contextPath}/UserServlet?id="+new Date().getTime();
        ajax.open(method,url);
        //3.如果是POST提交 設定請求頭
        ajax.setRequestHeader("content-type","application/x-www-form-urlencoded");
        //4.傳送請求體到伺服器
        var context="userName="+userName;
        ajax.send(context);
        //---------------等待伺服器
        //5非同步物件監聽伺服器響應的狀態碼
        ajax.onreadystatechange= function(){
          //滿足條件
          if(ajax.readyState==4){
	           if(ajax.status==200){
	            //獲取伺服器資料
	            var tip=ajax.responseText;
	             if(tip=="img/MsgError.gif"){
	             msgSpan.innerHTML="使用者名稱已存在";
	             }
	             //設定img標籤屬性 圖片路徑 大小
	             imgElement.src=tip;
	             imgElement.style.width="12px";
	             imgElement.style.height="12px";             
	             //清空資料
	             spanElement.innerHTML="";
	             //加入圖片
	             spanElement.appendChild(imgElement);
	           }
          }
        }
        }
    }
   </script>
        // 獲取表單提交引數
		request.setCharacterEncoding("utf-8");
		String userName = request.getParameter("userName");
		String tip="img/MsgSent.gif";
		//從資料庫中判斷
		if("zhangsan".equals(userName)){
			tip="img/MsgError.gif";
		}
		//輸出流
		response.setContentType("text/html;charset=utf-8");
		PrintWriter pw = response.getWriter();
		pw.write(tip);
		pw.flush();
		pw.close();
這裡沒有用到JDBC技術,只是模擬了一下查詢資料庫操作。

注意如果採用GET提交方式 需要進行url編碼

//對漢字進行UTF-8(U8)的編碼;  username = encodeURI(username); //加到url後面



(3)應用三、基於XML,以POST方式,完成省份-城市二級下拉聯動

當點選省份下拉列表時,自動更新城市列表。

 <select id="provinceID" name="province" style="width:90px">
     <option>選擇省份</option>
     <option>山東</option>
     <option>湖南</option>
    </select>
      
    <select id="cityID" name="city" style="width:90px">
     <option>選擇城市</option>
    </select>
    
    <script type="text/javascript">
	     //獲取select省份標籤 新增事件
	     document.getElementById("provinceID").onchange=function(){
	     //清空城市下拉框裡的內容 只保留第一個
	     var cityElement=document.getElementById("cityID");
	     cityElement.options.length=1;
         //獲取選中option的索引 從0開始
         var index=this.selectedIndex;
         //獲取option標籤的內容
         var province =this[index].innerHTML;
         if(province !="選擇省份"){
              //1建立ajax非同步物件
              var ajax = createAJAX();
              //2準備傳送請求
              var method="POST";
     Var url="${pageContext.request.contextPath}/ProvinceServlet?id="+new Date().getTime();
              ajax.open(method,url);
              //3如果是POST提交設定請求頭
              ajax.setRequestHeader("content-type","application/x-www-form-urlencoded");
              //4傳送請求體資料到伺服器
              var content="province="+province;
              ajax.send(content);
               //--------------------等待伺服器響應
              //5非同步物件不斷的監聽伺服器傳送的狀態碼
             ajax.onreadystatechange = function(){
                   if(ajax.readyState == 4){
	                       if(ajax.status==200){
		                        //從非同步物件中獲取伺服器響應的xml文件
		                        var xmlDocument = ajax.responseXML;
		                        //按照DOM規則,解析XML文件
		                        var cityElementArray = xmlDocument.getElementsByTagName("city");
		                        //遍歷city陣列
		                        var size = cityElementArray.length;
		                        for(var i=0;i<size;i++){
		                             //獲取city標籤體內的內容
		                             var city=cityElementArray[i].firstChild.nodeValue;
		                             //建立option物件
		                             var cityOption = document.createElement("option");
		                             //設定cityOption
		                             cityOption.innerHTML=city;
		                             //把option標籤新增到select中
		                             cityElement.appendChild(cityOption); 
		                        }
		                    }    
	                   } 
              }
         }
       }
    </script>
 //獲取資料
		request.setCharacterEncoding("utf-8");
		String province=request.getParameter("province");
		System.out.println(province);
		//告訴AJAX非同步物件 伺服器採用XML方式響應資料
		response.setContentType("text/xml;charset=utf-8");
		PrintWriter pw = response.getWriter();
		pw.write("<?xml version='1.0' encoding='UTF-8'?>");
		pw.write("<root>");
		if("山東".equals(province)){
			pw.write("<city>濟南</city>");
			pw.write("<city>青島</city>");
			pw.write("<city>菏澤</city>");
		}else if("湖南".equals(province)){
			pw.write("<city>長沙</city>");
			pw.write("<city>株洲</city>");
			pw.write("<city>湘潭</city>");
			pw.write("<city>岳陽</city>");
		}
		pw.write("</root>");
		pw.flush();
		pw.close();
		System.out.println("傳輸完成");
這裡也沒有用到JDBC技術,只是模擬了一下查詢資料庫操作。