---祝大家中秋愉快---
Ajax (
AsynchronousJavaScript and XML)是近年來流行的一門web 技術(shù)。在Blogjava上看到有人開始在介紹AJAX,但仿佛流于概念或理論的東西,對于想用Ajax的初學者似乎不是很make sense。我想,學習任何一樣新的技術(shù),例子和步驟是極為make sense的兩樣東西。
筆者想結(jié)合過去的學習經(jīng)驗簡單講講使用Ajax的基本步驟和舉幾個實用例子。由于筆者主要在于后臺端的開發(fā),所以很多腳本并不是很擅長。Ajax也主要限于以前大學的修課和近期的一些為后臺端程序的測試的簡單實現(xiàn)。所以只是一個拋磚引玉的使用Ajax版本,歡迎相互學習交流。
0. 導讀???
1。使用Ajax的基本流程
??? 2。使用Ajax的基本步驟。(簡單例子--> Demo)
??? 3。再來一個例子(Google Suggest)。(Demo)
??? 4。家庭作業(yè) :)
1。使用Ajax的基本流程在筆者看來,Ajax更像是一個簡單的網(wǎng)絡框架,它描述著如何高效地使網(wǎng)絡前端的數(shù)據(jù)展現(xiàn)和網(wǎng)絡后端的數(shù)據(jù)之間的交互。基本上,就是瀏覽器提供一個XMLHttpRequest(當然在IE里是ActiveXObject)的對象向后臺端的腳本程序或者Servlet Classes發(fā)送http請求,從后臺端的回應中獲取文本數(shù)據(jù)(如xml格式和最近有人討論的Json格式)并嵌入前臺段的網(wǎng)頁中或腳本中。
下圖是一個簡單的流程圖:
2。使用Ajax的基本步驟。下面,我們結(jié)合上面的流程,以及一個簡單的例子(見
這篇文章)過一遍基本的步驟。(藍色代碼為標準寫法)
第一步:Form 代碼:接受前臺端的輸入,并通過Action方法(方法函數(shù)里包含創(chuàng)建XMLHttpRequest對象)把request post到后臺端。
<input id="username" name="username" type="text"
? onblur="checkName(this.value,'')" />
<span class="hidden" id="nameCheckFailed">
? This name is in use, please try another.
</span>
<script language="javascript">
function checkName(input, response)
{
? if (response != ''){
??? // Response mode
??? message?? = document.getElementById('nameCheckFailed');
??? if (response == '1'){
????? message.className = 'error';
??? }else{
????? message.className = 'hidden';
??? }
? }else{
??? // Input mode
??? url? = 'http://localhost/xml/checkUserName.php?q=' + input;
??? loadXMLDoc(url);
? }
}
var req;
function loadXMLDoc(url)
{
??? // branch for native XMLHttpRequest object
??? if (window.XMLHttpRequest) {
??????? req = new XMLHttpRequest();
??????? req.onreadystatechange = processReqChange;
??????? req.open("GET", url, true);
??????? req.send(null);
??? // branch for IE/Windows ActiveX version
??? } else if (window.ActiveXObject) {
??????? req = new ActiveXObject("Microsoft.XMLHTTP");
??????? if (req) {
??????????? req.onreadystatechange = processReqChange;
??????????? req.open("GET", url, true);
??????????? req.send();
??????? }
??? }
}
</script>
注:
1。 這里的form只是一個input box,action的方法是onblur,就是響應失去焦點的事件,然后調(diào)用一個函數(shù)checkName, 這個函數(shù)里通過XMLHttpRequest向PHP server script 發(fā)送Post請求(看得出來,這里的php server script的文件名叫checkUserName.php,唯一參數(shù)是q)。
2。函數(shù)loadXMLDoc里有個通用的創(chuàng)建XMLHttpRequest對象的代碼,標準代碼整理如下:
?
?????? var req;
??? ??? function foo()
??? ??? {
??? ??? ??? req = false;
??? ??? ??? // branch for native XMLHttpRequest object
??? ??? ??? if(window.XMLHttpRequest)
??? ??? ??? {
??? ??? ??? ??? try
??? ??? ??? ??? {
??? ??? ??? ??? ??? req = new XMLHttpRequest();
??? ??? ??? ??? }
??? ??? ??? ??? catch(e)
??? ??? ??? ??? {
??? ??? ??? ??? ??? req = false;
??? ??? ??? ??? }
??? ??? ??? }
??? ??? ??? else if(window.ActiveXObject) // branch for IE/Windows ActiveX version
??? ??? ??? {
??? ??? ??? ??? try
??? ??? ??? ??? {
??? ??? ??? ??? ??? req = new ActiveXObject("Msxml2.XMLHTTP");
??? ??? ??? ??? }
??? ??? ??? ??? catch(e)
??? ??? ??? ??? {
??? ??? ??? ??? ??? try
??? ??? ??? ??? ??? {
??? ??? ??? ??? ??? ??? req = new ActiveXObject("Microsoft.XMLHTTP");
??? ??? ??? ??? ??? }
??? ??? ??? ??? ??? catch(e)
??? ??? ??? ??? ??? {
??? ??? ??? ??? ??? ??? req = false;
??? ??? ??? ??? ??? }
??? ??? ??? ??? }
??? ??? ??? }
??? ??? ??? if(req)
??? ??? ??? {
??? ?? ?? ?? ?? ??//do something here
???? ??? ??? }
??? ??? ???
??? ??? }
第二步:響應文本處理代碼:XMLHttpRequest對象里有個類似消息響應函數(shù)的屬性,即通過設置 req.onreadystatechange 來告訴XMLHttpRequest在哪個函數(shù)里處理服務端返回的文本信息。
如在上面的例子中:
req.onreadystatechange = processReqChange;
那么我們接著要有一個processReqChange的函數(shù):
function processReqChange()
{
// only if req shows "complete"
if (req.readyState == 4) {
// only if "OK"
if (req.status == 200)
{
// ...processing statements go here...
processResponse();
} else {
alert("There was a problem retrieving
the XML data:\n" + req.statusText);
}
}
}
function processResponse()
{
response = req.responseXML.documentElement;
method = response.getElementsByTagName('method')[0].firstChild.data;
result = response.getElementsByTagName('result')[0].firstChild.data;
eval(method + '(\'\', result)');
}
注:
1。 基本上
processReqChange
函數(shù)是標準代碼的寫法。
2。這里要用到前面定義的全局變量(XMLHttpRequest對象)req
第三步:后臺端代碼(這個例子是php server script):接受前臺端的請求,處理其參數(shù),并返回相應的結(jié)果。
文件名: checkUserName.php
<?php
header('Content-Type: text/xml');
function nameInUse($q)
{?
? if (isset($q)){
??? switch(strtolower($q))
??? {
????? case? 'drew' :
????????? return '1';
????????? break;
????? case? 'fred' :
????????? return '1';
????????? break;
????? default:
????????? return '0';
??? }
? }else{
??? return '0';
? }
?
}
?>
<?php echo '<?xml version="1.0" encoding="UTF-8"? standalone="yes"?>'; ?>
<response>
? <method>checkName</method>
? <result><?php
??? echo nameInUse($_GET['q']) ?>
? </result>
</response>
注:代碼很簡單,就不用解釋了。這里返回的是xml格式的字符串。
總體效果見
這里輸入"fred"或者"drew"的名字,失去焦點后會顯示名字已存在的信息。
?
3。再來一個例子。這里再講一個實用的例子,這是以前上課的一個課堂作業(yè),也很有代表性。是關(guān)于
Google Suggest(好像新的Google Toolbar上就用的這個功能)的應用問題。這里是寫好的
DEMO。現(xiàn)在越來越多的網(wǎng)站提供類似Web Service的API, 我們利用他們提供的API URL可以返回一些我們用的著的數(shù)據(jù),放在我們的網(wǎng)頁上。這里就用的上Ajax。只不過有些返回來的文本數(shù)據(jù)是xml格式的,就可以利用上面的簡單例子來處理,但很多像Google Suggest那樣是返回一段類似代碼格式的文本。我們就要利用Javascript的eval函數(shù),把這些文本當作一段代碼在嵌入自己的網(wǎng)頁中。如果嵌入的代碼中含有函數(shù),則需要自己再寫一個同名的函數(shù)作為實現(xiàn)。(這就是流程圖中的optional的func 3)
這里完整代碼就不貼了,貼一些關(guān)鍵代碼(原本后臺端是用Java Servlet寫的,但做demo的空間沒有Tomcat不支持Servlet,所以改用Php實現(xiàn),大家可以自己用Java再寫一邊作為家庭作業(yè) :) ):
1) form 代碼:
<form name = "QForm" method="POST" action="google_suggest.php">
??? <table bgcolor="8080C0" width="90%" >
??? <tr>
??? ??? <td? nowrap>Search Term:</td>
??? ??? <td ><input type="text" name="qtext"? onkeyup="return GetSuggestion()" size="60"></td>
??? </tr>
??? <tr>
??? ??? <th colspan="2" align="left" bgcolor="#A8A8FF"><DIV id=google_suggest_target>results go here . . . </DIV></th>
??? </tr>
??? </table>
??? </form>
注:
a. 看得出來,要把查詢的字符串post到google_suggest.php上
b. action的函數(shù)是GetSuggestion(),其返回的字符串會顯示在預留的網(wǎng)頁空間里。
2) 后臺端代碼(PHP):這里主要接收前臺的請求,并不請求轉(zhuǎn)化為向Google Suggest的API URL請求,把接收到的文本信息返回給前端。代碼很簡單,如下:
文件名:google_suggest.php
<?php
function getGoogleSuggest($q)
{
??? $url = "http://www.google.com/complete/search?hl=en&js=true&qu=" . $q;
??? return file_get_contents($url);
}
?>
<?php echo getGoogleSuggest($_POST['q']) ?>
注:
a。
Google Suggest API 返回的是一個代碼格式的文本信息,如下:
sendRPCDone(frameElement, "", new Array(), new Array(), new Array(""));
所以我們再前臺接受到這個文本信息之后,應該寫一個sendRPCDone的函數(shù)來做進一步信息處理(比如說列表出查詢結(jié)果)。
3) 前臺文本處理代碼:
??? <script type="text/javascript">
??? ??? var req;
??? ??? function GetSuggestion()
??? ??? {
??? ??? ??? req = false;
??? ??? ??? var f = document.QForm;
??? ??? ??? // branch for native XMLHttpRequest object
??? ??? ??? if(window.XMLHttpRequest)
??? ??? ??? {
??? ??? ??? ??? try
??? ??? ??? ??? {
??? ??? ??? ??? ??? req = new XMLHttpRequest();
??? ??? ??? ??? }
??? ??? ??? ??? catch(e)
??? ??? ??? ??? {
??? ??? ??? ??? ??? req = false;
??? ??? ??? ??? }
??? ??? ??? }
??? ??? ??? else if(window.ActiveXObject) // branch for IE/Windows ActiveX version
??? ??? ??? {
??? ??? ??? ??? try
??? ??? ??? ??? {
??? ??? ??? ??? ??? req = new ActiveXObject("Msxml2.XMLHTTP");
??? ??? ??? ??? }
??? ??? ??? ??? catch(e)
??? ??? ??? ??? {
??? ??? ??? ??? ??? try
??? ??? ??? ??? ??? {
??? ??? ??? ??? ??? ??? req = new ActiveXObject("Microsoft.XMLHTTP");
??? ??? ??? ??? ??? }
??? ??? ??? ??? ??? catch(e)
??? ??? ??? ??? ??? {
??? ??? ??? ??? ??? ??? req = false;
??? ??? ??? ??? ??? }
??? ??? ??? ??? }
??? ??? ??? }
??? ??? ??? if(req)
??? ??? ??? {
??? ??? ??? ??? var url = "google_suggest.php";
???????
??? ??? ??? ??? req.onreadystatechange = processReqChange;
??? ??? ??? ??? req.open("POST", url, true);
??????? ??? ??? req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
??? ??? ??? ??? req.setRequestHeader("Method", "POST " + url + " HTTP/1.1");
??? ??? ??? ??? req.send("q=" + escape(document.QForm.qtext.value));
??? ??? ??? }
??? ??? ???
??? ??? }
??? ???
??? ??? function processReqChange()
??? ??? {
??? ??? ??? if(req.readyState == 4) // only if req shows "loaded"
??? ??? ??? {
??? ??? ???????????????? if (req.status == 200) // only if "OK"
??? ??? ???????????????? {
?
?? ??? ???????????????? ??? ??? x = req.responseText;
??? ??? ???????????????????????? eval(x);
??? ??? ???????????????? }
??? ??? ???????????????? else
??? ??? ???????????????? {
??? ??? ?????????? ??? ??? ????? alert("There was a problem retrieving the XML data:\n" + req.statusText);
??? ??? ???????????????? }
??? ??? ??? }
??? ??? ??? else if(req.readyState == 2)
??? ??? ??? {
??? ??? ??? }
??? ??? }
??? ???
??? ??? function sendRPCDone(frameElement, qString, arr1, arr2, arr3)
??? ??? {
??? ???
??? ??? ??? var suggest_results = eval(arr1);
??? ??? ??? var counts = eval(arr2);
??? ??? ??? var htmlstr = "<TABLE cellspacing=4 border=0>";
??? ??? ??? for (var i=0; i < suggest_results.length; i++)
??? ??? ??? {
??? ??? ??? ??? htmlstr += "<tr><td><a href=\"javascript:self.location=\'http://www.google.com/search?hl=en&q=" + suggest_results[i] + "&btnG=Google+Search\'\">" + suggest_results[i] + "</a></td>";
??? ??? ??? ??? htmlstr += "<TD width=200><font color= 228b22>" + counts[i] + "</font></TD></TR>"
??? ??? ?????? ??? ?
??? ??? ??? }
??? ??? ??? htmlstr += "</TABLE>";
??? ??? ??? document.getElementById("google_suggest_target").innerHTML = htmlstr;
??? ???
??? ??? }
??? ???
??? ??? </script>
4。家庭作業(yè) :)一定要自己寫一些代碼,才能鞏固知識:)
題目:
我們經(jīng)常用
del.icio.us來收藏我們喜歡的網(wǎng)站或者文章,并加一些類似讀書筆記的注釋。那么我們怎么利用del.icio.us提供的API來訪問我們的讀書筆記信息,并顯示在自己的Blog里呢?
提示:
1。你要有一個del.icio.us的賬號,并且已經(jīng)有所網(wǎng)頁收藏作為實驗數(shù)據(jù):)
2。API URL 是 "http://del.icio.us/feeds/json/" + "你的賬號名";自己參看一下,看返回什么樣的格式文本。另外,如果要限制返回的記錄數(shù),可以加"?count=10"這樣的參數(shù)。
最后,祝大家中秋愉快!
---------------------------完----------------------------