自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

使用jQuery構(gòu)建未來Web應(yīng)用程序

開發(fā) 開發(fā)工具
在本篇本章,通過更精彩的功能來進(jìn)一步擴(kuò)展您的jQuery知識(shí),并向老的Internet應(yīng)用程序添加一些真正的“富”特性,使這個(gè)演示應(yīng)用程序成為富Internet應(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. 清單1.jQueryEvent方法  
  2. //makethe"myButton"click.Thiswillcausethebuttontoclickandanyactions  
  3. //tiedtoitwilloccur-forexample,itcouldsubmitaform,orother  
  4. //jQueryactionscouldbetiedtoit.  
  5. $("#myButton").click();  
  6.  
  7. $("#myButton").click(function(){  
  8. $("#myDiv").toggle();  
  9. });  
  10.  
  11. $("#myButton").click(function(){  
  12. $("#myDiv").toggle();  
  13. }).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ù)。

  1. 清單2.jQuery的Hover方法  
  2. $("tr").hover(function(){  
  3. $(this).css("background","#0000ff");  
  4. },  
  5. function(){  
  6. $(this).css("background","#ffffff");  
  7. }); 

#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è)示例來了解其工作原理。

  1. 清單3.jQueryattr()函數(shù)  
  2. <imgsrcimgsrc="/images/space.gif"id="spacer"class="abc"alt="blank"> 
  3. //Callstotheattr()functionwillreturnthefollowing  
  4. $("#spacer").attr("src");//willreturn"/images/space.gif"  
  5. $("#spacer").attr("alt");//willreturn"blank"  
  6. //Similarly,youcanaccesstheIDinthesameway  
  7. $(img).each(function(){  
  8. $(this).attr("id");//willreturn"spacer"  
  9. }); 

在試圖向頁面添加交互性時(shí),此函數(shù)十分有用。實(shí)際上,在添加data()函數(shù)(如下所示)之前,通常都必須將所需信息壓縮到一個(gè)可用變量內(nèi)。例如,假設(shè)有一個(gè)頁面具有兩個(gè)框架,***個(gè)框架顯示選項(xiàng)卡,底部框架顯示每個(gè)選項(xiàng)卡的內(nèi)容,那么可以這樣設(shè)置:

  1. 清單4.應(yīng)用attr()  
  2. <!--Thiswouldappearinthetopframeasatab.TheCSSfilewouldcontrolhow  
  3. thetabappears,andtheonlyHTMLcodeneededwouldbethis--> 
  4. <td> 
  5. <divclassdivclass="tab"id="/messages.jsp">Messages</div> 
  6. </td> 
  7.  
  8. $(".tab").click(function(){  
  9. window.parent.frames['content'].location=$(this).attr("id");  
  10. }); 

除了獲得每個(gè)元素上的屬性值外,還可以設(shè)置這些值。其效果與以編程方式更改元素外觀或行為相同。

  1. 清單5.利用attr(str)更改屬性  
  2. //willchangetheimagesource,andtheimagedisplayedonthepagewillchange  
  3. $("img").attr("src","myimage.jpg");  
  4.  
  5. //willchangeallthelinksonthepagetogotoonespecificpage  
  6. $("a").attr("href","mypage.html");  
  7.  
  8. //willchangethemaxLengthonallpasswordfieldsto10characters  
  9. $(":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ù)。

  1. 清單6.Form元素的val()函數(shù)  
  2. //willgetthetextcontainedinthetextfieldandcheckthatit'snotblank  
  3. $(":textfield").each(function(){  
  4. //usetheval()functiontogetthetextinsidethetextfield  
  5. if($(this).val()=="")  
  6. $(this).next().text("Error");  
  7. });  
  8.  
  9. //onanewpasswordpage,thiswillcomparethenewonewiththeconfirmation,  
  10. //tomakesuretheyareequal  
  11. if($("#newPassword").val()!=$("#confirmPass").val())  
  12. $("#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)含的文本。以下示例展示了它們的不同之處。

  1. 清單7.html()與text()的對(duì)比  
  2. //thiswillexamineevery<td>tag,andifthevalueisblank,itwillinsert  
  3. //a"-"intoit,asaplaceholder.  
  4. $("td").each(function(){  
  5. //checkthetextofthetablecell  
  6. if($(this).text()=="")  
  7. $(this).text("-");  
  8. });  
  9.  
  10. //thiswillconverteveryparagraph'stexttolowercase  
  11. $("p").each(function(){  
  12. varoldText=$(this).text();  
  13. varnewText=oldText.toLowerCase();  
  14. $(this).text(newText);  
  15. });  
  16.  
  17. <--Thisshowsthedifferencebetweentext()andhtml()--> 
  18. <dividdivid="sample"><b>Thisistheexample</b></div> 
  19.  
  20. $("#sample").html();//willreturn"<b>Thisistheexample</b>"  
  21. $("#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ù)重寫上文提到的示例:

  1. 清單8.新的data()函數(shù)  
  2. //createthedivlikewedidabove,butwithoutanyspecificinformation.Inthis  
  3. //waywecancreateagenericHTMLlayoutandcustomizeitinourjQuerycode.  
  4.  
  5. <td> 
  6. <divclassdivclass="tab"></div> 
  7. </td> 
  8.  
  9. //NowcustomizeeachtabinthejQuerycode.  
  10.  
  11. $(".tab").eq(0).text("Messages");  
  12. $(".tab").eq(0).data("link","messages.jsp");  
  13. $(".tab").click(function(){  
  14. window.parent.frames['content'].location=$(this).data("link");  
  15. });  
  16.  
  17. //Takingthisastepfurther,youcanpictureallthisinformationcomingfrom  
  18. //anexternalpropertiesfileviaaJavaarray.ThiswouldbethecodeonaJSP  
  19. //page.  
  20.  
  21. <%  
  22. //arraycontainingtabnames  
  23. String[]tabNames;  
  24. //arraycontainingtablinks  
  25. String[]links;  
  26.  
  27. for(inti=0;i<tabNames.length;i++){  
  28. %> 
  29. $(".tab").eq(<%=i%>).text("<%=tabNames[i]%>");  
  30. $(".tab").eq(<%=i%>).data("link","<%=links[i]%>");  
  31. <%}%> 
  32.  
  33. $(".tab").click(function(){  
  34. window.parent.frames['content'].location=$(this).data("link");  
  35. }); 

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。

  1. 清單9.css()函數(shù)  
  2. //changethebackgroundofeverydivtored  
  3. $("div").css("backgroundColor","#ff0000");  
  4. //-or-  
  5. $("div").css("backgroundColor","red");  
  6. //-or-  
  7. $("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)看以下這些示例:

  1. 清單10.更佳的CSS處理-addClass()和removeClass()  
  2. $(":textfield").each(function(){  
  3. if($(this).val()=="")  
  4. {  
  5. $(this).next().text("Error");  
  6. //thiswillturnthetextfield'sborder/textred  
  7. $(this).addClass("input_error");  
  8. }  
  9. //thistestsifthetextfieldhastheclassattachedalready  
  10. elseif($(this).hasClass("input_error"))  
  11. {  
  12. $(this).next().text("");  
  13. //thiswillremovetheclass,restoringanormalborder/text  
  14. $(this).removeClass("input_error");  
  15. }  
  16. }); 

如這個(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ì)改變以表明此消息不再是未讀消息。

真實(shí)的效果 

在某行上雙擊

  1. 清單11.綜合學(xué)到的知識(shí)  
  2. //Firstweaddtherowstothetable.Eachrowisamemberofthe"messageRow"class.  
  3. //WealsogiveanIDtoeachrow,andthisIDisthemessagenumberitself,whichis  
  4. //gottenfromtheJavadataobject.KeepinmindthissitsinaforloopinaJSPfile.  
  5.  
  6. <%  
  7. for(inti=0;i<messages.size();i++)  
  8. {  
  9. MessageDatamessage=messages.get(i);  
  10. %> 
  11. <trclasstrclass="messageRow"id="<%=message.id%>"> 
  12.  
  13. $(".messageRow").click(function(){  
  14. $(".messageRow").removeClass("message_selected");  
  15. $(this).addClass("message_selected");  
  16. });  
  17.  
  18. $(".messageRow").dblclick(function(){  
  19. if($(this).hasClass("mail_unread"))  
  20. {  
  21. $(this).removeClass("mail_unread");  
  22. }  
  23. $.post("<%=HtmlServlet.READ_MESSAGE%>.do",  
  24. {  
  25. messageId:$(this).attr("id"),  
  26. view:"<%=view%>"},  
  27. function(data){  
  28. //DoAJAXstuffhere  
  29. });  
  30. });  
  31. }); 

結(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ù)器。

【編輯推薦】

  1. 使用jQuery和PHP構(gòu)建一個(gè)受Ajax驅(qū)動(dòng)的Web頁面
  2. 一些應(yīng)該熟記于心的jQuery函數(shù)和技巧
  3. 5種方法教你用jQuery重寫表單驗(yàn)證
  4. 你應(yīng)該學(xué)習(xí)jQuery的七大理由
  5. 了解jQuery技巧來提高你的代碼質(zhì)量

 

責(zé)任編輯:王曉東 來源: PHPchina
相關(guān)推薦

2012-06-15 11:32:19

ibmdw

2009-09-22 12:59:07

ibmdwWeb

2009-01-03 14:25:10

ibmdwWeb

2023-06-29 07:45:03

2012-04-19 09:34:21

ibmdw

2023-09-21 08:00:00

ChatGPT編程工具

2020-03-30 10:49:36

物聯(lián)網(wǎng)應(yīng)用程序IOT

2012-03-21 09:36:33

ibmdw

2012-05-14 17:35:28

移動(dòng)Web

2014-02-19 15:38:42

2015-03-20 10:31:10

移動(dòng)Web

2023-04-25 15:50:50

Flask框架Web

2010-07-22 08:54:14

jQuery

2024-01-02 00:18:56

Buffalo項(xiàng)目Go Web框架

2009-08-27 11:40:43

ibmdw云計(jì)算

2011-01-24 07:24:48

Visual Stud

2022-10-24 16:19:45

2011-07-08 15:27:03

jQuery Mobi

2021-09-07 10:24:36

Vue應(yīng)用程序Web Workers

2010-05-20 09:48:36

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)