AJAX筆記-實現城市下拉列表聯動框
學習一門新技術不外乎掌握四個點(what、how、where、why)!
一、什麼是AJAX?(what)
首先要了解什麼是同步?什麼是非同步的問題。
同步就是當瀏覽器提交請求到伺服器時,伺服器必須要響應瀏覽器,這樣瀏覽器才能繼續傳送請求。簡單來說就是請求1-響應1-請求2-響應2。
非同步是當瀏覽器提交請求到伺服器後,瀏覽器還未收到伺服器響應之前,瀏覽器還能繼續傳送請求。不管伺服器是否響應資訊。請求1-請求2-響應1-響應2。
AJAX是Asychronous JavaScript And Xml縮寫。就是瀏覽器和伺服器進行互動的時候,瀏覽器可以不必重新整理整個頁面,實現區域性頁面與伺服器進行非同步通訊的技術。
簡單來說,AJAX是區域性重新整理的非同步通訊技術。注意:AJAX只是一種程式設計模式,並不是新的程式語言!
二、為什麼要用AJAX?(why)
1.讓瀏覽器不需要經常載入大量的靜態資料,減輕瀏覽器的負擔。
2.改善了使用者對web頁面的體驗效果。
三、JAX適合用在什麼地方(where)AJAX不用來傳遞大量資料,而只用來傳遞少量資料,在使用者的體驗上更加人性化。
AJAX是一個和伺服器無關的技術,即伺服器可使用:JavaEE,.NET,PHP,。。。這些技術都可以。
AJAX只管向伺服器傳送請求,同時只管接收伺服器的HTML或XML或JSON載體響應。
服務端不能使用轉發或重定向到web頁面,因為這樣會起瀏覽器全面重新整理。
即只能以“流”的方式響應給瀏覽器。
AJAX不用來傳遞大量資料,而只用來傳遞少量資料,在使用者的體驗上更加人性化。
AJAX是一個和伺服器無關的技術,即伺服器可使用:JavaEE,.NET,PHP,。。。這些技術都可以。
AJAX只管向伺服器傳送請求,同時只管接收伺服器的HTML或XML或JSON載體響應。
服務端不能使用轉發或重定向到web頁面,因為這樣會起瀏覽器全面重新整理。
即只能以“流”的方式響應給瀏覽器。
AJAX不用來傳遞大量資料,而只用來傳遞少量資料,在使用者的體驗上更加人性化。
AJAX是一個和伺服器無關的技術,即伺服器可使用:JavaEE,.NET,PHP,。。。這些技術都可以。
AJAX只管向伺服器傳送請求,同時只管接收伺服器的HTML或XML或JSON載體響應。
服務端不能使用轉發或重定向到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技術,只是模擬了一下查詢資料庫操作。