第6章 jQuery與Ajax的應用javascript
Ajax的全稱:Asynchronous JavaScript and XML (異步Javascript和XML)html
傳統模式中,數據提交經過表單方式實現,數據的獲取是靠全頁面刷新來從新獲取整頁的內容。而Ajax模式只是經過XMLHttpRequest對象向服務器端提交數據,即按需發送。由於Ajax須要與Web服務器端進行交互,因此用個服務器,我這裏用的是Tomcat。前端
1. 傳統Js的Ajax操做java
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title></title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script language="javascript" type="text/javascript"> //經過這個函數來異步獲取信息 function Ajax(){ var xmlHttpReq = null; //聲明一個空對象用來裝入XMLHttpRequest if (window.ActiveXObject){//IE5 IE6是以ActiveXObject的方式引入XMLHttpRequest的 xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP"); } else if (window.XMLHttpRequest){//除IE5 IE6 之外的瀏覽器XMLHttpRequest是window的子對象 xmlHttpReq = new XMLHttpRequest();//實例化一個XMLHttpRequest } if(xmlHttpReq != null){ //若是對象實例化成功 xmlHttpReq.open("GET","test.jsp",true); //調用open()方法並採用異步方式 xmlHttpReq.onreadystatechange=RequestCallBack; //設置回調函數 xmlHttpReq.send(null); //由於使用get方式提交,因此能夠使用null參調用 } function RequestCallBack(){//一旦readyState值改變,將會調用這個函數 if(xmlHttpReq.readyState == 4){//readyState的值爲4表示請求完成加載(即請求發出去了) if(xmlHttpReq.status == 200){//HTTP狀態爲200表示相服務器應成功 //將xmlHttpReq.responseText的值賦給ID爲 resText 的元素 document.getElementById("resText").innerHTML = xmlHttpReq.responseText; } } } } </script> </head> <body> <input type="button" id="" value="Ajax提交" onclick="Ajax();" /> <div id="resText" ></div> </body> </html>
2. jQuery中的Ajax mysql
$.ajax(); $.load(); $.get(); $.post(); $.getStript(); $.getJSON() 這幾個經常使用的方法。jquery
$.load()方法: 將遠程的HTML載入並插入DOM中。web
首先構建一個test.html:ajax
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> </head> <body> <div class="comment"> <h6>張三:</h6> <p class="para">沙發.</p> </div> <div class="comment"> <h6>李四:</h6> <p class="para">板凳.</p> </div> <div class="comment"> <h6>王五:</h6> <p class="para">地板.</p> </div> </body> </html>
而後用load()方法將它插入到另外一個頁面中:sql
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <style> * { margin:0; padding:0;} body { font-size:12px;} .comment { margin-top:10px; padding:10px; border:1px solid #ccc;background:#DDD;} .comment h6 { font-weight:700; font-size:14px;} .para { margin-top:5px; text-indent:2em;background:#DDD;} </style> <!-- 引入jQuery --> <script src="../scripts/jquery.js" type="text/javascript"></script> <script language="javascript" type="text/javascript"> $(function(){ $("#send").click(function(){ $("#resText").load("test.html"); }) }) </script> </head> <body> <input type="button" id="send" value="Ajax獲取" /> <div class="comment"> 已有評論: </div> <div id="resText" ></div> </body> </html>
本身第一遍寫的時候忘記了基本的事:對於jQuery來講,爲頁面元素添加事件要在DOM初始完成以後再操做,即$(document).ready(......);數據庫
load()方法裏的第三個參數是個回調函數,這個函數有3個參數,分別表明請求返回的內容,請求狀態和XMLHttpRequest對象
$("#resText").load("test.html .para",function (responseText, textStatus, XMLHttpRequest){ alert( $(this).html() ); //在這裏this指向的是當前的DOM對象,即 $("#iptText")[0] alert(responseText); //請求返回的內容 alert(textStatus); //請求狀態:success,error alert(XMLHttpRequest); //XMLHttpRequest對象 });
$.get()方法和$.post()方法
分別使用get方式和post方式來進行異步請求。
注意上面的回調函數是隻有當請求成功時纔會被調用,這點和$.load()的回調函數不同。面是一個評論頁面的HTML的代碼,來講明$.get()方法的使用。
<form id="form1"> <p>評論:</p> <p>姓名: <input type="text" name="username" id="username" /></p> <p>內容: <textarea name="content" id="content" ></textarea></p> <p><input type="button" id="send" value="提交"/></p> </form> <div class='comment'>已有評論:</div> <div id="resText" > </div>
實現點擊提交按鈕後將評論顯示在已有評論下方:
$(function(){ $("#send").click(function(){ $.get("get1.jsp", { //使用$get()方法異步請求,第一個參數是請求頁面的URL地址,第二個是發送至服務器的data,第三個是回調函數 username : encodeURI( $("#username").val() ) , content : encodeURI( $("#content").val() ) }, function (data, textStatus){ //第一個參數是返回的內容,第二個是請求狀態 $("#resText").html( decodeURI(data) ); // 把返回的數據添加到頁面上 } ); }) })
Js的encodeURI()和decodeURI() 方法,encodeURI() 函數可把字符串做爲 URI 進行編碼。對如下在 URI 中具備特殊含義的 ASCII 標點符號,encodeURI() 函數是不會進行轉義的: , / ? : @ & = + $ #
decodeURI() 函數可對 encodeURI() 函數編碼過的 URI 進行解碼。
數據格式:HTML片斷、XML文檔(jQuery的DOM處理也可用於XML文檔)、JSON
jQuery解析XML文檔:
$(function(){ $("#send").click(function(){ $.get("get2.jsp", { username : encodeURI( $("#username").val() ) , content : encodeURI( $("#content").val() ) }, function (data, textStatus){ var username = $(data).find("comment").attr("username"); var content = $(data).find("comment content").text(); username = decodeURI(username); content = decodeURI(content); var txtHtml = "<div class='comment'><h6>"+username+":</h6><p class='para'>"+content+"</p></div>"; $("#resText").html(txtHtml); // 把返回的數據添加到頁面上 }); }) })
jQuery解析JSon:
$(function(){ $("#send").click(function(){ $.get("get3.jsp", { username : encodeURI( $("#username").val() ) , content : encodeURI( $("#content").val() ) }, function (data, textStatus){ var username = data.username; var content = data.content; username = decodeURI(username); content = decodeURI(content); var txtHtml = "<div class='comment'><h6>"+username+":</h6><p class='para'>"+content+"</p></div>"; $("#resText").html(txtHtml); // 把返回的數據添加到頁面上 },"json"); }) })
$.getScript()和$.getJson()方法
$.getScript()用來加載js文件,它也有回調函數,在js文件加載成功後運行。
$.getJson()方法用於加載json文件,用法和$.getScript()相同。
能夠經過JSONP形式的回調函數來加載其它網站的JSON數據,關於JSON和JSONP。例如從圖片網站Flickr搜索4張汽車圖片:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title></title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <style> * { margin:0; padding:0;} body { font-size:12px;} .para { width:100px; height:100px; margin:5px; border:0; } </style> <!-- 引入jQuery --> <script src="../scripts/jquery.js" type="text/javascript"></script> <script> $(function(){ $('#send').click(function() { $.getJSON("http://api.flickr.com/services/feeds/photos_public.gne?tags=car&tagmode=any&format=json&jsoncallback=?", function(data){ $.each(data.items, function( i,item ){ $("<img class='para'/> ").attr("src", item.media.m ).appendTo("#resText"); if ( i == 3 ) { return false; } }); } ); }) }) </script> </head> <body> <p> <input type="button" id="send" value="加載"/> </p> <div id="resText" > </div> </body> </html>
關於遍歷用的$.each()函數:以一個數組或者對象做爲第一個參數,以一個回調函數做爲第二個參數。回調函數有兩個參數,第一個是對象的成員或者數組的索引,第二個是對應變量或內容。
$.ajax()方法:jQuery最底層ajax的實現。
<!-- $.ajax()方法代替$.getScript()方法 --> <script> $(function(){ $('#send').click(function() { $.ajax({ type: "GET", url: "test.js", dataType: "script" }); }); }) </script>
<!-- $.ajax()方法代替$.getJson()方法 --> <script> $(function(){ $('#send').click(function() { $.ajax({ type: "GET", url: "test.json", dataType: "json", success : function(data){ $('#resText').empty(); var html = ''; $.each( data , function(commentIndex, comment) { html += '<div class="comment"><h6>' + comment['username'] + ':</h6><p class="para">' + comment['content'] + '</p></div>'; }) $('#resText').html(html); } }); }); }) </script>
2. 序列化元素
其他須要注意的方法是:serializaArray()方法,做用於DOM對象而不是全局函數,將DOM元素序列化後,返回JSON數據的格式。eg:
$(function(){ var fields = $(":checkbox,:radio").serializeArray(); console.log(fields);// Firebug輸出 $.each( fields, function(i, field){ $("#results").append(field.value + " , "); }); })
$.param()方法,用來對一個數組或對象按照key/value進行序列化。
3. jQuery中的ajax全局事件
使某個Ajax請求不受全局方法影響。
4. 實戰案例——基於jQuery的Ajax聊天室程序
Mysql建表,這裏navicat建表的話字段名和表名不要加什麼雙引號之類的,不然報錯。
CREATE TABLE messages ( id INT (7) NOT NULL auto_increment, USER VARCHAR (255) NOT NULL, msg text NOT NULL, time INT (9) NOT NULL, PRIMARY KEY (id) );
HTML:
<body> <div id="wrapper"> <p id="messagewindow"><span id="loading">加載中...</span></p> <form id="chatform" action="#"> 姓名: <input type="text" id="author" size="50"/><br /> 內容: <input type="text" id="msg" size="50"/> <br /> <input type="submit" value="發送" /><br /> </form> </div> </body>
書上給的例子只有PHP的....,你妹的我只懂JSP啊!!!結果只好本身用JSP來實現了。
對於服務端:
對於客戶端:
使用Myeclipse新建web工程,src目錄下建servlet存放servlet類和數據操做的類。順便說一句:引入jar包時,直接將jar包黏貼到web工程的lib目錄下便可,不須要再build path了。
數據庫操做,這裏能夠參照的是jdbc鏈接數據庫的寫法,之後直接拷貝:
1 package servlets; 2 3 import java.sql.Connection; 4 import java.sql.DriverManager; 5 6 public class DatabaseConnection { 7 private static final String DBDRIVER = "org.gjt.mm.mysql.Driver"; 8 private static final String URL = "jdbc:mysql://localhost:3306/test"; 9 private static final String USER = "root"; 10 private static final String PASSWORD = "root"; 11 private Connection conn = null; 12 13 public DatabaseConnection(){ 14 try{ 15 Class.forName(DBDRIVER); 16 this.conn=DriverManager.getConnection(URL,USER,PASSWORD); 17 }catch (Exception e) { 18 e.printStackTrace(); 19 } 20 } 21 22 public Connection getConnection(){ 23 return conn; 24 } 25 26 public void close() throws Exception{ 27 if(conn!=null){ 28 try{ 29 conn.close(); 30 }catch (Exception e) { 31 throw e; 32 } 33 } 34 } 35 }
編寫後端的servlet,用於處理前端頁面發來的請求並將對應的請求結果發回給前端頁面:
1 package servlets; 2 3 import java.io.IOException; 4 import java.io.PrintWriter; 5 import java.sql.Connection; 6 import java.sql.PreparedStatement; 7 import java.sql.ResultSet; 8 import java.sql.SQLException; 9 import java.text.SimpleDateFormat; 10 import java.util.Date; 11 12 import javax.servlet.ServletException; 13 import javax.servlet.http.HttpServlet; 14 import javax.servlet.http.HttpServletRequest; 15 import javax.servlet.http.HttpServletResponse; 16 17 public class AjaxServlet extends HttpServlet { 18 DatabaseConnection db = new DatabaseConnection(); 19 Connection connection = db.getConnection(); 20 PreparedStatement pstmt = null; 21 22 @Override 23 protected void doGet(HttpServletRequest req, HttpServletResponse resp) 24 throws ServletException, IOException { 25 req.setCharacterEncoding("UTF-8"); 26 resp.setContentType("text/xml;charset=utf-8"); 27 resp.setHeader("Cache-Control", "no-cache"); 28 PrintWriter out = resp.getWriter(); //這裏要注意 29 int status_code = 2; 30 String name = req.getParameter("name"); 31 String message = req.getParameter("message"); 32 String current=req.getParameter("time"); 33 Date d = new Date(); 34 SimpleDateFormat sdf = new SimpleDateFormat("MMddHHmmss"); 35 String dateNowStr = sdf.format(d); 36 int time=Integer.parseInt(dateNowStr); 37 if (req.getParameter("action") != null 38 && req.getParameter("action").equals("postmsg")) { 39 String sql = "insert into messages (user, msg, time) values(?,?,?)"; 40 try { 41 pstmt = connection.prepareStatement(sql); 42 pstmt.setString(1, name); 43 pstmt.setString(2, message); 44 pstmt.setLong(3, time); 45 pstmt.execute(); 46 } catch (SQLException e) { 47 e.printStackTrace(); 48 } 49 } 50 String sql = "select user,msg from messages where time>? order by id asc"; 51 try { 52 pstmt = connection.prepareStatement(sql); 53 pstmt.setInt(1, Integer.parseInt(current)); 54 ResultSet resultSet = pstmt.executeQuery(); 55 if (resultSet.next()) { 56 status_code = 1; 57 } else { 58 status_code = 2; 59 } 60 System.out.println(status_code); 61 out.println("<?xml version='1.0' encoding='utf-8'?>"); 62 out.println("<response>"); 63 out.println("\t<status>" + status_code + "</status>"); 64 out.println("\t<time>" + time + "</time>"); 65 if (status_code == 1) { 66 do { 67 out.println("\t<message>"); 68 out.println("\t\t<author>" + resultSet.getString("user") 69 + "</author>"); 70 out.println("\t\t<text>" + resultSet.getString("msg") 71 + "</text>"); 72 out.println("\t</message>"); 73 } while (resultSet.next()); 74 } 75 out.println("</response>"); 76 } catch (Exception e) { 77 e.printStackTrace(); 78 } 79 } 80 81 @Override 82 protected void doPost(HttpServletRequest req, HttpServletResponse resp) 83 throws ServletException, IOException { 84 // TODO Auto-generated method stub 85 this.doGet(req, resp); 86 } 87 88 }
本身寫代碼就會寫得亂七八糟的.....,嘛、如今是完成主義就對了(並無完成保持數據庫中只有10條數據這個功能,懶)。上面代碼的注意點有:
1. 如何向前臺頁面返回XML文檔?首先是
resp.setContentType("text/xml;charset=utf-8");
resp.setHeader("Cache-Control", "no-cache");
設置了返回內容的類型,編碼,頭部。而後是 PrintWriter out = resp.getWriter(), 接着套xml的格式拼裝打印輸出到前端頁面便可。
2. 第二個要注意的比較基本,數據庫基本API的使用:Connection PreparedStatement ResultSet之類的,jdbc的基本操做。
3. 注意使用$.post(url,data,callback,type)時,JSP後端是怎麼拿到data裏的值的:req.getParameter("name")
接下來在web.xml配置咱們寫的servlet:
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <display-name></display-name> <servlet> <servlet-name>ajax</servlet-name> <servlet-class>servlets.AjaxServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>ajax</servlet-name> <url-pattern>/back</url-pattern> </servlet-mapping> </web-app>
編寫腳本,下面是完整的前端頁面:
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ TR/xhtml1/DTD/xhtml1-transitional.dtd"> 2 <html xmlns="http://www.w3.org/1999/xhtml"> 3 <head> 4 <title></title> 5 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 6 <style> 7 body { 8 margin: 0; 9 padding: 0; 10 font-size: 12px; 11 } 12 13 #messagewindow { 14 height: 250px; 15 border: 1px solid; 16 padding: 5px; 17 overflow: auto; 18 } 19 20 #wrapper { 21 margin: auto; 22 width: 438px; 23 } 24 </style> 25 <!-- 引入jQuery --> 26 <script src="scripts/jquery.js" type="text/javascript"></script> 27 <script type="text/javascript"> 28 $(function(){ 29 //定義時間戳 30 timestamp = 0; 31 //調用更新信息函數 32 updateMsg(); 33 //表單提交 34 $("#chatform").submit(function(){ 35 $.post("back",{ 36 message: $("#msg").val(), 37 name: $("#author").val(), 38 action: "postmsg", 39 time: timestamp 40 }, function(xml) { 41 //清空信息文本框內容 42 $("#msg").val(""); 43 //調用解析xml的函數 44 addMessages(xml); 45 }); 46 return false; //阻止表單提交 47 }); 48 }); 49 //更新信息函數,每隔必定時間去服務端讀取數據 50 function updateMsg(){ 51 $.post("back",{ time: timestamp }, function(xml) { 52 //移除掉 等待提示 53 $("#loading").remove(); 54 //調用解析xml的函數 55 addMessages(xml); 56 }); 57 //每隔4秒,讀取一次. 58 setTimeout('updateMsg()', 4000); 59 } 60 //解析xml文檔函數,把數據顯示到頁面上 61 function addMessages(xml) { 62 //若是狀態爲2,則終止 63 if($("status",xml).text() == "2") return; 64 //更新時間戳 65 timestamp = $("time",xml).text(); 66 //$.each循環數據 67 $("message",xml).each(function() { 68 var author = $("author",this).text(); //發佈者 69 var content = $("text",this).text(); //內容 70 var htmlcode = "<strong>"+author+"</strong>: "+content+"<br />"; 71 $("#messagewindow").prepend( htmlcode ); //添加到文檔中 72 }); 73 } 74 </script> 75 </head> 76 <body> 77 <div id="wrapper"> 78 <p id="messagewindow"> 79 <span id="loading">加載中...</span> 80 </p> 81 <form id="chatform" action="#"> 82 姓名: <input type="text" id="author" size="50" /><br /> 內容: <input 83 type="text" id="msg" size="50" /> <br /> <input type="submit" 84 value="發送" /><br /> 85 </form> 86 </div> 87 </body> 88 </html>
上面的代碼中要注意的是jQuery對xml文檔的DOM操做:$("status",xml)方法用來通知jQuery去XML文檔中尋找 "status"標籤,找到後再利用text()方法取其標籤裏的文本便可。運行效果以下: