作者: Jonathan Fenocchi 時間:2005.10.25 譯者:Sheneyan 英文原文: http://webreference.com/programming/javascript/jf/column12/index.html
在過去,由于為了獲得新數(shù)據(jù)而不得不重新加載web頁面(或者加載其他頁面)導(dǎo)致web應(yīng)用程序發(fā)展被限制。雖然有其他方法可用(不加載其他頁面),但是這些技術(shù)都沒有被很好地支持而且有bug成災(zāi)的趨向。在過去的幾個月里,一個過去并不被廣泛支持的技術(shù)已經(jīng)被越來越多的web沖浪者(web surfers??是指瀏覽器還是瀏覽者?)所接受,它給了開發(fā)者更多的自由開發(fā)先進的web應(yīng)用程序。這些通過javascript來異步取得xml數(shù)據(jù)的應(yīng)用程序,被親切的稱為“Ajax應(yīng)用程序”(Asynchronous Javascript and XML applications)。在這篇文章中,我將會解釋如何通過Ajax來取回一個遠程的XML文件并更新一個web page,并且隨著這個系列的繼續(xù),我將討論更多的方法,使用ajax技術(shù)將你的web應(yīng)用程序提升到一個新的層次.
這第一步就是創(chuàng)建一個帶一些數(shù)據(jù)的XML文件。我們將這個文件命名為data.xml。它是一個簡單的XML文件,而在一個真實的程序中,它會復(fù)雜許多,但對于我們的例子來說,簡單明了是最合適地。
<?xml version="1.0" encoding="UTF-8"?> <root> <data> 這是一些示例數(shù)據(jù),它被保存在一個XML文件中,并被JavaScript取回。 </data> </root>
現(xiàn)在讓我們創(chuàng)建一個簡單的web頁面包含一些示例數(shù)據(jù)。這個頁面將是我們的js腳本所在,并且這個頁面將會讓用戶們訪問柄看到Ajax腳本的運行。我們把它命名為ajax.html
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html lang="zh" dir="ltr"> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312"> <title>使用ajax開發(fā)web應(yīng)用程序 - 示例</title> </head> <body> <h1>使用ajax開發(fā)web應(yīng)用程序</h1> <p>這個頁面演示了AJAX技術(shù)如何通過動態(tài)讀取一個遠程文件來更新一個網(wǎng)頁的內(nèi)容--不需要任何網(wǎng)頁的重新加載。注意:這個例子對于禁止js的用戶來說沒有效果。</p> <p id="xmlObj"> 這是一些示例數(shù)據(jù),它是這個網(wǎng)頁的默認數(shù)據(jù) <a href="data.xml" title="查看這個XML數(shù)據(jù)." onclick="ajaxRead('data.xml'); this.style.display='none'; return false">查看XML數(shù)據(jù).</a> </p> </body> </html>
注意,對于那些沒有javascript的用戶,我們直接鏈接到data.xml文件。對于那些允許運行javascript的用戶,函數(shù)“ajaxRead”將被運行,這個鏈接被隱藏,并不會被轉(zhuǎn)向到那個data.xml文件。函數(shù)“ajaxRead”現(xiàn)在還沒定義。所以如果你要檢驗上面的示例代碼,你會得到一個javascript錯誤。讓我們繼續(xù)并定義這個函數(shù)(還有其他的),讓你能夠看到ajax是如何工作的,下面的腳本要放到你的head標(biāo)簽里:
<script type="text/javascript"><!-- function ajaxRead(file){ var xmlObj = null; if(window.XMLHttpRequest){ xmlObj = new XMLHttpRequest(); } else if(window.ActiveXObject){ xmlObj = new ActiveXObject("Microsoft.XMLHTTP"); } else { return; } xmlObj.onreadystatechange = function(){ if(xmlObj.readyState == 4){ updateObj('xmlObj', xmlObj.responseXML.getElementsByTagName('data')[0].firstChild.data); } } xmlObj.open ('GET', file, true); xmlObj.send (''); } function updateObj(obj, data){ document.getElementById(obj).firstChild.data = data; } //--></script>
(Sheneyan注:完整代碼示例見 example.html ML文件見:data.xml )
這堆代碼有點多,讓我們一點點的進行。第一個函數(shù)叫做“ajaxRead”-也就是我們在頁面的“查看XML數(shù)據(jù)”鏈接中調(diào)用的函數(shù),我們定義了一個“xmlObj”變量-這將作為客戶端(用戶正在查看的這個web頁面)以及服務(wù)端(web站點本身)之間的中間件。我們在一個if/else塊中定義這個對象:
if(window.XMLHttpRequest){ xmlObj = new XMLHttpRequest(); } else if(window.ActiveXObject){ xmlObj = new ActiveXObject("Microsoft.XMLHTTP"); } else { return; }
這只是一個對不同對象是否可用的測試-某些瀏覽器實現(xiàn)了不同的XMLHttpRequest對象,所以當(dāng)我們定義“xmlObj”作為我們的XMLHttpRequest對象時,我們不得不根據(jù)瀏覽器所實現(xiàn)的來定義它。如果沒有可用的XMLHttpRequest對象,我們將執(zhí)行“return”語句結(jié)束這個函數(shù)以避免腳本錯誤。在大部分情況下,這個檢驗將返回一個XMLHttpRequest對象-這部分代碼應(yīng)該能夠在絕大部分的瀏覽器上工作,除了少部分比較老的瀏覽器的異常情況(它能夠工作在ie5.01上,但是在netscape4上會使函數(shù)終止)。
接下來是這些代碼塊:
xmlObj.onreadystatechange = function(){ if(xmlObj.readyState == 4){ updateObj('xmlObj', xmlObj.responseXML.getElementsByTagName('data')[0].firstChild.data); } }
每次XMLHttpRequest的狀態(tài)發(fā)生變化,事件“onreadystatechange”就會被觸發(fā)。通過使用“xmlObj.onreadystatechange = function(){...}”我們能夠創(chuàng)建一個函數(shù)并讓它在這個XMLHttpRequest對象的狀態(tài)每次發(fā)生改變的時候立刻運行。這里總共有五個狀態(tài),由0走到4。
0 – 尚未初始化(在這個XMLHttpRequest開始前)
1 – 加載(XMLHttpRequest初始化一結(jié)束)
2 – 加載結(jié)束(XMLHttpRequest一從服務(wù)器上獲得一個回應(yīng))
3 – 交互(當(dāng)XMLHttpRequest對象和服務(wù)器連接中)
4 – 結(jié)束(當(dāng)XMLHttpRequest被告知它已經(jīng)完成了所有人物并結(jié)束運行)
這第五個狀態(tài)(數(shù)字4)就是我們能夠確定數(shù)據(jù)已經(jīng)可用的標(biāo)志,所以我們檢驗這個xmlObj.readyState是否等于“4”來確定數(shù)據(jù)是否可用,如果是4,我們運行updateObj函數(shù)。這個函數(shù)帶兩個參數(shù):一個當(dāng)前web頁面的元素ID(當(dāng)前web頁面中要更新的元素)以及用于填充這個元素的數(shù)據(jù)。這個函數(shù)的運行方式在稍后將更詳細地解釋。
我們的web頁面的p元素有一個id“xmlData”,這就是我們準(zhǔn)備更新的段落。我們正在取得的數(shù)據(jù)來自于XML文件,但它有點復(fù)雜。這里是它如何工作的原理。
xmlObj.responseXML屬性是一個DOM對象 - 它很象“document”對象,除了它來自遠程的XML文件。換句話說,如果你在data.xml中運行腳本,那xmlObj.responseXML就是一個“document”對象。因為我們知道這些,我們能夠通過“getElementsByTagName”方法取得任何XML節(jié)點。數(shù)據(jù)包含在一個命名為“<data>”的XML節(jié)點中,所以我們的任務(wù)很簡單:取得第一個(而且只有這一個)數(shù)據(jù)節(jié)點。因而,xmlObject.responseXML.getElementsByTagName("data")[0]返回XML文件中的第一個<data>節(jié)點。 注意:它返回的是XML節(jié)點,而不是節(jié)點中的數(shù)據(jù)-這個數(shù)據(jù)必須通過訪問XML節(jié)點的屬性取得,這就是下一步要說的。
接下來,取得數(shù)據(jù)只需要簡單的指定“firstChild.data”(firstChild指向了那個被<data>節(jié)點包含的文本節(jié)點,而這個“data”屬性則是這個文本節(jié)點的實際文本)。
xmlObj.open ('GET', file, true); xmlObj.send ('');
這是我們的ajaxRead函數(shù)的最后一個部分。它說了些什么?嗯,xmlObj的這個“open”方法打開了一個到服務(wù)器(通過一個指定的協(xié)議,這里指定的是“GET”-你可以使用“USE”或者其他別的協(xié)議)的連接,去請求一個文件(在我們的例子里,變量“file”被作為一個參數(shù)賦給ajaxRead函數(shù)-data.xml),而且javascript可以同步(false)或者異步(true,默認值)的處理請求。由于這是異步的Javascript和XML(AJAX),我們將使用默認的異步方式-在這個例子中,使用同步方式將不起作用。
這是我們函數(shù)中的最后一行,它簡單的發(fā)送一個空字符串回服務(wù)器。如果沒有這行,xmlObj的readyState永遠不會到4,所以你的頁面永遠不會更新。這個send方法能夠用于作其他事情,但今天我只是用來從服務(wù)器上取得數(shù)據(jù)-并不發(fā)送它-所以在這篇文章中我不準(zhǔn)備介入任何關(guān)于send方法的細節(jié)。
function updateObj(obj, data){ document.getElementById(obj).firstChild.data = data; }
現(xiàn)在再稍微解釋一下updateObj函數(shù):這個函數(shù)使用一個新的值來更新當(dāng)前頁面上任何指定的元素。他的第一個參數(shù),“obj”是當(dāng)前頁面中元素的ID-那個要被更新的對象;它的第二個參數(shù),“data”是用來將那個將被替換值的對象(“obj”)的內(nèi)容替換掉。一般來說,檢驗一下并確定當(dāng)前頁面上確實有一個元素的ID是“obj”是比較明智的,但對我們的腳本的這個隔離級別來說校驗并不必要。這個函數(shù)更新的方式和我們之前從XML文件的“data”節(jié)點取得數(shù)據(jù)的方式類似-它定位它要更新的元素(這時候這個元素的ID代替了它的標(biāo)簽名和在頁面中的索引)并設(shè)置這個元素的第一個子節(jié)點(文本節(jié)點)的data屬性為新的值。如果你需要使用HTML而不是純文本來更新一個元素,你也可以使用
document.getElementById(obj).innerHTML = data
這就是全部了
這個概念很簡單,而且代碼也不是很難。你能夠從某個地方讀取一個文件并且不需要重新加載這個web頁面。你有足夠的靈活性來作各種事情,包括從表單發(fā)送數(shù)據(jù)(不需要重新加載web頁面)并且使用一個服務(wù)端語言來動態(tài)生成XML文件。如果你需要更近一步,記得這個連接是很有用的-哦,還要記得Google是你朋友。在另外的文章中,我將解釋你如何配合服務(wù)端技術(shù)使用AJAX來構(gòu)造強大的web應(yīng)用程序。
關(guān)于作者
Jonathan Fenocchi(mail:jona#slightlyremarkable.com #換成@)是一個網(wǎng)絡(luò)開發(fā)者,主攻web設(shè)計,客戶端腳本,php腳本。 他的網(wǎng)站位于:http://www.slightlyremarkable.com
出處:藍色理想
責(zé)任編輯:moby
上一頁 下一頁 如何使用ajax開發(fā)web應(yīng)用程序 [2]
◎進入論壇網(wǎng)絡(luò)編程版塊參加討論
|