《鋒利的JQuery》讀書要點筆記5——jQuery與Ajax的應用

第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()方法取其標籤裏的文本便可。運行效果以下:

相關文章
相關標籤/搜索