探討Ajax獲取表單值向Servlet傳遞的設(shè)計方案_第1頁
探討Ajax獲取表單值向Servlet傳遞的設(shè)計方案_第2頁
探討Ajax獲取表單值向Servlet傳遞的設(shè)計方案_第3頁
探討Ajax獲取表單值向Servlet傳遞的設(shè)計方案_第4頁
探討Ajax獲取表單值向Servlet傳遞的設(shè)計方案_第5頁
已閱讀5頁,還剩16頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、探討Ajax獲取表單值向Servlet傳遞的設(shè)計方案 現(xiàn)在JavaWeb領(lǐng)域,MVC框架越來越多,比較出名的有Struts、Struts2、SpringMVC、WebWork等。而Ajax,作為一種與特定的動態(tài)Web編程語言(如Java、C#、PHP)無關(guān)的技術(shù),也已經(jīng)被引入到了Java MVC框架的各家各戶。而這些MVC框架,歸根到底,都是對Servlet技術(shù)的封裝。同時,支持Ajax的JavaScript框架(or類庫)也越來越多,出名的如Jquery、Ext、Prototype、DWR等,而它們實現(xiàn)異步傳輸功能還是離不開JavaScript中的XMLHttpRequest這個對象。好,轉(zhuǎn)

2、入正題吧。Ajax通過XMLHttpRequest對象實現(xiàn)異步傳輸,那我們首先要獲取這個對象。由于瀏覽器的差異,為了兼容各種常用的瀏覽器,先寫一個初始化XMLHttpRequest對象的方法,代碼如下: Js代碼 /* * Get方式向服務(wù)器端異步發(fā)送數(shù)據(jù) * param url 服務(wù)器端的路徑,數(shù)據(jù)發(fā)送的目的地 * param data 發(fā)送的數(shù)據(jù),格式如: key1=value1&key2=value2 * param callback 回調(diào)函數(shù), */ function doGet(url, data, callback) var url = url; if(url.indexOf(?)

3、 = -1) url = url + ? + data; else url = url + & + data; initXmlHttp(); xmlHttp.onreadystatechange = callback; /注冊回調(diào)函數(shù) xmlHttp.open(GET, url, true); /設(shè)置連接信息 xmlHttp.send(null); /* * Post方式向服務(wù)器端異步發(fā)送數(shù)據(jù) * param url 服務(wù)器端的路徑,數(shù)據(jù)發(fā)送的目的地 * param data 發(fā)送的數(shù)據(jù),格式如: key1=value1&key2=value2 * param callback 回調(diào)函數(shù) *

4、return */ function doPost(url, data, callback) initXmlHttp(); /初始化 xmlHttp.onreadystatechange = callback; /注冊回調(diào)函數(shù) xmlHttp.open(POST, url, true); xmlHttp.setRequestHeader(Content-Type, application/x-www-form-urlencoded); xmlHttp.send(data); /* * 默認回調(diào)函數(shù) * 只在測試時使用,在doGet和doPost函數(shù)中的第三個參數(shù)callback,可由用戶自定義

5、回調(diào)函數(shù), * 若不設(shè)定,則調(diào)用默認的回調(diào)函數(shù) */ function callback() /判斷對象的狀態(tài)是否交互完成 if(xmlHttp.readyState = 4) /判斷http的交互是否成功 if(xmlHttp.status = 200) /獲取服務(wù)器返回的純文本數(shù)據(jù) var responseText = xmlHttp.responseText; /獲取服務(wù)器返回的XML格式數(shù)據(jù) /var responseXml = xmlHttp.responseXML; /Alert從服務(wù)器端返回的信息 window.alert(responseText); 對上面的代碼,在這里解析一

6、下:XMLHttpRequest對象的請求狀態(tài)(readyState)有0、1、2、3、4,其中,0表示未初始化,1表示open方法成功調(diào)用,2表示服務(wù)器應(yīng)答客戶端請求,3表示交互中,HTTP頭信息已經(jīng)收到,但響應(yīng)數(shù)據(jù)還沒有接收,4表示數(shù)據(jù)接收完成。我們通過“xmlHttp.onreadystatechange = callback;”來設(shè)置如果XMLHttpRequest對象的請求狀態(tài)發(fā)生改變了,則會執(zhí)行回調(diào)函數(shù)callback。我們可以看到,在callback方法體中,我們只關(guān)心readyState=4(交互完成)的情況,再獲取從服務(wù)器端返回的狀態(tài)碼status,常見的狀態(tài)碼有:200表示

7、交互成功,404表示頁面沒找到,500表示服務(wù)器處理錯誤等。接著,通過XMLHttpRequest的responseText屬性得到從服務(wù)器端返回的文本數(shù)據(jù),或者通過responseXML屬性獲得XML格式的數(shù)據(jù)。在上面的代碼中,doGet方法和doPost方法都有參數(shù)”data”,它由XMLHttpRequest負責從客戶端傳送到服務(wù)器端,對于Get方法,附在URL尾部,例如:member.jsp?name=xxx&sex=male。對于Post方式,可調(diào)用XMLHttpRequest的send方法發(fā)送。data的數(shù)據(jù)形式比較靈活,可以是普通的參數(shù)格式、XML格式,JSON格式或者是其他格式

8、,只要你能發(fā)送過去,服務(wù)器端就有辦法將你解析出來。在這里,我們降低難度,就用最簡單的參數(shù)格式,即key1=value1 & key2=value2 & key3=value3 & 我們都知道,HTTP協(xié)議的Get方式傳輸數(shù)據(jù),是通過把這些key-value串附到URL后面的,也就是我們只要點表單的提交按鈕,就可以看到地址欄后面會多了一串key-value,代表表單里各輸入框的名和值。然后,我們要做異步發(fā)送數(shù)據(jù),就不能用表單的自動提交了,也就是說,得自己一個一個獲取到各輸入框的數(shù)據(jù),然后再一個一個拼成上面的key-value串再發(fā)送。有沒有一種簡單的辦法來組織這些數(shù)據(jù)呢?大家看到key-valu

9、e是否會想到Java中的什么類?請看下面代碼,我用JavaScript寫了一個Map類(JavaScript中的“function”可以看作是方法,也可以看作是面向?qū)ο蟮摹邦悺保褪穷愃朴贘ava中我們常用的Map接口。 Java代碼 /* * Map類 * 實現(xiàn)了類似于Java語言中的Map接口的常用方法 */ function Map() /key集 this.keys = new Array(); /value集 this.values = new Array(); /添加key-value進Map this.put = function(key, value) if(key = nu

10、ll | key = undefined) return; var length = this.size(); for(var i = 0 ; i length ; i + ) /如果keys數(shù)組中有相同的記錄,則不覆蓋原記錄的值 if(this.keysi = key) this.valuesi = value; this.keys.push(key); this.values.push(value); ; /獲取指定key的value this.get = function(key) var length = this.size(); for(var i = 0 ; i length ;

11、i + ) if(this.keysi = key) return this.valuesi; else continue; return null; ; /移除指定key所對應(yīng)的map this.remove = function(key) var length = this.size(); for(var i = 0 ; i length ; i + ) if(this.keysi = key) while(i length - 1) this.keysi = this.keysi+1; this.valuesi = this.valuesi+1; i + ; /處理最后一個元素 this

12、.keys.pop(); this.values.pop(); break; ; /是否包含指定的key this.containsKey = function(key) var length = this.size(); for(var i = 0 ; i length ; i + ) if(this.keysi = key) return true; return false; ; /是否包含指定的value this.containsValue = function(value) var length = this.size(); for(var i = 0 ; i length ; i

13、 + ) if(this.valuesi = value) return true; return false; ; /包含記錄總數(shù) this.size = function() return this.keys.length; ; /是否為空 this.isEmpty = function() return this.size() = 0 ? true : false; ; /清空Map this.clear = function() this.keys = new Array(); this.values = new Array(); ; /將map轉(zhuǎn)成字符串,格式:key1=value1

14、,key2=value2 this.toString = function() var length = this.size(); var str = ; for(var i = 0 ; i length ; i + ) str = str + this.keysi + = + this.valuesi; if(i != length-1) str += ,; return str; ; 代碼比較長,有些方法在本例中可能用不到,但也寫出來了,或者在其他地方可能有用吧。當我們使用這個Map類來存儲HTTP的參數(shù)時,發(fā)覺有幾個不妥的地方:一是put方法,在Java的Map接口中,是不允許有重復(fù)的k

15、ey存在的,而在JavaScript中作為傳輸參數(shù)的載體時,很多時候會出現(xiàn)多個同名的key的,例如處理表單的checkbox時,同一個name的有幾個checkbox,構(gòu)成一個復(fù)選框組,組織參數(shù)時就形如“key=value1&key=value2”,故put方法必須改。也是由于這個原因,get方法和remove方法也要改。二是toString方法,key=value對,不是用“,”號隔開的,而是用“&”號,故toString方法也須改。而有時候想想,如果把Map類改了,如果其他地方要用到的話,是不是還是改回來,與其改來改去的,不如繼承它,重寫put、get、remove和toString方法。

16、好主意,代碼如下:Js代碼 /* * ParamMap類,用于存儲HTTP請求中的Get方法或者Post方法所傳遞的參數(shù) * 繼承于Map類,但改寫一些方法,以適合HTTP請求中的參數(shù)格式 * 與Map不同之處有:ParamMap允許多個同名的key存在, * toString方法返回的key=value對以&號連接,而不是,號,等等。 */ function ParamMap() /繼承Map類 Map.call(this); /重寫put方法,允許多個同名key存在 this.put = function(key, value) if(key = null | key = undefine

17、d) return; this.keys.push(key); this.values.push(value); ; /重寫get方法,返回values數(shù)組 this.get = function(key) var results = new Array(); var length = this.size(); for(var i = 0 ; i length ; i + ) if(this.keysi = key) results.push(this.valuesi); return results; ; /重寫remove方法 this.remove = function(key) var

18、 length = this.size(); for(var i = 0 ; i length ; i + ) if(this.keysi = key) while(i length - 1) this.keysi = this.keysi+1; this.valuesi = this.valuesi+1; i + ; /處理最后一個元素 this.keys.pop(); this.values.pop(); ; /重寫toString方法, 轉(zhuǎn)成XMLHttpRequest.send(ajaxString)方法的參數(shù)格式的字符串, /形如:key1=value1&key2=value2 th

19、is.toString = function() var length = this.size(); var str = ; for(var i = 0 ; i length ; i + ) str = str + this.keysi + = + this.valuesi; if(i != length-1) str += &; return str; ; 怎么使用這個ParamMap類呢,且看下面的示例代碼:Js代碼 var username = document.getElementById(username).value; var password = document.getElem

20、entById(password).value; var sex = document.getElementById(sex).value; var map = new ParamMap(); map.put(username, username); map.put(password, password); map.put(sex, sex); doGet(test/register, map.toString(), callback); doPost(test/register, map.toString(), callback); Js代碼 在JavaScript中,用來獲取HTML結(jié)點的

21、方法,常用的有如下方法:Js代碼 Node document.getElementById(username) /根據(jù)標簽的id NodeList document.getElementsByName(“username”) /根據(jù)標簽的name NodeList document.getElementsByTagName(input) /根據(jù)標簽的標簽名 我們注意到在除了getElementById是返回Node對象外,其他兩個方法都是返回NodeList對象,相當于Node數(shù)組。在Ajax應(yīng)用中,根據(jù)ID來獲取節(jié)點,很多時候十分方便,如獲取text、password、hidden、text

22、area類型的值,但有時候并不那么方便,如處理checkbox、radio(不允許多個同名的id)。況且有許多情況下,開發(fā)者是由“非Ajax”轉(zhuǎn)成Ajax應(yīng)用的。在還沒有引進Ajax的時候,表單傳值都是根據(jù)輸入域的name的值來區(qū)分的,不管是Get方式還是Post方式,在服務(wù)器端(這里指Java Servlet)獲取數(shù)據(jù)的代碼如下:Java代碼 String HttpServletRequest.getParameter(keyName); /用于單值表單域 String HttpServletRequest.getParameterValues(keyName); /用于多值表單域 所謂的“

23、單值表單域”就是上面提到過的type為text、password、hidden的input或者textarea等,而“多值表單域”是指checkbox。其實,也不盡然,如單值表單域有時候也可以是多值表單域,如我們注冊時有時會要求填多個郵箱,這個就可以重復(fù)多行用同一個name,它在Servlet端獲取值方式跟checkbox一樣處理。鑒于各種原因,我們在JavaScript獲取HTML Form表單域方法,決定采用getElementsByName方法,這樣,我們是不是每取一個表單元素,就得將NodeList類型的返回結(jié)果遍歷一遍,獲取Node,再從Node獲取值呢?既然選擇了這樣做,當然少不了

24、這樣的工作,不過,我們可以寫一個可重用的方法,讓它處理一下NodeList對象。且看代碼: Js代碼 /* * 獲取nodeList的值集 * param nodeList Node數(shù)組,可通過getElementsByName或者getElementsByTagName等方法獲得 * return 值數(shù)組 */ function nodeList2ValuesArray(nodeList) /結(jié)果值數(shù)組,形如:aaa,bbb,ccc var values = new Array(); var length = nodeList.length; var nodeName = nodeList.

25、item(0).nodeName; /對的處理 if(nodeName = INPUT) var type = nodeList.item(0).getAttribute(type); if(type = text | type = password | type = hidden) for(var i = 0 ; i length ; i + ) values.push(nodeList.item(i).value); else if(type = checkbox | type = radio) for(var i = 0 ; i length ; i + ) var node = nod

26、eList.item(i); if(node.checked) values.push(node.value); /對xxx的處理 else if(nodeName = TEXTAREA) for(var i = 0 ; i length ; i + ) values.push(nodeList.item(i).value); /對的處理 else if (nodeName = SELECT) var subNodeList = nodeList.item(0).getElementsByTagName(option); return nodeList2ValuesArray(subNodeL

27、ist); /對的子元素xxx的處理 else if (nodeName = OPTION) for(var i = 0 ; i length ; i + ) var node = nodeList.item(i); if(node.selected) values.push(node.value); return values; 上面代碼將NodeList轉(zhuǎn)成了值數(shù)組,而且讓使用者忽略表單域類型的差異,專心于值的獲取和使用。美中不足的是,上面的方法返回的是數(shù)組,我們還是一個一個遍歷再拼成key=value字符串。接下來的方法不但解決了這一點,而且還大大簡化我們的表單取值,且看: Js代碼 /

28、* * 解析表單的數(shù)據(jù),轉(zhuǎn)成ParamMap的形式 * param 任意個參數(shù),代表表單子元素的name值 * return ParamMap結(jié)果集 */ function parseForm2ParamMap() var map = new ParamMap(); /參數(shù)的長度,注意:方法定義的括號中雖然沒有定義參數(shù),但卻可以設(shè)任意多個參數(shù) var length = arguments.length; for(var i = 0 ; i length ; i + ) var nodeList = document.getElementsByName(argumentsi); var valu

29、es = nodeList2ValuesArray(nodeList); for(var j = 0 ; j values.length ; j + ) map.put(argumentsi, valuesj); return map; 這個方法返回值的類型是ParamMap,也就是我們剛才定義的用來傳遞參數(shù)的類,這個類中有一個toString的方法,不就是返回“key1=value1&key2=value2”形式的字符串嗎?OK,下面的測試例子,將涉及到表單的各種元素域,其中引進了ajax.js文件,其內(nèi)容即是我們上面所寫的JS函數(shù)和類,在附件中可下載到,在此就不重復(fù)貼出來了。且看HTML代

30、碼: Html代碼 測試Ajax與Servlet之間的數(shù)據(jù)傳遞 window.onload = function() var submit = document.getElementById(submit); submit.onclick = function() var map = parseForm2ParamMap(username, email, password, userid, sex, framework, salary, dream); /doPost(input, map.toString(), callback); /默認Alert出信息 doPost(input, map

31、.toString(), function() if(xmlHttp.readyState = 4) if(xmlHttp.status = 200) var returnMsg = document.getElementById(returnMsg); returnMsg.innerHTML = xmlHttp.responseText; ); ; ; 測試Ajax與Servlet之間的數(shù)據(jù)傳遞(Step1:從Client-Server) 你的姓名: 你的電子郵件(可填兩個): 郵件地址1: 郵件地址2: 你的密碼: 你的性別 : 男 女 你掌握的開源框架 : Struts Spring H

32、ibernate iBatis WebWork 你的薪水范圍 : 2000以下 20003000 30004000 40005000 5000以上 你的職業(yè)夢想: 服務(wù)器端的代碼如下:Java代碼 package simple.rongxh.servlet; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServle

33、tRequest; import javax.servlet.http.HttpServletResponse; /* * RongXinHua心夢帆影 * site1: * site2: /rongxh7 * author rongxinhua * */ public class Input extends HttpServlet private static final long serialVersionUID = 1L; private void process(HttpServletRequest request, HttpServletResponse response) thro

34、ws ServletException, IOException /獲取數(shù)據(jù) request.setCharacterEncoding(UTF-8); String username = request.getParameter(username); String emails = request.getParameterValues(email); String password = request.getParameter(password); String userid = request.getParameter(userid); String sex = request.getPar

35、ameter(sex); String framework = request.getParameterValues(framework); String salary = request.getParameter(salary); String dream = request.getParameter(dream); /響應(yīng)給客戶端 response.setContentType(text/html;charset=UTF-8); PrintWriter out = response.getWriter(); out.append(恭喜你,保存成功,你的基本信息如下:); out.appen

36、d(姓名: + username + ); for(int i = 0 ; i emails.length ; i + ) out.append(郵箱 + (i+1) + : + emailsi + ); out.append(密碼: + password + ); out.append(編號: + userid + ); out.append(性別: + sex + ); out.append(框架:); for(int i = 0 ; framework != null & i framework.length ; i + ) out.append(frameworki + ); out.

37、append(); out.append(薪水: + salary + ); out.append(夢想: + dream + ); out.println(); protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException process(request, response); protected void doPost(HttpServletRequest request, HttpServletResponse resp

38、onse) throws ServletException, IOException process(request, response); 運行結(jié)果截圖如下:附錄資料:從 XML 生成可與 Ajax 共同使用的 JSON時下,非常流行使用 JavaScript 代碼為數(shù)據(jù)驅(qū)動的 Web 應(yīng)用程序添加互動性。若能將數(shù)據(jù)編碼成 JavaScript Object Notation(JSON)的格式,您就可以更輕松地通過 JavaScript 語言使用它。通過本文,發(fā)掘使用 XSLT V2 從 XML 數(shù)據(jù)生成 JSON 的幾種不同方法。幾年前,許多開發(fā)人員很看好 XML、XSLT、Extensi

39、ble HTML (XHTML)和其他一些基于標記的語言?,F(xiàn)在,Asynchronous JavaScript and XML(AJAX)成了新的熱點,人們又將目光轉(zhuǎn)向了使用 JavaScript 代碼的數(shù)據(jù)驅(qū)動的富 Internet 應(yīng)用程序。但是開發(fā)人員是否已經(jīng)消除了 XML 和這一新技術(shù)之間的鴻溝呢?當然,您可以在 Web 客戶機中使用 XML 解析器來讀取數(shù)據(jù),但這種做法會帶來兩個問題。第一,出于安全方面的原因,XML 數(shù)據(jù)只能從與此頁面相同的那個域中讀取。這雖然不是什么大的限制因素,但它的確會引起部署方面的問題,還會阻礙 DHTML 小部件的創(chuàng)建。第二,讀取和解析 XML 會非常慢。

40、另一種做法是讓服務(wù)器執(zhí)行 XML 的解析工作,方法是設(shè)置服務(wù)器,使之向瀏覽器發(fā)送以 JavaScript 代碼或時下流行的 JavaScript Object Notation(JSON)編碼的數(shù)據(jù)。本文將展示如下三種使用 XSLT V2 語言和 Saxon XSLT V2 處理器從 XML 數(shù)據(jù)生成 JSON 的技巧: 簡單編碼 通過函數(shù)調(diào)用加載數(shù)據(jù) 編碼對象 JSON 簡介要學(xué)習(xí)如何將數(shù)據(jù)編碼成 JSON(它只是 JavaScript 的一個子集),最好的方法是從數(shù)據(jù)開始。清單 1 顯示了書籍列表的一個示例 XML 數(shù)據(jù)集。清單 1. 基本的圖形化圖書館 Code Generation i

41、n Action JackHerrington Manning PHP Hacks JackHerrington OReilly Podcasting Hacks JackHerrington OReilly 這個數(shù)據(jù)集很簡單,只包含三本書,每本書都具有惟一的 ID、書名、作者姓名及出版商的名字。(沒錯,我只選擇了我自己的書作為數(shù)據(jù)集,但能怨我嗎?這些書實在是不可多得的節(jié)日和生日禮物。)清單 2 顯示了這些數(shù)據(jù)在 JSON 中的效果。清單 2. JSON 中的示例數(shù)據(jù)集 id: 1, title: Code Generation in Action, first: Jack, last: He

42、rrington, publisher: Manning , . 方括號 () 表明這是一個數(shù)組。大括號 () 則表明這是一個散列表,該散列表由一組名稱和值對組成。在本例中,我創(chuàng)建了一個散列表的數(shù)組 用來存儲這類結(jié)構(gòu)式數(shù)據(jù)的一種常見方法。另外一點值得注意的是字符串是通過單引號或雙引號被編碼的。所以,如果我想用單引號編碼 OReilly,我就必須使用反斜杠對它進行轉(zhuǎn)義:OReilly。 這讓我編寫的這個 XSLT 樣式表更為有趣了一些。我并未在本例中放上任何日期,但您也可以通過如下兩種方法來編碼日期。第一種方法是將日期作為字符串,該字符串必須在后面被解析。第二種方法是將日期作為一個對象,比如:p

43、ublishdate: new Date( 2006, 6, 16, 17, 45, 0 )這段代碼將 publishdate 的值設(shè)置為6/16/2006 5:45:00 p.m.。簡單編碼接下來我將陸續(xù)介紹 JSON 編碼的幾種技巧。第一種也是其中最簡單的一種,此樣式表如 清單 3 所示。清單 3. simple.xsl 樣式表 var g_books = 1, id: ,name: ,first: ,last: ,publisher: ;要理解此樣式表,不妨先來看一下 清單 4 所示的輸出。清單 4. simple.xsl 的輸出var g_books = id: 1,name: Cod

44、e Generation in Action,first: Jack,last: Herrington,publisher: Manning, id: 2,name: PHP Hacks,first: Jack,last: Herrington,publisher: OReilly, id: 3,name: Podcasting Hacks,first: Jack,last: Herrington,publisher: OReilly;這里,我將名為 g_books 的變量設(shè)置為一個包含三個散列表的數(shù)組,每個散列表包含關(guān)于該書的信息。再回過頭來看看 清單 3,您會發(fā)現(xiàn)第一個模板匹配 / 路徑,

45、它也是首先應(yīng)用到輸入數(shù)據(jù)集的模板,該模板使用 for-each 循環(huán)來遍歷每本書。之后,它使用 標記來將文本從該數(shù)據(jù)輸出到 JavaScript 輸出代碼。對于字符串,我使用名為 js:escape() 的定制函數(shù),它在模板之前定義。該函數(shù)使用一個正則表達式將一個單引號標記更改為帶有反斜杠的單引號標記。最后一個重要的元素是 標記,它告知處理器要輸出的是文本而不是 XML。要檢驗此過程是否可以正常工作,我加入了一個 simple .html 文件,該文件引用我在 simple.js 保存的 XSL 樣式表的輸出。這個 HTML 文件如 清單 5 所示。清單 5. simple.html 文件Si

46、mple JS loaderdocument.write( Found +g_books.length+ books );.html 文件使用 標記簡單地加載已編碼了的 JavaScript 代碼。之后,第二個 標記將數(shù)組的長度寫出到瀏覽器頁面,如 圖 1 所示。圖 1. simple.html 的輸出好了!數(shù)據(jù)文件包含三本書,相應(yīng)的 JavaScript 文件也包含三本書。它真的可以工作!通過函數(shù)加載上述第一個示例很簡單,而且在大多數(shù)情況下可以發(fā)揮其作用,但它存在一些問題。第一個問題是對于數(shù)據(jù)何時被加載沒有任何提示。如果數(shù)據(jù)是像頁面那樣被靜態(tài)加載的,這不成問題。但是如果頁面動態(tài)創(chuàng)建了一個 標

47、記來按需加載數(shù)據(jù),那么就很有必要知道 標記是何時完成的。實現(xiàn)此功能的最好的方法是讓編碼了的數(shù)據(jù)調(diào)用一個 JavaScript 函數(shù),而不是只設(shè)置數(shù)據(jù)。這個概念很重要,所以我將花一些時間來介紹一下為什么您必須要通過動態(tài)生成的 標記來加載數(shù)據(jù)。頁面加載后,從服務(wù)器獲得數(shù)據(jù)是 Web 2.0 的核心功能。一種方法是使用 AJAX 機制通過到服務(wù)器的調(diào)用來加載 XML。然而,出于安全性的原因,AJAX 機制只限于從單一域獲取數(shù)據(jù)。這在大多數(shù)情況下都沒有問題,但有時,您可能需要 JavaScript 代碼運行在他人的頁面上(例如,Google Maps)。在這種情況下從服務(wù)器獲得數(shù)據(jù)的惟一方法是通過動態(tài)

48、加載 標記。獲悉 標記何時加載的最好的方法是讓 標記返回的腳本調(diào)用函數(shù)而不是簡單地加載數(shù)據(jù)。清單 6 顯示了在函數(shù)調(diào)用中編碼的數(shù)據(jù)。清單 6. Function1.jsAddBooks( id: 1,name: Code Generation in Action,first: Jack,last: Herrington,publisher: Manning, id: 2,name: PHP Hacks,first: Jack,last: Herrington,publisher: OReilly, id: 3,name: Podcasting Hacks,first: Jack,last: H

49、errington,publisher: OReilly );清單 7 給出了相應(yīng)的 .html 文件。清單 7. Function1.htmlFunction 1 JS loadervar g_books = ;function AddBooks( books ) g_books = books; drawbooks( g_books );稍后將詳細介紹 drawbooks 函數(shù)。這里重要的是了解一下頁面如何定義 AddBooks 函數(shù),該函數(shù)隨后會由 function1.js 文件中的腳本調(diào)用。該 AddBooks 函數(shù)負責處理數(shù)據(jù)。而且被調(diào)用的 AddBooks 函數(shù)會向頁面指示 標記被

50、正確加載,并已加載完成。要創(chuàng)建 function1.js 文件,我只對樣式表稍微做了一點修改,如 清單 8 所示。清單 8. function1.xsl 樣式表AddBooks( 1, id: ,name: ,first: ,last: ,publisher: );這里,我調(diào)用了一個函數(shù),而不是簡單地設(shè)置一個變量。這就是我所做的惟一更改?;氐巾撁妫沂褂昧?drawbooks 函數(shù)來構(gòu)建書的表格,這樣我就能夠確認數(shù)據(jù)被正確編碼和正確顯示。此函數(shù)是在 drawbooks.js 內(nèi)定義的,如 清單 9 所示。清單 9. Drawbooks.jsfunction drawbooks( books )

51、 var elTable = document.createElement( table ); for( var b in books ) var elTR = elTable.insertRow( -1 ); var elTD1 = elTR.insertCell( -1 ); elTD1.appendChild( document.createTextNode( booksb.id ) ); var elTD2 = elTR.insertCell( -1 ); elTD2.appendChild( document.createTextNode( ) ); var

52、elTD3 = elTR.insertCell( -1 ); elTD3.appendChild( document.createTextNode( booksb.first ) ); var elTD4 = elTR.insertCell( -1 ); elTD4.appendChild( document.createTextNode( booksb.last ) ); var elTD5 = elTR.insertCell( -1 ); elTD5.appendChild( document.createTextNode( booksb.publisher ) ); document.b

53、ody.appendChild( elTable );這個簡單函數(shù)創(chuàng)建了一個表格節(jié)點,然后循環(huán)訪問書的列表并為每本書創(chuàng)建一行,為每個數(shù)據(jù)元素分配一個單元格。此頁面上的代碼的結(jié)果如 圖 2 所示。圖 2. function1.html 的結(jié)果現(xiàn)在我就可以查看一下此頁面的輸出并確認來自原始 .xml 文件的一切均已被正確轉(zhuǎn)換成 JavaScript 代碼,且數(shù)據(jù)被發(fā)送到 AddData 函數(shù)并被正確添加到頁面。細化函數(shù)調(diào)用技術(shù)我很喜歡函數(shù)調(diào)用這一技術(shù),但我并不贊同將所有圖書數(shù)據(jù)都放入一個塊中。另一種方式是為每條記錄采用一個調(diào)用,如 清單 10 所示。清單 10. Function2.jsAddBo

54、ok( id: 1,name: Code Generation in Action,first: Jack,last: Herrington,publisher: Manning );AddBook( id: 2,name: PHP Hacks,first: Jack,last: Herrington,publisher: OReilly );.對 .html 頁面只需做少許修改,如 清單 11 所示。清單 11. Function2.html.var g_books = ;function AddBook( book ) g_books.push( book ); .這里更改了 XSLT,以

55、使函數(shù)調(diào)用駐留在 for-each 循環(huán)體內(nèi)。清單 12 顯示了更新后的樣式表。清單 12. function2.xsl.AddBook( id: ,name: ,first: ,last: ,publisher: );.對這個給定示例來說,這種更改看起來有些隨意。但如果原始的 XML 數(shù)據(jù)集有多種數(shù)據(jù)類型,要為每種類型分配一個單獨的函數(shù)調(diào)用會使 XSL 和頁面上的 JavaScript 代碼更為簡單、更易于維護。編碼對象對小的頁面來講,使用 JavaScript 函數(shù)沒有問題。但對于大型項目,就需要使用 JavaScript 語言的一些面向?qū)ο筇匦浴J堑?,JavaScript 語言可以處理對象而且可以處理得很好。清單 13 顯示了如何創(chuàng)建帶有數(shù)據(jù)的對象。清單 13. Object1.jsg_books.push( new Book( id: 1,name: Code Generation in Action,fir

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論