使用jQuery構(gòu)建未來Web應(yīng)用程序
jQuery正在成為Web開發(fā)人員***的JavaScript庫,與此同時(shí),人們對(duì)富Internet應(yīng)用程序(Rich Internet Application,RIA)的需求也在不斷的增長,隨著RIA的增多和功能的日益復(fù)雜,JavaScript庫將會(huì)變得越來越重要,那么jQuery無疑是將您的***選擇。
51CTO推薦專題: jQuery從入門到精通
示例應(yīng)用程序在這個(gè)Web郵件應(yīng)用程序的額外小部件中包含了各種東西,展示了如何創(chuàng)建一個(gè)客戶端的富應(yīng)用程序,并且根據(jù)與頁面的交互來更改對(duì)象的顏色、大小和位置。通過本文,您將能夠掌握創(chuàng)建RIA所需的jQuery工具,并借此打動(dòng)您的客戶。
事件
jQuery內(nèi)的Events模塊是向Web應(yīng)用程序添加交互性的***步,因?yàn)槭录ǔJ琼撁嫔习l(fā)生的事情的觸發(fā)器。正如我在簡介中提到的,您不應(yīng)該認(rèn)為事件只發(fā)生在Form元素—實(shí)際上,任何元素都能觸發(fā)事件,因此應(yīng)該充分利用這一點(diǎn)來更輕松地構(gòu)建定制的小部件,以及添加一些獨(dú)特卻又不局限于特定Form元素的交互。關(guān)于jQuery的相關(guān)事件的操作,請(qǐng)參閱51CTO之前報(bào)導(dǎo)的文章:分解jQuery對(duì)相關(guān)控件的事件操作。
眾所周知,大多數(shù)事件都基于Form元素。演示這些方法***的方式就是使用它們。在開始深入研究可用的函數(shù)之前,一定要注意:Events模塊針對(duì)每個(gè)函數(shù)都遵循一種模式。每個(gè)事件函數(shù)都包含兩種形式:一個(gè)沒有任何參數(shù),一個(gè)包含一個(gè)函數(shù)作為參數(shù)。
二者間的差異十分重要,而且這對(duì)各個(gè)函數(shù)都是一致的。沒有參數(shù)的函數(shù)將實(shí)際激發(fā)該事件。換而言之,調(diào)用click()將實(shí)際導(dǎo)致該按鈕被單擊。在實(shí)際單擊該按鈕,或其click()函數(shù)被調(diào)用時(shí),將會(huì)調(diào)用click(function)。是不是很困惑?這只是文字上的描述,舉例說明之后,您就會(huì)清楚了。
- 清單1.jQueryEvent方法
- //makethe"myButton"click.Thiswillcausethebuttontoclickandanyactions
- //tiedtoitwilloccur-forexample,itcouldsubmitaform,orother
- //jQueryactionscouldbetiedtoit.
- $("#myButton").click();
- $("#myButton").click(function(){
- $("#myDiv").toggle();
- });
- $("#myButton").click(function(){
- $("#myDiv").toggle();
- }).click();
此外,您可以想像得到,一些事件是與鼠標(biāo)緊密相連的。由于這些事件常被誤用,所以我將它們包括在第三節(jié)。認(rèn)識(shí)到這一點(diǎn)后,jQuery已經(jīng)用特定的函數(shù)替代了其中的一些事件。我將它們列于此,只是為了直接與底層的DOM事件相匹配,但對(duì)于所有的實(shí)際使用,***使用其他的方法。
比如,當(dāng)鼠標(biāo)在某個(gè)元素上按下或釋放時(shí),就會(huì)調(diào)用mousedown(fn)和mouseup(fn)方法。然而,更多時(shí)候,卻應(yīng)該調(diào)用click()方法,因?yàn)榇朔椒ㄒ矔?huì)作為事件拋出,而且它更符合預(yù)期的行為,更不容易出錯(cuò)。試想一下這樣的情況:用戶在某個(gè)按鈕上按下鼠標(biāo),發(fā)現(xiàn)錯(cuò)了,立即松開鼠標(biāo)而不是釋放鼠標(biāo)。
如果用戶用所定義的mouseup(fn)在另一個(gè)頁面元素之上釋放鼠標(biāo),那么應(yīng)該發(fā)生什么行為呢?理想情況下,這兩個(gè)函數(shù)的使用應(yīng)該限于對(duì)界面的拖放,因?yàn)檫@種情況下單擊不會(huì)有合適的替代。
Event模塊的***兩個(gè)方法mouseover(fn)和mouseout(fn)目前在很多Web站點(diǎn)上都很常見。它們常被用來顯示懸浮幫助、圖片顯示所需的相框和基于鼠標(biāo)指針?biāo)谖恢枚l(fā)生的顏色改變。JQuery認(rèn)識(shí)到這兩個(gè)函數(shù)還將很常用,但很多人都不能正確使用它們,這就導(dǎo)致很多錯(cuò)誤。
人們并不是有意要將bug引入其代碼,而是自己不會(huì)編寫嵌套組件或應(yīng)對(duì)其他復(fù)雜情況的代碼。因此,jQuery向Event模塊添加了一個(gè)新方法來替代這兩個(gè)函數(shù),這個(gè)方法就是hover(fn1,fn2)函數(shù)。
- 清單2.jQuery的Hover方法
- $("tr").hover(function(){
- $(this).css("background","#0000ff");
- },
- function(){
- $(this).css("background","#ffffff");
- });
#p#
屬性
頁面交互性的一個(gè)體現(xiàn)就是它從頁面的某個(gè)區(qū)域獲得信息并將信息傳送到其他位置的能力。這可以很具體,比如從一個(gè)文本字段獲得信息后將信息放入一個(gè)表內(nèi);也可以很寬泛,比如從一個(gè)組合框獲得信息后將信息傳給服務(wù)器,然后將服務(wù)器的響應(yīng)再放入另外一個(gè)不同的組合框內(nèi)。交互性的核心就是頁面信息的傳遞。
在頁面上保存信息有很多不同的方式,在頁面的某個(gè)元素內(nèi)存儲(chǔ)信息的方法就更多樣了。您可能會(huì)想,一個(gè)簡單的<p>所包含的信息肯定沒有一個(gè)文本字段那么多(這不一定正確),因而,訪問信息也有很多不同的函數(shù)。
同樣地,您自己可能已經(jīng)有了這樣的結(jié)論:如果能從頁面元素獲得信息,那么也應(yīng)該可以在這些元素上放置信息。實(shí)際上,每個(gè)頁面元素都是一個(gè)數(shù)據(jù)對(duì)象,其中包含由getter/setter方法封裝的變量。JavaBean模型和jQuery的實(shí)際差異是方法名稱和某些元素不適合特定函數(shù)的限制。
在深入研究這些方法之前,讓我們先來看看什么信息能存儲(chǔ)到頁面元素內(nèi)。簡單一些的,像a<p>,可能只包含CLASS或ID信息。而像<img>則可能包含更多信息,比如“src”、“alt”、“width”和“height”。而復(fù)雜一些的,像<inputtype="password">則可能包含“defaultValue”、“maxLength”、“readOnly”或“accessKey”等信息。這種潛在變量的多樣性促使jQuery創(chuàng)建了一種廣義函數(shù)來訪問它們。這個(gè)函數(shù)是attr(name),可用來訪問來自任何頁面元素的信息。我們將通過幾個(gè)示例來了解其工作原理。
- 清單3.jQueryattr()函數(shù)
- <imgsrcimgsrc="/images/space.gif"id="spacer"class="abc"alt="blank">
- //Callstotheattr()functionwillreturnthefollowing
- $("#spacer").attr("src");//willreturn"/images/space.gif"
- $("#spacer").attr("alt");//willreturn"blank"
- //Similarly,youcanaccesstheIDinthesameway
- $(img).each(function(){
- $(this).attr("id");//willreturn"spacer"
- });
在試圖向頁面添加交互性時(shí),此函數(shù)十分有用。實(shí)際上,在添加data()函數(shù)(如下所示)之前,通常都必須將所需信息壓縮到一個(gè)可用變量內(nèi)。例如,假設(shè)有一個(gè)頁面具有兩個(gè)框架,***個(gè)框架顯示選項(xiàng)卡,底部框架顯示每個(gè)選項(xiàng)卡的內(nèi)容,那么可以這樣設(shè)置:
- 清單4.應(yīng)用attr()
- <!--Thiswouldappearinthetopframeasatab.TheCSSfilewouldcontrolhow
- thetabappears,andtheonlyHTMLcodeneededwouldbethis-->
- <td>
- <divclassdivclass="tab"id="/messages.jsp">Messages</div>
- </td>
- $(".tab").click(function(){
- window.parent.frames['content'].location=$(this).attr("id");
- });
除了獲得每個(gè)元素上的屬性值外,還可以設(shè)置這些值。其效果與以編程方式更改元素外觀或行為相同。
- 清單5.利用attr(str)更改屬性
- //willchangetheimagesource,andtheimagedisplayedonthepagewillchange
- $("img").attr("src","myimage.jpg");
- //willchangeallthelinksonthepagetogotoonespecificpage
- $("a").attr("href","mypage.html");
- //willchangethemaxLengthonallpasswordfieldsto10characters
- $(":password").attr("maxLength","10");
頁面上的Form元素具有一個(gè)特殊的函數(shù),該函數(shù)可以針對(duì)這些元素調(diào)用以獲得附加到元素的值。在處理表單和驗(yàn)證時(shí),這一點(diǎn)尤其便利,而且在用Form元素創(chuàng)建交互Web站點(diǎn)時(shí)更有可能會(huì)用到這些函數(shù)。
- 清單6.Form元素的val()函數(shù)
- //willgetthetextcontainedinthetextfieldandcheckthatit'snotblank
- $(":textfield").each(function(){
- //usetheval()functiontogetthetextinsidethetextfield
- if($(this).val()=="")
- $(this).next().text("Error");
- });
- //onanewpasswordpage,thiswillcomparethenewonewiththeconfirmation,
- //tomakesuretheyareequal
- if($("#newPassword").val()!=$("#confirmPass").val())
- $("#newPassword").next().text("Error");
還有其他一些函數(shù),可用來獲得包含在某些標(biāo)記之內(nèi)的信息。那么這有什么用途呢?比如說,您可以獲得包含在某個(gè)<td>標(biāo)記內(nèi)的所有信息并進(jìn)行替換,或者您也可以將所有<p>內(nèi)的文本變成小寫的。獲得這些信息的方式有兩種,但不能為此使用attr()函數(shù)。
#p#
與所有其他的屬性函數(shù)類似,這些函數(shù)也有相應(yīng)的setter方法。***個(gè)是html()函數(shù),它能返回某個(gè)標(biāo)記的所有innerHTML。另一個(gè)是text(),它能返回某個(gè)標(biāo)記內(nèi)的所有文本。那么二者有何區(qū)別呢?html()函數(shù)能返回包括HTML標(biāo)記在內(nèi)的文本,而text()則會(huì)分離二者,只返回內(nèi)含的文本。以下示例展示了它們的不同之處。
- 清單7.html()與text()的對(duì)比
- //thiswillexamineevery<td>tag,andifthevalueisblank,itwillinsert
- //a"-"intoit,asaplaceholder.
- $("td").each(function(){
- //checkthetextofthetablecell
- if($(this).text()=="")
- $(this).text("-");
- });
- //thiswillconverteveryparagraph'stexttolowercase
- $("p").each(function(){
- varoldText=$(this).text();
- varnewText=oldText.toLowerCase();
- $(this).text(newText);
- });
- <--Thisshowsthedifferencebetweentext()andhtml()-->
- <dividdivid="sample"><b>Thisistheexample</b></div>
- $("#sample").html();//willreturn"<b>Thisistheexample</b>"
- $("#sample").text();//willreturn"Thisisanexample"
此外,最近還向jQuery庫添加了用于屬性的data()函數(shù)。它源自jQueryUI項(xiàng)目并且已納入jQuery的整體項(xiàng)目之中。起初,UI項(xiàng)目開發(fā)人員只是覺得他們不想破壞某些頁面元素的可用屬性,于是就想到要找到一種方法,用來根據(jù)自己的需要?jiǎng)?chuàng)建能存儲(chǔ)信息的屬性。
回顧上文提到過的選項(xiàng)卡的例子。我其實(shí)“破壞”了此DIV的ID內(nèi)的鏈接,而這顯然不是最理想的方法。但是,受jQuery以前版本的限制,這在當(dāng)時(shí)是惟一的選擇。有了data()函數(shù)之后,這個(gè)問題就有了更好的解決方案。不妨將data()函數(shù)視為用來訪問包含在每個(gè)頁面元素的內(nèi)部Map的一種方式。
一個(gè)Map實(shí)際上就是鍵-值對(duì)的集合。這就讓開發(fā)人員可以創(chuàng)建他們想要給頁面元素提供的任何定制屬性,并能給該屬性附加任意值。最終的結(jié)果就是代碼的編寫更簡單,而且當(dāng)項(xiàng)目規(guī)模不斷增大時(shí),代碼的維護(hù)也更容易。接下來,讓我們用新的data()函數(shù)重寫上文提到的示例:
- 清單8.新的data()函數(shù)
- //createthedivlikewedidabove,butwithoutanyspecificinformation.Inthis
- //waywecancreateagenericHTMLlayoutandcustomizeitinourjQuerycode.
- <td>
- <divclassdivclass="tab"></div>
- </td>
- //NowcustomizeeachtabinthejQuerycode.
- $(".tab").eq(0).text("Messages");
- $(".tab").eq(0).data("link","messages.jsp");
- $(".tab").click(function(){
- window.parent.frames['content'].location=$(this).data("link");
- });
- //Takingthisastepfurther,youcanpictureallthisinformationcomingfrom
- //anexternalpropertiesfileviaaJavaarray.ThiswouldbethecodeonaJSP
- //page.
- <%
- //arraycontainingtabnames
- String[]tabNames;
- //arraycontainingtablinks
- String[]links;
- for(inti=0;i<tabNames.length;i++){
- %>
- $(".tab").eq(<%=i%>).text("<%=tabNames[i]%>");
- $(".tab").eq(<%=i%>).data("link","<%=links[i]%>");
- <%}%>
- $(".tab").click(function(){
- window.parent.frames['content'].location=$(this).data("link");
- });
CSS處理
本文***的這個(gè)部分將要介紹如何在不調(diào)整樣式表或重載此頁面的情況下動(dòng)態(tài)地處理頁面的CSS。我們將能夠通過簡單更改顏色、字體等向頁面添加一些基本效果。jQuery的CSS實(shí)際上是整個(gè)庫最初的創(chuàng)意來源。其目標(biāo)是讓頁面上的CSS編程更容易。
正如您所見,此項(xiàng)目隨后得到了充分的發(fā)展。但是項(xiàng)目的初衷并沒有改變,jQuery的確簡化了CSS編程。不過,我還是先要說明一點(diǎn),即jQuery為處理CSS所提供的那些傳統(tǒng)函數(shù)實(shí)際上已經(jīng)不能適應(yīng)當(dāng)今的Web環(huán)境。然后,我會(huì)介紹可以使用的其他函數(shù)(也是jQuery內(nèi)的)。
有兩個(gè)基本函數(shù)可用來處理頁面上的CSS。可以先以字符串傳遞單個(gè)屬性,然后再以字符串傳遞單個(gè)值,也可以用字符串/字符串?dāng)?shù)組的形式一次傳遞。這兩個(gè)函數(shù)的功能基本相同,并且可以很容易地更改頁面的CSS。
- 清單9.css()函數(shù)
- //changethebackgroundofeverydivtored
- $("div").css("backgroundColor","#ff0000");
- //-or-
- $("div").css("backgroundColor","red");
- //-or-
- $("div").css({backgroundColor:"#ff0000"});//noticethebracesandlackofquotes
可以看出這些函數(shù)非常簡單直觀,很容易理解和掌握。不過,考慮到目前Web頁面設(shè)計(jì)的潮流,這些函數(shù)還存在一些問題。常規(guī)的Web頁面都是從頁面刪除樣式,然后在樣式表中填入一個(gè)外部文件或代碼片段。如果能采用其他辦法,您肯定不希望將樣式代碼放入JavaScript代碼中。否則,將來更改站點(diǎn)的外觀將十分困難。
幸運(yùn)的是,現(xiàn)在已經(jīng)有了替代函數(shù),它既能提供所需的代碼分離,又能讓CSS處理簡單直觀。這些函數(shù)允許從頁面元素添加和刪除類。通過將這些類的樣式放入外部樣式表,就能分離樣式、數(shù)據(jù)和事件,這種分離對(duì)于復(fù)雜的頁面至關(guān)重要。請(qǐng)看以下這些示例:
- 清單10.更佳的CSS處理-addClass()和removeClass()
- $(":textfield").each(function(){
- if($(this).val()=="")
- {
- $(this).next().text("Error");
- //thiswillturnthetextfield'sborder/textred
- $(this).addClass("input_error");
- }
- //thistestsifthetextfieldhastheclassattachedalready
- elseif($(this).hasClass("input_error"))
- {
- $(this).next().text("");
- //thiswillremovetheclass,restoringanormalborder/text
- $(this).removeClass("input_error");
- }
- });
如這個(gè)示例所示,通過引用在外部樣式表內(nèi)定義的類來調(diào)整CSS是一種更可取的處理CSS的方法。它讓W(xué)eb站點(diǎn)創(chuàng)建者通過更改樣式表就能改變整個(gè)站點(diǎn)錯(cuò)誤消息的處理方式,而不再像采用css()方法時(shí)那樣,必須追究代碼的每個(gè)實(shí)例。雖然這些方法直觀易用,但是不太適合大型Web應(yīng)用程序,應(yīng)該避免采用addClass()和removeClass()方法。
#p#
綜合學(xué)到的知識(shí)
要綜合使用以上知識(shí),讓我們?cè)賮砜纯催@個(gè)示例應(yīng)用程序。它是一個(gè)具有交互性的Web應(yīng)用程序,試圖創(chuàng)建一個(gè)RIA并給用戶這樣的感覺:他們處理電子郵件所用的這個(gè)Web應(yīng)用程序非常類似于桌面應(yīng)用程序。在本例中,將利用Event、Attribute和CSS模塊來定義Web郵件應(yīng)用程序?qū)⑷绾翁幚硎髽?biāo)單擊和雙擊。
以下所示的屏幕截圖顯示了真實(shí)的效果。當(dāng)用戶在表的一個(gè)行上單擊時(shí),此行將會(huì)改變顏色以突出顯示用戶的當(dāng)前選擇。當(dāng)用戶在消息上雙擊時(shí),用戶就能看到消息,但如果用戶讀的是條新消息,此行的背景顏色會(huì)改變以表明此消息不再是未讀消息。
- 清單11.綜合學(xué)到的知識(shí)
- //Firstweaddtherowstothetable.Eachrowisamemberofthe"messageRow"class.
- //WealsogiveanIDtoeachrow,andthisIDisthemessagenumberitself,whichis
- //gottenfromtheJavadataobject.KeepinmindthissitsinaforloopinaJSPfile.
- <%
- for(inti=0;i<messages.size();i++)
- {
- MessageDatamessage=messages.get(i);
- %>
- <trclasstrclass="messageRow"id="<%=message.id%>">
- $(".messageRow").click(function(){
- $(".messageRow").removeClass("message_selected");
- $(this).addClass("message_selected");
- });
- $(".messageRow").dblclick(function(){
- if($(this).hasClass("mail_unread"))
- {
- $(this).removeClass("mail_unread");
- }
- $.post("<%=HtmlServlet.READ_MESSAGE%>.do",
- {
- messageId:$(this).attr("id"),
- view:"<%=view%>"},
- function(data){
- //DoAJAXstuffhere
- });
- });
- });
結(jié)束語
隨著應(yīng)用程序不斷從桌面向?yàn)g覽器轉(zhuǎn)移,像jQuery這樣的JavaScript庫的將越來越重要。應(yīng)用程序會(huì)越來越復(fù)雜,這就使跨瀏覽器的jQuery成為所有Web應(yīng)用項(xiàng)目的必要工具。由于易于使用和功能完備,jQuery逐漸從其他JavaScript庫中脫穎而出,成為很多開發(fā)人員的***選擇。
文章隨后討論了屬性以及如何恰當(dāng)?shù)貜捻撁嬖孬@得屬性,如何在頁面元素上設(shè)置屬性。您看到了通用的attr()函數(shù)可用于每個(gè)元素,并且Form元素有獲得其值的特殊函數(shù)。您還看到了新添加到j(luò)Query的data()函數(shù),此函數(shù)可充當(dāng)每個(gè)頁面元素的HashMap,讓程序員可以創(chuàng)建所需的任何屬性。
***,您了解到如何修改頁面元素的CSS,而不需重新加載頁面。您還體驗(yàn)了css()函數(shù)的簡單和直觀。但是為了分離頁面的樣式和jQuery代碼,您和您的團(tuán)隊(duì)***選擇用addClass()和removeClass()函數(shù)替代前面那些函數(shù)。
本文的***的一部分將您所學(xué)到的這三個(gè)模塊綜合起來,展示了示例郵件應(yīng)用程序如何處理鼠標(biāo)交互。通過突出顯示單擊的行以及在適當(dāng)?shù)臅r(shí)候?qū)ο⑦M(jìn)行“未讀”標(biāo)記,可以區(qū)分鼠標(biāo)單擊和雙擊,然后為特定于消息的數(shù)據(jù)向服務(wù)器發(fā)送一個(gè)Ajax調(diào)用,將消息編號(hào)傳遞給服務(wù)器。
【編輯推薦】
- 使用jQuery和PHP構(gòu)建一個(gè)受Ajax驅(qū)動(dòng)的Web頁面
- 一些應(yīng)該熟記于心的jQuery函數(shù)和技巧
- 5種方法教你用jQuery重寫表單驗(yàn)證
- 你應(yīng)該學(xué)習(xí)jQuery的七大理由
- 了解jQuery技巧來提高你的代碼質(zhì)量