文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>jquery高级应用:优化web应用程序的最后绝招...

jquery高级应用:优化web应用程序的最后绝招...

时间:2010-08-13  来源:jxf19860114


原文地 址:http://developer.51cto.com/art/201007/213251.htm

    在本文中,我将讨论代码的性能改进,同时也谈及一些关于jQuery库的容 易被忽视的问题。有些东西对于复杂的应用程序而言至关重要,即对所有应用程序都非常关键的插件,以及使应用程序的编写更加容易的良好设计技巧。

jQuery让编写基于JavaScript的良好Web应用程序变得简单明了,但是要想将好的Web应用程序变得更出色还需要额 外几个步骤。本文详细阐述几个让Web应用程序变得更强大的步骤,这些步骤是优化您的Web应用程序的最后绝招。

51CTO推荐专题:jQuery从入门到精通

第一个示例应用程序

本文中的大部分技巧都可以从附带的样例应用程序中找到,这是一个直观的电子邮件Web应用程序。不过,您可以看到它是如何从第一篇文章中发展而来 的,它的性能是如何改进的,以及这些最后步骤如何将它转变成强大的Web应用程序的。

Bind/Unbind

在Events模块中有两个函数,它们是bind()和unbind(),用于完成所有其他事件方法的任务。如果您能够向页面元素添加一个 click()方法,那么哪还有必要调用bind("click")呢?这仅是浪费时间而已。但是,这些函数在特定情况下是非常方便的,如果正确地使用它 们,可以显著提高应用程序的性能。

这些函数不仅能够向特定页面元素添加事件(就像该模块中的许多其他事件方法一样),而且还可以从页面元素中删除这些事件。为什么要这样做?下面我们 看看这个Web应用程序,以及如何在特定情况下使用这些函数。

清单1显示了以上设置的代码,这是未改进之前的原始代码:

  1. $(document).ready(function(){  
  2. //cachethisquerysinceit'sasearchbyCLASS  
  3. selectable =$(":checked.selectable");  
  4. //whentheselect/deselectallisclicked,dothisfunction  
  5. $("#selectall").click(selectAll);  
  6. //wheneveranyindividualcheckboxischecked,changethetext  
  7. //describinghowmanyarechecked  
  8. selectable.click(changeNumFilters);  
  9. //calculatehowmanyareinitiallychecked  
  10. changeNumFilters();  
  11. });  
  12.  
  13. varselectable;  
  14. functionchangeNumFilters()  
  15. {  
  16. //thisneedstobecheckedoneverycall  
  17. //sincethelengthcanchangewitheveryclick  
  18. varsize =$(":checked.selectable").length;  
  19. if(size > 0)  
  20. $("#selectedCount").html(size);  
  21. else  
  22. $("#selectedCount").html("0");  
  23. }  
  24.  
  25. //handlestheselect/deselectofallcheckboxes  
  26. functionselectAll()  
  27. {  
  28. varchecked =$("#selectall").attr("checked");  
  29. selectable.each(function(){  
  30. varsubChecked =$(this).attr("checked");  
  31. if(subChecked!=checked)  
  32. {  
  33. $(this).click();  
  34. }  
  35. });  
  36. changeNumFilters();  
  37. }  

该代码看起来比较简单,因为我在好几篇文章中都用到这个小部件。您在第一篇文章中见到了“select/deselectall”小部件,我给出了 它的基础形式。在关于性能的文章中,您看到如何通过缓存选择查询和通过CLASS减少使用查询来改进它的性能。但是还有一个问题需要解决。当在包含100 行的表中勾选“select/deselectall”复选框之后,您将得到糟糕的性能。事实上,在我的浏览器中,如果使用了这些代码,那么完成选择的平 均时间为3.4秒。响应性太差了!即使进行了各项优化,仍然有些不可接受的地方。

让我们深入一步考察这个算法,看看是否有地方出了问题。您将遍历页面上的每个复选框,看看它们当前的“checked”状态是否与 “select/deselectall”复选框一致。如果不一致,就对其调用“click”,以和“select/deselectall”复选框的状 态匹配。等一等,您还需要向这些复选框添加一个函数,从而在每次单击时都调用changeNumFilters()函数。

通过仔细检查,您发现设置了一个可能调用changeNumFilters()101次的算法。怪不得性能如此差。很明显,您不需要在每次单击时都 更新选中的消息的计数,而是在该过程完成之后进行更新即可。在单击复选框的同时如何才能避免调用该方法?

现在,unbind()方法开始发挥它的作用。通过在单击复选框之前调用unbind(),将停止调用click(),同时避免了click()进 一步调用changeNumFilter()方法。这很棒!现在就不会调用changeNumFilters()101次了。但是,这仅是一次有效的,在 调用click方法之后,需要使用bind方法将click方法添加回到每个复选框。清单2显示了更新之后的小部件。

  1. //handlestheselection/unselectionofallcheckboxes  
  2. functionselectAll()  
  3. {  
  4. varchecked =$("#selectall").attr("checked");  
  5. selectable.unbind("click",changeNumFilters);  
  6. selectable.each(function(){  
  7. varsubChecked =$(this).attr("checked");  
  8. if(subChecked!=checked)  
  9. {  
  10. $(this).click();  
  11. }  
  12. });  
  13. selectable.bind("click",changeNumFilters);  
  14. changeNumFilters();  

通过这些优化之后,复选框的运行速度提高到约900毫秒,从而大大改进了性能。这些改进源于返回去检查您的算法正在做什么,以及贯穿代码的操作。您 可以仅调用函数1次,而不是100次。通过在本系列的其他文章中不断改进该函数,您最后会让它变得更快、更高效。但不一定非得这么做,我还发现一个最快的 算法,以前从来没有透露过。此外,如果我过早地向您展示这个最快的算法,我就不能将其作为本文的题材了。希望它能使您看到在代码中使用 bind/unbind特性带来的好处(如果没有更好的方法的话)。

记住:在不希望触发默认事件时才使用bind/unbind,或作为向页面元素添加或删除事件的临时方法

清单3显示了编写该算法的最快方法(如果您的代码中有这个小部件)。它运行该函数仅需40毫秒,远远胜过之前的其他方法。

  1. functionselectAll()  
  2. {  
  3. varchecked =$("#selectall").attr("checked");  
  4. selectable.each(function(){  
  5. $(this).attr("checked",checked);  
  6. });  
  7. changeNumFilters();  
  8. }
 

Live/Die

jQuery 1.3版本的另外两个强大的新特性是live()和die()函数。通过一个示例可以看到它对构建设计良好的Web应用程序的作用。想像一下对表中的每个 单元格都添加一个双击。作为jQuery老手,您应该知道要在document.ready()函数中设置双击,如清单4所示。

  1. $("tr.messageRow").dblclick(function(){  
  2. if($(this).hasClass("mail_unread"))  
  3. {  
  4. $(this).removeClass("mail_unread");  
  5. }  
  6. }); 

这个设计存在一个问题。它向包含一个messageRow类的表的每行添加一个双击事件。但是,如果向该表添加新的行,会发生什么事情呢?例如,当 您使用Ajax在未重新加载页面的情况下将额外的消息加载到页面时,可能会显示这些行。这导致一个问题,因为所编写的代码不能工作。您创建的事件被绑定到 所有在加载页面时显示的tr.messageRow元素中。

它没有绑定到您在页面的生命周期中创建的任何新的tr.messageRow中。编写类似代码的程序员最终会很失望的,因为它无法工作。在 jQuery文档发现该问题之前,jQuery新手可能要花好几个小时才能弄明白为什么他们的代码不能工作(这也是我去年的经历)。

在jQuery 1.3之前,有3种可以解决该问题的方法,但都不是很好(对于使用jQuery 1.2.x的程序员而言,它们仍然有效)。第一种方法是重新初始化技术,它在每次添加新的元素之后重新将事件添加到选中的元素中。第二种方法利用了 bind/unbind,如前面小节所示。清单5显示了这两种方法。

  1. //firsttechniquetodealwith"hot"pageelements,addedduringthepage's  
  2. //lifetime  
  3. $("#mailtabletr#"+message.id).addClass("messageRow")  
  4. .dblclick(function(){  
  5. if($(this).hasClass("mail_unread"))  
  6. {  
  7. $(this).removeClass("mail_unread");  
  8. }  
  9.  
  10. //secondtechniquetodealwith"hot"pageelements  
  11. $("#mailtabletr#"+message.id).addClass("messageRow")  
  12. .bind("dblclick",(function(){  
  13. if($(this).hasClass("mail_unread"))  
  14. {  
  15. $(this).removeClass("mail_unread");  
  16. }  

这两种方法都不是很好。您可能正在重复编写代码,或者被迫查找可能添加新页面元素的点,然后在这些点上处理“热元素”问题。这不是良好的编程方式。 但是,jQuery可能大大简化这一切,它能够帮助我们完成很多事情。

幸运的是,有一个插件好像能够解决该问题。这个插件称为LiveQuery插件,它允许您将特定页面元素绑定到事件,但仅能以“活动”的方式进行, 因此所有页面元素(包括创建页面时自带的元素和在页面的生命周期中创建的元素)都可能触发事件。对UI开发人员而言,这是一个非常智能、重要的插件,因为 使得处理动态页面就像处理静态页面一样简单。对于Web应用程序开发人员而言,它就是真正不可或缺的插件。

jQuery核心团队意识到该插件的重要性,从而将其包含到1.3发布版中。这个“活动”特性现在是核心jQuery的一部分,因此任何开发人员都 可以利用它。这个特性完整地包含在1.3核心代码中,除了一小部分事件之外。我敢打赌,这些未被包含的事件将出现在jQuery的下一个发布版之中。我们 看看如何利用它改变代码。

  1. $("tr.messageRow").live("dblclick",function(){  
  2. if($(this).hasClass("mail_unread"))  
  3. {  
  4. $(this).removeClass("mail_unread");  

通过对代码进行一处小更改,该页面上的所有tr.messageRow元素被双击时都将触发这段代码。仅使用dblclick()函数是看不到这种 行为的,如上所述。为此,我极力推荐您在大部分事件方法中使用live()方法。事实上,我认为它对于任何动态地创建页面元素的页面都是必不可少的,不管 是通过Ajax还是用户交互进行创建,都需要使用live()函数而不是事件方法。它很好的实现了易编写和bug之间的折衷。

记住:当将事件添加到动态页面元素时要使用live()方法。这让事件和页面元素一样具有动态性。

Ajax Queue/Sync

在服务器中使用Ajax调用成为Web2.0公司度量自身的度量指标。我们已经多次讨论过,在jQuery中使用Ajax就像调用普通的方法一样简 单。这意味着您可以轻松地调用任何服务器端Ajax函数,就像调用客户端的JavaScript函数一样。但是美中存在一些不足之处,当对服务器进行过多 的Ajax调用时,就会出现一些负面效应。如果Web应用程序使用的Ajax调用过多,就会导致问题。

第一个问题是一些浏览器限制打开的服务器连接的数量。在Internet Explorer中,当前版本仅支持打开2个服务器连接。Firefox支持打开8个连接,但仍然是一个限制。如果Web应用程序不对Ajax调用进行控 制,它就很可能打开2个以上的连接,尤其是服务器端调用属于时间密集型调用时。这个问题可能源于Web应用程序的不良设计,或用户不对请求加以限制。不管 是那种情况都是不可取的,因为您不希望由浏览器决定使用哪些连接。

另外,因为调用是异步的,不能保证从服务器返回的响应的顺序与发送时一样。例如,如果您几乎同时发出2个Ajax调用,您就不能保证服务器的响应是 以相同的顺序返回。因此,如果第二个调用依赖于第一个调用的结果,那么就会出现问题。想象这样一种场景,其中第一个调用获取数据,第二个调用在客户端操作 该数据。如果第二个调用的响应返回得比第一个Ajax调用快,那么您的代码就会导致错误。您完全不能保证响应速度。当调用更多时,就更容易导致问题。

jQuery的创建者意识到这个潜在的问题,但同时也认识到它仅会给1%的Web应用程序带来问题。但1%开发Web应用程序的开发人员需要一个解 决办法。因此创建了一个插件,通过创建一个Ajax Queue和一个Ajax Sync来筛查该问题。Queue和Sync的功能是很相似的:Queue一次发出一个Ajax调用,并且等待其响应返回之后才发出另一个调用。Sync 几乎同时发出多个调用,但调用的响应是按先后顺序返回的。

通过在客户端控制Ajax调用解决了超载问题,同时也控制和规范了将响应发送回客户端的方式。现在,您可以确保知道响应返回到客户端的顺序,从而可 以根据事件的顺序编写代码。我们看看这个插件是如何工作的,以及如何在您的代码中使用它(见清单7)。记住,这仅是为1%的Web应用程序设计的,它们拥 有多个Ajax调用,并且后一个调用严重依赖于前一个调用的结果。这个示例不是调用相互依赖的例子,但它能够向您展示如何使用该插件(要为这个插件的应用 创建一个完美的真实例子,并让其易于理解是很困难的)。

  1. varnewRow = "<trid='?'>" +  
  2. " < td > < inputtype inputtype = checkboxvalue ='?' > </ td > "+  
  3. " < td > ? </ td > "+  
  4. " < td > ? </ td > "+  
  5. " < td > ? </ td > "+  
  6. " < td > ? </ td > </ tr > "; 
  1. $("#mailtable").everyTime(30000,"checkForMail",function(){  
  2. //byusingtheAjaxQueuehere,wecanbesurethatwewillcheckformail  
  3. //every30seconds,butONLYifthepreviousmailcheckhasalreadyreturned.  
  4. //Thisactuallywouldbebeneficialinamailapplication,ifonecheckfor  
  5. //newmailtakeslongerthan30secondstorespond,wewouldn'twantthe  
  6. //nextAjaxcalltokickoff,becauseitmightduplicatemessages(depending  
  7. //ontheserversidecode).  
  8. //So,byusingtheAjaxQueueplug-in,wecanensurethatourWebclient  
  9. //isonlycheckingfornewmailonce,andwillneveroverlapitself.  
  10.  
  11. $.ajaxQueue({  
  12. url:"check_for_mail.jsp",  
  13. success:function(data)  
  14. {  
  15. varmessage = eval ('('+data+')');  
  16. if(message.id!=0)  
  17. {  
  18. varrow = newRow .replace("?",message.id);  
  19. row row =row.replace("?",message.id);  
  20. row row =row.replace("?",message.to);  
  21. row row =row.replace("?",message.from);  
  22. row row =row.replace("?",message.subject);  
  23. row row =row.replace("?",message.sentTime);  
  24. $("#mailtabletbody").prepend(row);  
  25. $("#mailtable#"+message.id).addClass("mail_unread").addClass("messageRow");  
  26. $("#mailtable#"+message.id+"td").addClass("mail");  
  27. $("#mailtable:checkbox").addClass("selectable");  
  28. }  
  29. }  
  30. });  

记住:如果您的应用程序有多个相互依赖的Ajax调用,那么要考虑使用Ajax Queue或Ajax Sync。

第二个示例Web应用程序

我将使用另一个小部件解决本文的最后3个问题,并且在深入研究其代码之前展示和解释它。这个401k小部件并不陌生,因为您已经在前面的文章见过它 (参见参考资料部分获取这些文章的链接)。不过,这回有个微妙的不同之处,因为我在同一个页面上两次添加了这个小部件。它被添加到两个不同的表中。这将带 来几个有趣的地方。图3显示了这个小部件:

在这个小部件中,我正在做几件事情。第一件是计算文本字段之和并确定它们是否为100。如果它们的和不为100,我将向用户显示一个错误,提示他们 没有正确使用该小部件。第二,我在每个选项获取输入之后对选项进行排序。通过这种方式,百分比最高的投资分配将一直出现在表的顶部。这可以在图3中看到, 它按百分比对选项进行排序。最后,为了让它更酷,我添加了一些条带。

用于生产这个小部件的HTML代码出奇地简单。清单8详细地显示了这个小部件。

  1. < p > < tablewidth tablewidth = 300class ="percentSort" cellpadding = 0cellspacing =0 >  
  2. < tbody >  
  3. < tr > < td > S&P500Index </ td >  
  4. < td > < inputtype inputtype = text > % </ td > </ tr >  
  5. < tr > < td > Russell2000Index </ td >  
  6. < td > < inputtype inputtype = text > % </ td > </ tr >  
  7. < tr > < td > MSCIInternationalIndex </ td >  
  8. < td > < inputtype inputtype = text > % </ td > </ tr >  
  9. < tr > < td > MSCIEmergingMarketIndex </ td >  
  10. < td > < inputtype inputtype = text > % </ td > </ tr >  
  11. < tr > < td > REITIndex </ td >  
  12. < td > < inputtype inputtype = text > % </ td > </ tr >  
  13. </ tbody >  
  14. < tfoot >  
  15. </ tfoot >  
  16. </ table >  

用jQuery设置小部件

以上的一小段HTML直接引入了这部分内容,本小节关注如何在jQuery中设置小部件,以及所需的所有代码。要将事件附加到页面元素或在特定情况 下需要添加类时,通常需要这样做。有时候还需要更进一步。这些小部件的所有设置代码都是jQuery代码。

我可以提供关于角色分离的理论,让HTML设计师和JavaScript程序员各自完成自己的工作,但是您们可能已经多次听到这种陈词。在这里我仅 添加另一样东西,即“类修饰”,这是很多插件创作者都使用的。看看清单8中的HTML代码,仅通过将一个percentSort类添加到表,您就可以显著 改变表的功能和外观。这是小部件设计的目标,让添加和删除小部件就像向小部件添加类一样简单。

让我们遵循我曾用jQuery设置小部件的几个步骤。通过查看这些步骤,您可以看到清单9中的设计模式是如何出现的。

  1. $(document).ready(function(){  
  2.  
  3. //thefirststepistofindallthetablesonthepagewith  
  4. //aclassofpercentSort.Theseareallthetableswewantto  
  5. //convertintoourwidget.  
  6. //Afterwefindthem,weneedtoloopthroughthemandtakesome  
  7. //actionsonthem  
  8. //Attheconclusionofthisblockofcode,eachtablethat'sgoingto  
  9. //beapercentSortwidgetwillhavebeentransformed  
  10.  
  11. $("table.percentSort").each(function(i){  
  12.  
  13. //eachtableneedsauniqueID,fornamespaceissues(discussedlater)  
  14. //wecansimplycreateauniqueIDfromtheloopcounter  
  15.  
  16. $(this).attr("id","percentSort-"+i);  
  17.  
  18. //withineachtable,let'shighlighteveryotherrowinthetable,to  
  19. //giveitthat"zebra"look  
  20.  
  21. $(this).find("tbody > tr").filter(":odd").addClass("highlight");  
  22.  
  23. //becauseeachtableneedstoshowthe"Total"totheuser,let'screateanew  
  24. //sectionofthetableinthefooter.We'lladdarowinthetablefooter  
  25. //todisplaythewords"Total"andaspanfortheupdatedcount.  
  26.  
  27. $("#"+$(this).attr("id")+"tfoot")  
  28. .append(" < tr > < td > Total </ td > < td >  
  29. < span > </ span > % </ td > </ tr > ");  
  30.  
  31. //finally,let'saddtheCLASSof"percentTotal"tothespanwejust  
  32. //createdabove.We'llusethisinformationlatertodisplay  
  33. //theupdatedtotals  
  34.  
  35. $("#"+$(this).attr("id")+"tfootspan").addClass("percentTotal");  
  36. });  
  37.  
  38. //nowthesecondstep,afterwe'vecompletedsettingupthetablesthemselves  
  39. //istosetuptheindividualtablerows.  
  40. //Wecansimilarlysortthrougheachofthem,takingtheappropriateactions  
  41. //oneachoftheminturn.  
  42. //Uponcompletionofthisblockofcode,eachrowineachtablewillbe  
  43. //transformedforourwidget  
  1. $("table.percentSorttbody > tr").each(function(i){  
  2.  
  3. //getthenamespace(tobediscussedinthenextsection)  
  4.  
  5. varNAMESPACE =$(this).parents("table.percentSort").attr("id");  
  6.  
  7. //attachauniqueIDtothisrow.Wecanusetheloopcounter  
  8. //toensuretheIDisuniqueonthepage(whichisamustoneverypage)  
  9.  
  10. $(this).attr("id","row"+i);  
  11.  
  12. //now,withinthisrowofthetable,weneedtofindthetextinput,because  
  13. //weneedtoattachaclasstothem.Weutilizethenamespace,andalso  
  14. //findthe:textwithinthetablerow,andthenattachthecorrectclass  
  15.  
  16. $("#"+$(this).attr("id")+":text").addClass("percent");  
  17.  
  18. //Finally,weattachauniqueIDtoeachofthetextinputs,andwedothisby  
  19. //makingitacombinationofthetablenameandtherowname.  
  20.  
  21. $("#"+$(this).attr("id")+".percent").  
  22. attr("id",NAMESPACE+"-"+$(this).attr("id"));  
  23. });  
  24. //Finally,becauseweknowweonlywantnumericalinputs,werestrictthetextentry  
  25. //tojustnumbers.Wemustdothisnow,becauseupuntilthispoint,thepage  
  26. //containednoelementswiththeCLASS"percent"  
  27. $(".percent").numeric();  

如您从这个例子中见到的一样,可以通过jQuery代码向HTML代码引入大量功能。这种类型的设计的好处是很明显的。同样,遵循角色分离、代码重 用等也是非常有益的。您还将在小部件插件中看到这种类型的设计,因为它将简单的HTML代码转变成适用于插件的小部件。最重要的是,这也是您在这里需要完 成的任务,即编写一个插件来将一个简单的表转变成排序和汇总表。

记住:尽量多使用jQuery代码进行设置,并且尽可能少使用HTML。

名称空间

可能处理这种类型的设计和jQuery的最难解方面是理解名称空间。这个例子很好,因为它以一种很直观的方式展示了该问题。知道页面上的所有ID和 类时,编写jQuery代码是非常简单的。这就是jQuery的设计目标。当您不知道页面上有几个类时,或这些类开始重复时,会发生什么呢?在这个例子 中,您可以直接看到问题,有两个完全相同的小部件!所有东西都是重复的。这似乎是不考虑名称空间引起的问题;您的小部件开始彼此干扰,最终导致不能正常工 作。

造成这个问题的原因是您仅调用$(".percentTotal")等,而忽略了应该同步哪个小部件。因为相同的页面上有多个表,因此该页面就有 percentTotal类的多个实例。当然,如果页面上仅有一个表,那么您就可以确定它是唯一的。但是随着页面更加高级,以及组件的重用越来越多,这种 一个表的假设就不再成立。有些人会问,“在这里使用ID不行吗?”这不能解决问题:您打算给它什么ID?您不可以使用“percentTotal”,因为 这会带来歧义。

也不可以使用“percentTotal-1”,因为它不表示页面上的任何东西。(以上数字毕竟是任意创建的)。您可以向页面包含的表添加一些引用 来解决问题,比如“percentTotal-percentSort1”,但这会让问题更加复杂。jQuery有一个超级复杂但又十分容易使用的选择语 法,从而让这种混合命名模式变得毫无必要。为什么要重新创造已有的东西呢?让我们使用jQuery的选择引擎帮助您解决名称空间问题。

这个小部件的核心问题是决定操作发生在哪个小部件中。当向文本框输入数字时,您可以问自己,jQuery如何知道进入哪个文本框?您在代码中的“百 分比”类添加了一个事件,并且可以在代码内部使用$(this)引用它。这将我们带入下一个问题:jQuery如何知道问题发生在哪个小部件中,从而使您 能够更新正确的percentTotal字段?我认为这不是一件简单的事情。这确实不简单。尽管您的代码能够向页面上带有“百分比”类的每个文本框添加一 个事件,但如果忽略了发生事件的小部件就是不妥当的。

这个问题被归结为名称空间问题的原因是,小部件的命名不清晰,容易导致问题。要使jQuery代码正常工作,每个名称都必须在其自己的空间之内明确 定义,这就出现了术语名称空间。您必须避免编写重名的代码,实现每个小部件都是自含的。您必须能够在相同的页面上添加相同小部件的多个实例,同时避免名称 重复。最重要的是,每个小部件在页面上都是独立的。

没有能够处理名称空间问题的现成方法,因此我将展示我的解决办法,您可以在自己的代码中使用我的办法,或通过了解问题创建更好的解决办法。我喜欢该 代码的原因是它简单易用(只有1行),并且能够让您在某种程度上控制自己的名称空间。看看清单10。

  1. //oureventisattachedtoEVERYinputtextfieldwithaCLASSof"percent"  
  2. //thismakesourcodelookgood,butcanleadtonamespaceissues  
  3. $("table.percentSortinput.percent").keyup(function(){  
  4.  
  5. //thissimplelinecanestablishanamespaceforus,bygettingtheunique  
  6. //IDattachedtoourtable(thetableisconsideredthe"container"for  
  7. //ourwidget.Itcouldbeanything,dependingonyourspecificcode.)  
  8. //WepasstheCLASSofourwidgettotheparents()function,because  
  9. //thateffectivelyencapsulatesthewidget  
  10.  
  11. varNAMESPACE = "#" +$(this).parents("table.percentSort").attr("id");  
  12.  
  13. //withthenamespaceestablished,wecanusethejQueryselection  
  14. //syntaxtousethisnamespaceasourprefixforallofourremaining  
  15. //searches.Noticehowtheambiguityisremovedforoursearch  
  16. //byCLASSof"percent"and"percentTotal"  
  17. //Thissolvesournamespaceissues  
  18.  
  19. varsum =$(NAMESPACE+"input.percent").sum();  
  20. vartotalField =$(NAMESPACE+".percentTotal"); 

因此,仅需添加一行代码,您就能够封装小部件,从而避免它的函数与自身的其他实例重复(或者甚至是其他碰巧对ID或类使用相同名称的小部件)。这种 类型的代码编写方式在插件代码中很常见。编写良好的插件应该考虑到名称空间问题,而糟糕的插件忽略了这个问题。从这个例子中可以看到,在代码中使用名称空 间也是很简单的,并且随着页面越来越复杂,它可以给您节省大量时间。鉴于这个原因,我建议您现在就开始考虑jQuery代码中的名称空间问题,并在编写代 码时使用这种解决办法。

记住:开始编写jQuery代码时,一般就要开始包含名称空间解决办法。您可以使用以上的解决办法,或创建自己的解决办法。通过采用名称空间解决办 法,即使代码越来越复杂,也不会带来名称重复问题。

结束语

本文提供一些技巧,帮助您将良好的jQuery代码转变成强大的jQuery代码。jQuery非常简单易用(并且是独立的JavaScript的 巨大改进),因此编写良好的jQuery代码也很容易。大部分开发人员在几分钟之内编写完并运行良好的jQuery代码。但是良好的代码和强大的代码是有 区别的。强大的jQuery代码考虑随着页面越来越复杂时的性能问题。强大的jQuery代码能够考虑到页面的未来方向,而不是仅看到当前的位置。强大的 jQuery代码是为最复杂的应用程序设计的,然后让应用程序处理输入的简单信息。

本文介绍了5个概念,帮助您将良好的jQuery代码转变成强大的jQuery代码。

第一个概念是使用bind()/unbind()方法。当您不希望在页面的生命周期内将事件添加到代码时,这些方法对向页面元素添加/移除事件非常 有用。这些方法在页面包含大量事件时对提升性能非常重要,或者用于某些用户界面中。

第二个概念是使用1.3中包含的新特性live()/die()。这些函数允许将事件变成动态的,就像页面元素一样。随着Web应用程序包含的页面 元素越来越多,这些函数允许代码随着页面的增长而增长,这在以前的发布版中是无法实现的。您希望事件处理像页面处理一样具有动态性。

第三个新添加的特性是AjaxQueue/Sync插件,它用于规范和控制对服务器发出的Ajax调用,避免它们超出限度(从客户端角度看)。当 Ajax调用的响应返回顺序很重要时,该插件也能帮上大忙。

第四个概念是,尽可能多地用jQuery代码编写页面设置代码。这让HTML的编写更加简单,并且在设置页面时能够获得更多的控制。

最后一个概念是,在代码中利用名称空间解决办法,避免因小部件的函数名称重复而导致问题。每个页面元素和小部件都应该是自含的,不与页面的其他方面 发生干扰,名称空间解决办法能够阻止该问题。

这5个步骤并不难实现。事实上,其中4个步骤仅需修改一行代码。不过,理解如何在代码中应用它们才是最重要的。像所有东西一样,如果不能正确时使 用,它不仅不能提供帮助,反而还有害处。我的建议是,当您用jQuery代码编写页面时,要尽快应用这5个步骤。每个开发人员都会告诉您,利用特性是编程 过程的一部分。您不希望仅因开头设计得不好或更改某些部分而重新设计整个Web应用程序。编写代码时就要抱有编写强大应用程序的想法,并且遵循这些建议。

原文地址:http://developer.51cto.com/art/201007/213251.htm

排行榜 更多 +
辰域智控app

辰域智控app

系统工具 下载
网医联盟app

网医联盟app

运动健身 下载
汇丰汇选App

汇丰汇选App

金融理财 下载