您的位置:首页 > Web前端 > JQuery

jQuery高级应用:优化Web应用程序的最后绝招1

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

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

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

第一个示例应用程序




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

Bind/Unbind

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




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

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

$(document).ready(function(){
//cachethisquerysinceit'sasearchbyCLASS
selectable=$(":checked.selectable");
//whentheselect/deselectallisclicked,dothisfunction
$("#selectall").click(selectAll);
//wheneveranyindividualcheckboxischecked,changethetext
//describinghowmanyarechecked
selectable.click(changeNumFilters);
//calculatehowmanyareinitiallychecked
changeNumFilters();
});

varselectable;
functionchangeNumFilters()
{
//thisneedstobecheckedoneverycall
//sincethelengthcanchangewitheveryclick
varsize=$(":checked.selectable").length;
if(size>0)
$("#selectedCount").html(size);
else
$("#selectedCount").html("0");
}

//handlestheselect/deselectofallcheckboxes
functionselectAll()
{
varchecked=$("#selectall").attr("checked");
selectable.each(function(){
varsubChecked=$(this).attr("checked");
if(subChecked!=checked)
{
$(this).click();
}
});
changeNumFilters();
}

该代码看起来比较简单,因为我在好几篇文章中都用到这个小部件。您在第一篇文章中见到了“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显示了更新之后的小部件。

//handlestheselection/unselectionofallcheckboxes
functionselectAll()
{
varchecked=$("#selectall").attr("checked");
selectable.unbind("click",changeNumFilters);
selectable.each(function(){
varsubChecked=$(this).attr("checked");
if(subChecked!=checked)
{
$(this).click();
}
});
selectable.bind("click",changeNumFilters);
changeNumFilters();
}

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

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

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

functionselectAll()
{
varchecked=$("#selectall").attr("checked");
selectable.each(function(){
$(this).attr("checked",checked);
});
changeNumFilters();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: