使用jQuery構建未來Web應用程序
jQuery正在成為Web開發人員***的JavaScript庫,與此同時,人們對富Internet應用程序(Rich Internet Application,RIA)的需求也在不斷的增長,隨著RIA的增多和功能的日益復雜,JavaScript庫將會變得越來越重要,那么jQuery無疑是將您的***選擇。
51CTO推薦專題: jQuery從入門到精通
示例應用程序在這個Web郵件應用程序的額外小部件中包含了各種東西,展示了如何創建一個客戶端的富應用程序,并且根據與頁面的交互來更改對象的顏色、大小和位置。通過本文,您將能夠掌握創建RIA所需的jQuery工具,并借此打動您的客戶。
事件
jQuery內的Events模塊是向Web應用程序添加交互性的***步,因為事件通常是頁面上發生的事情的觸發器。正如我在簡介中提到的,您不應該認為事件只發生在Form元素—實際上,任何元素都能觸發事件,因此應該充分利用這一點來更輕松地構建定制的小部件,以及添加一些獨特卻又不局限于特定Form元素的交互。關于jQuery的相關事件的操作,請參閱51CTO之前報導的文章:分解jQuery對相關控件的事件操作。
眾所周知,大多數事件都基于Form元素。演示這些方法***的方式就是使用它們。在開始深入研究可用的函數之前,一定要注意:Events模塊針對每個函數都遵循一種模式。每個事件函數都包含兩種形式:一個沒有任何參數,一個包含一個函數作為參數。
二者間的差異十分重要,而且這對各個函數都是一致的。沒有參數的函數將實際激發該事件。換而言之,調用click()將實際導致該按鈕被單擊。在實際單擊該按鈕,或其click()函數被調用時,將會調用click(function)。是不是很困惑?這只是文字上的描述,舉例說明之后,您就會清楚了。
- 清單1.jQueryEvent方法
- //makethe"myButton"click.Thiswillcausethebuttontoclickandanyactions
- //tiedtoitwilloccur-forexample,itcouldsubmitaform,orother
- //jQueryactionscouldbetiedtoit.
- $("#myButton").click();
- $("#myButton").click(function(){
- $("#myDiv").toggle();
- });
- $("#myButton").click(function(){
- $("#myDiv").toggle();
- }).click();
此外,您可以想像得到,一些事件是與鼠標緊密相連的。由于這些事件常被誤用,所以我將它們包括在第三節。認識到這一點后,jQuery已經用特定的函數替代了其中的一些事件。我將它們列于此,只是為了直接與底層的DOM事件相匹配,但對于所有的實際使用,***使用其他的方法。
比如,當鼠標在某個元素上按下或釋放時,就會調用mousedown(fn)和mouseup(fn)方法。然而,更多時候,卻應該調用click()方法,因為此方法也會作為事件拋出,而且它更符合預期的行為,更不容易出錯。試想一下這樣的情況:用戶在某個按鈕上按下鼠標,發現錯了,立即松開鼠標而不是釋放鼠標。
如果用戶用所定義的mouseup(fn)在另一個頁面元素之上釋放鼠標,那么應該發生什么行為呢?理想情況下,這兩個函數的使用應該限于對界面的拖放,因為這種情況下單擊不會有合適的替代。
Event模塊的***兩個方法mouseover(fn)和mouseout(fn)目前在很多Web站點上都很常見。它們常被用來顯示懸浮幫助、圖片顯示所需的相框和基于鼠標指針所在位置而發生的顏色改變。JQuery認識到這兩個函數還將很常用,但很多人都不能正確使用它們,這就導致很多錯誤。
人們并不是有意要將bug引入其代碼,而是自己不會編寫嵌套組件或應對其他復雜情況的代碼。因此,jQuery向Event模塊添加了一個新方法來替代這兩個函數,這個方法就是hover(fn1,fn2)函數。
- 清單2.jQuery的Hover方法
- $("tr").hover(function(){
- $(this).css("background","#0000ff");
- },
- function(){
- $(this).css("background","#ffffff");
- });
#p#
屬性
頁面交互性的一個體現就是它從頁面的某個區域獲得信息并將信息傳送到其他位置的能力。這可以很具體,比如從一個文本字段獲得信息后將信息放入一個表內;也可以很寬泛,比如從一個組合框獲得信息后將信息傳給服務器,然后將服務器的響應再放入另外一個不同的組合框內。交互性的核心就是頁面信息的傳遞。
在頁面上保存信息有很多不同的方式,在頁面的某個元素內存儲信息的方法就更多樣了。您可能會想,一個簡單的<p>所包含的信息肯定沒有一個文本字段那么多(這不一定正確),因而,訪問信息也有很多不同的函數。
同樣地,您自己可能已經有了這樣的結論:如果能從頁面元素獲得信息,那么也應該可以在這些元素上放置信息。實際上,每個頁面元素都是一個數據對象,其中包含由getter/setter方法封裝的變量。JavaBean模型和jQuery的實際差異是方法名稱和某些元素不適合特定函數的限制。
在深入研究這些方法之前,讓我們先來看看什么信息能存儲到頁面元素內。簡單一些的,像a<p>,可能只包含CLASS或ID信息。而像<img>則可能包含更多信息,比如“src”、“alt”、“width”和“height”。而復雜一些的,像<inputtype="password">則可能包含“defaultValue”、“maxLength”、“readOnly”或“accessKey”等信息。這種潛在變量的多樣性促使jQuery創建了一種廣義函數來訪問它們。這個函數是attr(name),可用來訪問來自任何頁面元素的信息。我們將通過幾個示例來了解其工作原理。
- 清單3.jQueryattr()函數
- <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"
- });
在試圖向頁面添加交互性時,此函數十分有用。實際上,在添加data()函數(如下所示)之前,通常都必須將所需信息壓縮到一個可用變量內。例如,假設有一個頁面具有兩個框架,***個框架顯示選項卡,底部框架顯示每個選項卡的內容,那么可以這樣設置:
- 清單4.應用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");
- });
除了獲得每個元素上的屬性值外,還可以設置這些值。其效果與以編程方式更改元素外觀或行為相同。
- 清單5.利用attr(str)更改屬性
- //willchangetheimagesource,andtheimagedisplayedonthepagewillchange
- $("img").attr("src","myimage.jpg");
- //willchangeallthelinksonthepagetogotoonespecificpage
- $("a").attr("href","mypage.html");
- //willchangethemaxLengthonallpasswordfieldsto10characters
- $(":password").attr("maxLength","10");
頁面上的Form元素具有一個特殊的函數,該函數可以針對這些元素調用以獲得附加到元素的值。在處理表單和驗證時,這一點尤其便利,而且在用Form元素創建交互Web站點時更有可能會用到這些函數。
- 清單6.Form元素的val()函數
- //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");
還有其他一些函數,可用來獲得包含在某些標記之內的信息。那么這有什么用途呢?比如說,您可以獲得包含在某個<td>標記內的所有信息并進行替換,或者您也可以將所有<p>內的文本變成小寫的。獲得這些信息的方式有兩種,但不能為此使用attr()函數。
#p#
與所有其他的屬性函數類似,這些函數也有相應的setter方法。***個是html()函數,它能返回某個標記的所有innerHTML。另一個是text(),它能返回某個標記內的所有文本。那么二者有何區別呢?html()函數能返回包括HTML標記在內的文本,而text()則會分離二者,只返回內含的文本。以下示例展示了它們的不同之處。
- 清單7.html()與text()的對比
- //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()函數。它源自jQueryUI項目并且已納入jQuery的整體項目之中。起初,UI項目開發人員只是覺得他們不想破壞某些頁面元素的可用屬性,于是就想到要找到一種方法,用來根據自己的需要創建能存儲信息的屬性。
回顧上文提到過的選項卡的例子。我其實“破壞”了此DIV的ID內的鏈接,而這顯然不是最理想的方法。但是,受jQuery以前版本的限制,這在當時是惟一的選擇。有了data()函數之后,這個問題就有了更好的解決方案。不妨將data()函數視為用來訪問包含在每個頁面元素的內部Map的一種方式。
一個Map實際上就是鍵-值對的集合。這就讓開發人員可以創建他們想要給頁面元素提供的任何定制屬性,并能給該屬性附加任意值。最終的結果就是代碼的編寫更簡單,而且當項目規模不斷增大時,代碼的維護也更容易。接下來,讓我們用新的data()函數重寫上文提到的示例:
- 清單8.新的data()函數
- //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處理
本文***的這個部分將要介紹如何在不調整樣式表或重載此頁面的情況下動態地處理頁面的CSS。我們將能夠通過簡單更改顏色、字體等向頁面添加一些基本效果。jQuery的CSS實際上是整個庫最初的創意來源。其目標是讓頁面上的CSS編程更容易。
正如您所見,此項目隨后得到了充分的發展。但是項目的初衷并沒有改變,jQuery的確簡化了CSS編程。不過,我還是先要說明一點,即jQuery為處理CSS所提供的那些傳統函數實際上已經不能適應當今的Web環境。然后,我會介紹可以使用的其他函數(也是jQuery內的)。
有兩個基本函數可用來處理頁面上的CSS。可以先以字符串傳遞單個屬性,然后再以字符串傳遞單個值,也可以用字符串/字符串數組的形式一次傳遞。這兩個函數的功能基本相同,并且可以很容易地更改頁面的CSS。
- 清單9.css()函數
- //changethebackgroundofeverydivtored
- $("div").css("backgroundColor","#ff0000");
- //-or-
- $("div").css("backgroundColor","red");
- //-or-
- $("div").css({backgroundColor:"#ff0000"});//noticethebracesandlackofquotes
可以看出這些函數非常簡單直觀,很容易理解和掌握。不過,考慮到目前Web頁面設計的潮流,這些函數還存在一些問題。常規的Web頁面都是從頁面刪除樣式,然后在樣式表中填入一個外部文件或代碼片段。如果能采用其他辦法,您肯定不希望將樣式代碼放入JavaScript代碼中。否則,將來更改站點的外觀將十分困難。
幸運的是,現在已經有了替代函數,它既能提供所需的代碼分離,又能讓CSS處理簡單直觀。這些函數允許從頁面元素添加和刪除類。通過將這些類的樣式放入外部樣式表,就能分離樣式、數據和事件,這種分離對于復雜的頁面至關重要。請看以下這些示例:
- 清單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");
- }
- });
如這個示例所示,通過引用在外部樣式表內定義的類來調整CSS是一種更可取的處理CSS的方法。它讓Web站點創建者通過更改樣式表就能改變整個站點錯誤消息的處理方式,而不再像采用css()方法時那樣,必須追究代碼的每個實例。雖然這些方法直觀易用,但是不太適合大型Web應用程序,應該避免采用addClass()和removeClass()方法。
#p#
綜合學到的知識
要綜合使用以上知識,讓我們再來看看這個示例應用程序。它是一個具有交互性的Web應用程序,試圖創建一個RIA并給用戶這樣的感覺:他們處理電子郵件所用的這個Web應用程序非常類似于桌面應用程序。在本例中,將利用Event、Attribute和CSS模塊來定義Web郵件應用程序將如何處理鼠標單擊和雙擊。
以下所示的屏幕截圖顯示了真實的效果。當用戶在表的一個行上單擊時,此行將會改變顏色以突出顯示用戶的當前選擇。當用戶在消息上雙擊時,用戶就能看到消息,但如果用戶讀的是條新消息,此行的背景顏色會改變以表明此消息不再是未讀消息。
- 清單11.綜合學到的知識
- //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
- });
- });
- });
結束語
隨著應用程序不斷從桌面向瀏覽器轉移,像jQuery這樣的JavaScript庫的將越來越重要。應用程序會越來越復雜,這就使跨瀏覽器的jQuery成為所有Web應用項目的必要工具。由于易于使用和功能完備,jQuery逐漸從其他JavaScript庫中脫穎而出,成為很多開發人員的***選擇。
文章隨后討論了屬性以及如何恰當地從頁面元素獲得屬性,如何在頁面元素上設置屬性。您看到了通用的attr()函數可用于每個元素,并且Form元素有獲得其值的特殊函數。您還看到了新添加到jQuery的data()函數,此函數可充當每個頁面元素的HashMap,讓程序員可以創建所需的任何屬性。
***,您了解到如何修改頁面元素的CSS,而不需重新加載頁面。您還體驗了css()函數的簡單和直觀。但是為了分離頁面的樣式和jQuery代碼,您和您的團隊***選擇用addClass()和removeClass()函數替代前面那些函數。
本文的***的一部分將您所學到的這三個模塊綜合起來,展示了示例郵件應用程序如何處理鼠標交互。通過突出顯示單擊的行以及在適當的時候對消息進行“未讀”標記,可以區分鼠標單擊和雙擊,然后為特定于消息的數據向服務器發送一個Ajax調用,將消息編號傳遞給服務器。
【編輯推薦】
- 使用jQuery和PHP構建一個受Ajax驅動的Web頁面
- 一些應該熟記于心的jQuery函數和技巧
- 5種方法教你用jQuery重寫表單驗證
- 你應該學習jQuery的七大理由
- 了解jQuery技巧來提高你的代碼質量