如何使用ajax開發(fā)web應(yīng)用程序第2/2頁
更新時間:2006年09月03日 00:00:00 作者:
在上一篇文章中,我們討論了如何通過javascript從一個遠程XML文件中取得數(shù)據(jù)。在這篇文章中,我們將學(xué)會怎樣對數(shù)據(jù)作更復(fù)雜的處理。作為一個示例,我們會準備一組XML數(shù)據(jù),將數(shù)據(jù)分割成獨立的片斷并以不同的方式展示這些片斷(取決于它們是如何被標識的)。
這篇文章是建立在上一篇文章中構(gòu)造的示例代碼的基礎(chǔ)之上,所以如果你不能理解我們現(xiàn)在的代碼,你可以回過頭去讀第一篇文章(sheneyan注:就在上面)。
開始~
讓我們開始我們的第一步:構(gòu)造XML。我們準備寫一個XML文檔,它組織了一系列準備讓javascript處理的數(shù)據(jù),所以我們將一起組織一些節(jié)點和子節(jié)點(或者,元素和子元素)。在這個例子里,我們將使用一些家庭寵物的名字:
<?xml version="1.0" encoding="UTF-8"?>
<data>
<pets>
<pet>貓</pet>
<pet>狗</pet>
<pet>魚</pet>
</pets>
</data>
在上面,我們有這個XML聲明(標明這個文檔是一個XML 1.0 文檔,使用UTF-8編碼),一個根元素(<data>)將下面所有的元素組合在一起,一個<pets>元素組織了所有的寵物,然后一個<pet>節(jié)點對應(yīng)一只寵物。為了指定每一只寵物是什么類型的動物,我們在<pet>元素中設(shè)置了文本節(jié)點:貓,狗,魚。
<!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>
<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){
processXML(xmlObj.responseXML);
}
}
xmlObj.open ('GET', file, true);
xmlObj.send ('');
}
function processXML(obj){
var dataArray = obj.getElementsByTagName('pet');
var dataArrayLen = dataArray.length;
var insertData = '<table style="width:150px; border: solid 1px #000"><tr><th>'
+ 'Pets</th></tr>';
for (var i=0; i<dataArrayLen; i++){
insertData += '<tr><td>' + dataArray[i].firstChild.data + '</td></tr>';
}
insertData += '</table>';
document.getElementById ('dataArea').innerHTML = insertData;
}
//--></script>
</head>
<body>
<h1>使用Ajax開發(fā)web應(yīng)用程序</h1>
<p>這個頁面演示了AJAX技術(shù)如何通過動態(tài)讀取一個遠程文件來更新一個網(wǎng)頁的內(nèi)容--不需要任何網(wǎng)頁的重新加載。注意:這個例子對于禁止js的用戶來說沒有效果。</p>
<p>這個頁面將演示如從取回并處理成組的XML數(shù)據(jù)。被取回的數(shù)據(jù)將會以表格形式輸出到底下。
<a href="#" onclick="ajaxRead('data_2.xml'); return false">查看演示</a>.</p>
<div id="dataArea"></div>
</body>
</html>
(Sheneyan注:完整代碼示例見 example_2.html ,XML文件見:data_2.xml)
你會注意到我們和上次一樣以同樣的方式(通過一個超鏈接)調(diào)用了這個函數(shù),而且我們將數(shù)據(jù)放入一個DIV(這次這個東東叫做“dataArea”)。這個ajaxRead()函數(shù)和上次很接近,除了一點不同:onreadystatechange函數(shù)。讓我們先看一下這個函數(shù):
xmlObj.onreadystatechange = function(){
if(xmlObj.readyState == 4){
processXML(xmlObj.responseXML);
}
}
我們?nèi)∠藆pdateObj函數(shù)并用一個叫做processXML()的新函數(shù)來代替它。這個函數(shù)將得到XML文檔本身(也就是被ajaxRead函數(shù)取回的)并處理它。(這“XML文檔本身”我指的是參數(shù)“xmlObj.responseXML”)
現(xiàn)在讓我們分析一下這個函數(shù)processXML。下面是它的代碼:
function processXML(obj){
var dataArray = obj.getElementsByTagName('pet');
var dataArrayLen = dataArray.length;
var insertData = '<table style="width:150px; border: solid 1px #000"><tr><th>'
+ 'Pets</th></tr>';
for (var i=0; i<dataArrayLen; i++){
insertData += '<tr><td>' + dataArray[i].firstChild.data + '</td></tr>';
}
insertData += '</table>';
document.getElementById ('dataArea').innerHTML = insertData;
}
首先,我們定義了一些變量。“dataArray”作為所有<pet>節(jié)點的數(shù)組(不是節(jié)點數(shù)據(jù),只是節(jié)點)?!癲ataArrayLen”是這個數(shù)組的長度,用于我們的循環(huán)?!癷nsertData”則是一個表格的開頭的HTML。
我們的第二步則是遍歷所有的<pet>元素(通過變量“dataArray”)并將數(shù)據(jù)添加到變量insertData中。這里我們會創(chuàng)建一個表格行,插入一個表格數(shù)據(jù)節(jié)點(td)進去,再將每一個<pet>元素的文本包含進這個表格數(shù)據(jù)節(jié)點,并將這些都添加進變量“insertData”。因此,每循環(huán)一次,變量insertData將添加一行包含三個寵物中之一名稱的新數(shù)據(jù)。
新數(shù)據(jù)行添加完后,我們插入一個“</table>”結(jié)束標簽到變量“insertData”。這完成了這個表格,然后我只剩這最后一步來達成我們的目標:我們需要將這個表格放到頁面上。幸運的是,我們得感謝innerHTML屬性,這很簡單。我們通過函數(shù)document.getElementById()取得DIV“dataArea”并將變量“insertData”中的HTML插進去。嗯,這個表格冒出來了!
我們繼續(xù)之前……
我得指出兩點:
首先,你會注意到我們并沒有使用節(jié)點<pets>。這事因為我們只有一個數(shù)據(jù)組(<pets>)以及后來所有的元素(每一個<pet>元素);這些子節(jié)點包含了不同的數(shù)據(jù)但它們有相同的名字。在這個例子中,這個節(jié)點能夠被忽略。然而,將所有的元素<pet>放進<pets>元素還是比較好,而不是讓這些<pet>元素自己散放(但仍然在data元素里面)。
另外一種方式是給每一個寵物放一個指定的標簽,比如:
<?xml version="1.0" encoding="UTF-8"?>
<data>
<pets>
<貓 />
<狗 />
<魚 />
</pets>
</data>
然后我們能夠遍歷元素<pets>里的節(jié)點。這個processXML函數(shù)看起來就像這樣:
function processXML(obj){
var dataArray = obj.getElementsByTagName('pets')[0].childNodes;
var dataArrayLen = dataArray.length;
var insertData = '<table style="width:150px; border: solid 1px #000"><tr><th>'
+ 'Pets</th></tr>';
for (var i=0; i<dataArrayLen; i++){
if(dataArray[i].tagName){
insertData += '<tr><td>' + dataArray[i].tagName + '</td></tr>';
}
}
insertData += '</table>';
document.getElementById ('dataArea').innerHTML = insertData;
}
(Sheneyan注:修改后的示例見:example_2_1.html ,XML文件見:data_2_1.xml)
這里所作的修改就是我們指向了<pets>組元素(這個“[0]”意味這是第一個,即使它就是唯一的那一個)以及它的子節(jié)點(元素<貓 />,<狗 />,<魚 />)。因為文本元素分割了這幾個元素(空格被認為是一個節(jié)點),我們需要確定只有那些有標簽名的節(jié)點(嗯,也就是只有標簽)通過。然后我們輸出每一個標簽的名字。因為每一個標簽名是一個寵物,我們不需要取得每一個節(jié)點的數(shù)據(jù)-節(jié)點名本身已經(jīng)足夠。去看一下它是怎么工作的吧。
還有另外一種方式來完成我們上面的工作,就是給每一個<pet>節(jié)點設(shè)置一個屬性值。你的XML文檔看起來就像這樣:
<?xml version="1.0" encoding="UTF-8"?>
<data>
<pets>
<pet type="貓" />
<pet type="狗" />
<pet type="魚" />
</pets>
</data>
你只需要稍微修改一下你的processXML函數(shù),它變成這樣子了:
function processXML(obj){
var dataArray = obj.getElementsByTagName('pet');
var dataArrayLen = dataArray.length;
var insertData = '<table style="width:150px; border: solid 1px #000"><tr><th>'
+ 'Pets</th></tr>';
for (var i=0; i<dataArrayLen; i++){
insertData += '<tr><td>' + dataArray[i].getAttribute('type') + '</td></tr>';
}
insertData += '</table>';
document.getElementById ('dataArea').innerHTML = insertData;
}
(Sheneyan注:修改后的示例見:example_2_2.html ,XML文件見:data_2_2.xml)
關(guān)鍵的不同在于我們通過dataArray[i].getAttribute('type')取得值,它返回了當前<pet>節(jié)點的“type”屬性的值。
繼續(xù)...
現(xiàn)在我們已經(jīng)知道了一些從一個單獨的XML數(shù)據(jù)組中取回數(shù)據(jù)的有效方法,讓我們看看如何從多個組中取回數(shù)據(jù)。和只是列出一個pets所擁有的內(nèi)容不同,我們假設(shè)我們有一個針對我們寵物的日課表。因為它們都有不同的需要,每一只寵物都得仔細的照顧。面對這種情況,動物的看管員需要一個每日依據(jù)。現(xiàn)在來讓我們將這些放入一個良好格式的XML:
<?xml version="1.0" encoding="UTF-8"?>
<data>
<pets>
<pet>Cat
<task>Feed</task>
<task>Water</task>
<task>Comb out fleas</task>
</pet>
<pet>Dog
<task>Feed</task>
<task>Water</task>
<task>Put outside</task>
</pet>
<pet>Fish
<task>Feed</task>
<task>Check oxygen, water purity, etc.</task>
</pet>
</pets>
</data>
也許這個看起來很奇怪,但這就是我們正在創(chuàng)建的子組(sub-group)。每一個<pet>元素都是一個組<pets>的子組,而每一個<task>則是每一個<pet>組的子元素。
在我繼續(xù)之前,你也許希望將你的表格用一些css美化一下,比如:
<style type="text/css"><!--
table, tr, th, td {
border: solid 1px #000;
border-collapse: collapse;
padding: 5px;
}
--></style>
這讓這個表格更容易讀取?,F(xiàn)在讓我們?nèi)パ芯亢瘮?shù)processXML:
function processXML(obj){
var dataArray = obj.getElementsByTagName('pet');
var dataArrayLen = dataArray.length;
var subAry, subAryLen;
var insertData = '<table><tr><th>'
+ 'Pets</th><th>Tasks</th></tr>';
for (var i=0; i<dataArrayLen; i++){
insertData += '<tr><td>' + dataArray[i].firstChild.data + '</td>';
subAry = dataArray[i].getElementsByTagName('task');
subAryLen = subAry.length;
insertData += '<td>';
for(var j=0; j<subAryLen; j++){
insertData += subAry[j].firstChild.data;
if( subAryLen != j+1 ) { insertData += ', '; }
}
insertData += '</td></tr>';
}
insertData += '</table>';
document.getElementById ('dataArea').innerHTML = insertData;
}
(Sheneyan注:修改后的示例見:example_2_3.html ,XML文件見:data_2_3.xml)
新增加的內(nèi)容,首先是兩個新變量的聲明:“subAry”和“subAryLen”。它們和之前的變量“dataArray”和“dataArrayLen”類似,除了它們指向不同的數(shù)組(特別是它們將指向那些“task”元素-當“dataArray”和“dataArrayLen”指向“pet”元素的時候)。
我們也改變了變量“insertData”的初始值-我們增加了一個表格頭(<th>)給我們的“tasks”字段。
下一步改變在于循環(huán):我們把值賦給subAry和subAryLen變量。變量subAry成為當前<pet>的<task>元素的數(shù)組。變量subAryLen成為這個數(shù)組的長度,直到這個數(shù)組發(fā)生變化(當外部循環(huán)走到下一個<pet>時)。
我們創(chuàng)建了一個內(nèi)嵌的循環(huán)來處理所有的<task>元素,一次一個。大概來說,我們創(chuàng)建一個新的數(shù)據(jù)格,放進一個用逗號分隔的任務(wù)列表,然后關(guān)閉數(shù)據(jù)表格以及當前行。尤其,這些<task>元素節(jié)點數(shù)據(jù)(任務(wù)本身,比如,“喂食”)放置入變量“insertData”里的數(shù)據(jù)格。
接下來,我們檢驗當前<pet>是否有其它更多的task。如果還有,我們增加一個逗號(,)到變量insertData來讓每一個任務(wù)使用一個逗號分隔(“a, b, c”,而不是“a, b, c,”-注意,最后一個逗號在第二個任務(wù)那里,所以我們不需要)。這個工作在我們?nèi)〉胹ubAry數(shù)組長度的時候(給循環(huán)的“j”變量加1)就完成了。因為這個循環(huán)會在下一個循環(huán)的時候把變量“j”遞增1,“j”會比它這次檢驗時還多1。因此,如果“j+1”(或者,“當循環(huán)再次開始的時候j的值”)等于subAryLen(當前<pet>節(jié)點的<task>節(jié)點數(shù)目),這個循環(huán)將停止。如果循環(huán)不再運行,我們就不再添加新的逗號來分隔任務(wù)。所以如果“j+1”不等于subAryLen,我們直到我們可以安全的加入逗號到“insertData”,為下一個<task>作準備。
一旦內(nèi)循環(huán)結(jié)束,我們關(guān)閉task數(shù)據(jù)格以及pet行。外部循環(huán)會重新開始創(chuàng)建一個新行以及移動到下一個<pet>。這個處理一直進行到所有的<pet>元素(以及每一個pet的所有<task>元素)都被處理完。
有其他方法嗎?
你也許會想:“那javascript變得相當復(fù)雜了,但它只會隨著XML越來越復(fù)雜而跟著變復(fù)雜,也許我們能夠簡化XML,然后,簡化javascript”。如果你這么想,很棒,因為你完全正確。我之前展示的不同方法之一,我詳細說明的那個也許能夠成為最合適的。我們怎么使用屬性來對應(yīng)每一只寵物以及相應(yīng)任務(wù)?XML看起來會變成怎樣?
<?xml version="1.0" encoding="UTF-8"?>
<data>
<pets>
<pet type="Cat" tasks="Feed, Water, Comb out fleas" />
<pet type="Dog" tasks="Feed, Water, Put outside" />
<pet type="Fish" tasks="Feed, Check oxygen, water purity, etc." />
</pets>
</data>
哇哦!看起來簡單多了。讓我們看看我們的processXML函數(shù)如何修改:
function processXML(obj){
var dataArray = obj.getElementsByTagName('pet');
var dataArrayLen = dataArray.length;
var insertData = '<table><tr><th>'
+ 'Pets</th><th>Tasks</th></tr>';
for (var i=0; i<dataArrayLen; i++){
insertData += '<tr><td>' + dataArray[i].getAttribute('type') + '</td>'
+ '<td>' + dataArray[i].getAttribute('tasks') + '</td></tr>';
}
insertData += '</table>';
document.getElementById ('dataArea').innerHTML = insertData;
}
(Sheneyan注:修改后的示例見:example_2_4.html,XML文件見:data_2_4.xml)
就像你猜的一樣,函數(shù)簡單多了。因為代碼變得簡單,它也會變得更有效率。和我們比較老的函數(shù)的唯一的不同在于這個變量insertData現(xiàn)在插入更多的HTML,尤其是兩個新變量“type”和“tasks”。就如我們較早之前所學(xué)的,那些屬性是我們從XML文檔的<pet>元素中取得的,而且每個pet的屬性都有不同的值。對于你自己修改這個XML文件以適應(yīng)你的進度的變動來說也許是最簡單的方法。例如,如果你最終把你的貓身上的跳蚤抓光了,你只要簡單從你的貓的每日任務(wù)表中把“減少跳蚤數(shù)量”刪除,然而在之前我們使用的XML中,實現(xiàn)起來也許會覺得糊里糊涂。
最后的XML格式化的方法是將兩部分混合。現(xiàn)在,我們將使用屬性和不同的標簽。讓我們看一下示例XML:
<?xml version="1.0" encoding="UTF-8"?>
<data>
<pets>
<貓 tasks="喂食, 飲水, 減少跳蚤數(shù)量" />
<狗 tasks="喂食, 飲水, 帶出去遛遛" />
<魚 tasks="喂食, 檢查氧氣,水的純度,其它" />
</pets>
</data>
這也許是最便于理解的XML。讓我們分析一下我們?yōu)榱俗宲rocessXML函數(shù)運作起來所作的變更:
function processXML(obj){
var dataArray = obj.getElementsByTagName('pets')[0].childNodes;
var dataArrayLen = dataArray.length;
var insertData = '<table><tr><th>'
+ 'Pets</th><th>Tasks</th></tr>';
for (var i=0; i<dataArrayLen; i++){
if(dataArray[i].tagName){
insertData += '<tr><td>' + dataArray[i].tagName + '</td>'
+ '<td>' + dataArray[i].getAttribute('tasks') + '</td></tr>';
}
}
insertData += '</table>';
document.getElementById ('dataArea').innerHTML = insertData;
}
(Sheneyan注:修改后的示例見:example_2_5.html,XML文件見:data_2_5.xml)
“dataArray”現(xiàn)在指向了<pets>的子節(jié)點,將它們作為一個數(shù)組對待(換句話說,dataArray現(xiàn)在是在<pets>節(jié)點內(nèi)所有節(jié)點的數(shù)組)。這事因為每一個標簽都不同(<貓 />,<狗 />,<魚 />),所以我們不能使用這些元素的名稱來搜索它們(而之前我們可以使用<pet>,因為所有的元素都是<pet>)。
還是一樣,每個節(jié)點之間的有空格,所以在我們的處理過程中得排除掉文本節(jié)點。我們能夠檢驗標簽名是否存在-文本節(jié)點是節(jié)點但沒有標簽,而<貓 />,<狗 />,<魚 />節(jié)點都是標簽。所以如果一個標簽有名字,那我們能夠?qū)?shù)據(jù)插入變量insertData。我們插入的數(shù)據(jù)是一個表格并有兩個表格數(shù)據(jù)格。這第一個單元格是標簽名,也就是寵物的類型(貓,狗或魚),而第二個單元格則是指定動物的“tasks”屬性值(比如“喂食或飲水”)。
結(jié)束語
在這篇文章里,我演示了這個例子的很多變化,你可以隨意試驗它們來檢驗?zāi)膫€更適合你。只要記住一點,XML是“可擴展的”,所以沒有“錯誤的”方法來組合你的數(shù)據(jù),雖然經(jīng)常有一個“最好的”方法。而且,要注意讓你的XML保持格式良好。記住很多問題來自于忘記結(jié)束一個標簽(比如<狗 />而不是<狗>;除非這個節(jié)點中有數(shù)據(jù),比如下面的<狗>這里有數(shù)據(jù)哦</狗>)。
我意圖使XML和javascript的應(yīng)用不糊涂而變得明朗。一步步的學(xué)習(xí)處理更多的數(shù)據(jù),你能夠?qū)jax運用于更大的用途。我希望看到ajax更多的應(yīng)用于企業(yè)網(wǎng)站,及其它。所以如果你將這些知識應(yīng)用于實踐,我很高興了解到你學(xué)到了什么(mail:jona#slightlyremarkable.com #換成@)。
相關(guān)文章
django中使用jquery ajax post數(shù)據(jù)出現(xiàn)403錯誤的解決辦法(兩種方法)
在django中,使用jquery ajax post數(shù)據(jù),會出現(xiàn)403的錯誤,大家知道該如何解決嗎?下面由腳本之家小編給大家分享兩種解決辦法,需要的朋友可以參考下2015-09-09SSH網(wǎng)上商城之使用ajax完成用戶名是否存在異步校驗
這篇文章主要介紹了SSH網(wǎng)上商城之使用ajax完成用戶名是否存在異步校驗的相關(guān)資料,需要的朋友可以參考下2015-12-12妙用Ajax技術(shù)實現(xiàn)局部刷新商品數(shù)量和總價實例代碼
這篇文章主要給大家介紹妙用Ajax技術(shù)實現(xiàn)局部刷新商品數(shù)量和總價實例代碼,非常不錯,需要的朋友一起看看吧2016-05-05基于Ajax的formData圖片和數(shù)據(jù)上傳
這篇文章主要為大家詳細介紹了基于Ajax的formData圖片和數(shù)據(jù)上傳相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-05-05Jquery中ajax提交表單幾種方法(get、post兩種方法)
ajax技術(shù)帶給我們的是良好的用戶體驗,同時,使用jquery可以簡化開發(fā),提高工作效率,接下來,腳本之家小編給大家分享Jquery中ajax提交表單幾種方法,需要的朋友可以參考下2015-09-09