Board logo

标题: 高级 jQuery-1 [打印本页]

作者: look_w    时间: 2018-8-23 09:18     标题: 高级 jQuery-1

简介这个关于 jQuery 的系列文章帮助您提高了创建基于 JavaScript 的 Web 应用程序的能力。即使您在阅读这些文章之前从未听说过 jQuery,但是您应该已经具备了使用 jQuery 构建良好的 Web 应用程序所需的语言技能和背景知识。但是,有时候良好的应用程序还不能满足需求,这时您将需要一个强大的 Web 应用程序。这就需要通过几个步骤修改现有的应用程序,让它能够在各种场合中顺利运行,并且适合所有用户。这些步骤是优化您的 Web 应用程序的最后绝招。
在本文中,我将讨论代码的性能改进,同时也谈及一些关于 jQuery 库的容易被忽视的问题。有些东西对于复杂的应用程序而言至关重要,即对所有应用程序都非常关键的插件,以及使应用程序的编写更加容易的良好设计技巧。在最后一个小节中,我将讨论 jQuery 1.3 中的一些新特性,它们是最近发布的并且为 jQuery 库添加了一些新特性。
第一个示例应用程序本文中的大部分技巧都可以从附带的样例应用程序中找到(见 ),这是一个直观的电子邮件 Web 应用程序。您可能对它比较熟悉,因为我在本系列的第一篇文章中使用的就是它。不过,您可以看到它是如何从第一篇文章中发展而来的,它的性能是如何改进的,以及这些最后步骤如何将它转变成强大的 Web 应用程序的。
图 1. 样例应用程序Bind/Unbind在 Events 模块中有两个函数,它们是 bind() 和 unbind(),用于完成所有其他事件方法的任务。如果您能够向页面元素添加一个 click() 方法,那么哪还有必要调用 bind("click") 呢?这仅是浪费时间而已。但是,这些函数在特定情况下是非常方便的,如果正确地使用它们,可以显著提高应用程序的性能。这些函数不仅能够向特定页面元素添加事件(就像该模块中的许多其他事件方法一样),而且还可以从页面元素中删除这些事件。为什么要这样做?下面我们看看这个 Web 应用程序,以及如何在特定情况下使用这些函数。
图 2. Bind/Unbind 示例清单 1 显示了以上设置的代码,这是未改进之前的原始代码:         
清单 1. 未经过优化的小部件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
$(document).ready(function(){
   // cache this query since it's a search by CLASS
   selectable = $(":checked.selectable");
   // when the select/deselect all is clicked, do this function
   $("#selectall").click(selectAll);
   // whenever any individual checkbox is checked, change the text
   // describing how many are checked
   selectable.click(changeNumFilters);
   // calculate how many are initially checked
   changeNumFilters();
});

var selectable;

function changeNumFilters()
{
   // this needs to be checked on every call
   // since the length can change with every click
   var size = $(":checked.selectable").length;
   if (size > 0)
      $("#selectedCount").html(size);
   else
      $("#selectedCount").html("0");
}
  
// handles the select/deselect of all checkboxes
function selectAll()
{
   var checked = $("#selectall").attr("checked");
   selectable.each(function(){
      var subChecked = $(this).attr("checked");
      if (subChecked != checked)
      {
         $(this).click();
      }
   });
   changeNumFilters();
   }




该代码看起来比较简单,因为我在好几篇文章中都用到这个小部件。您在第一篇文章中见到了 “select/deselect all” 小部件,我给出了它的基础形式。在关于性能的文章中,您看到如何通过缓存选择查询和通过 CLASS 减少使用查询来改进它的性能。但是还有一个问题需要解决。当在包含 100 行的表中勾选 “select/deselect all” 复选框之后,您将得到糟糕的性能。事实上,在我的浏览器中,如果使用了这些代码,那么完成选择的平均时间为 3.4 秒。响应性太差了!即使进行了各项优化,仍然有些不可接受的地方。
让我们深入一步考察这个算法,看看是否有地方出了问题。您将遍历页面上的每个复选框,看看它们当前的 “checked” 状态是否与 “select/deselect all” 复选框一致。如果不一致,就对其调用 “click”,以和 “select/deselect all” 复选框的状态匹配。等一等,您还需要向这些复选框添加一个函数,从而在每次单击时都调用 changeNumFilters() 函数。通过仔细检查,您发现设置了一个可能调用 changeNumFilters() 101 次的算法。怪不得性能如此差。很明显,您不需要在每次单击时都更新选中的消息的计数,而是在该过程完成之后进行更新即可。在单击复选框的同时如何才能避免调用该方法?
现在,unbind() 方法开始发挥它的作用。通过在单击复选框之前调用 unbind(),将停止调用 click(),同时避免了 click() 进一步调用 changeNumFilter() 方法。这很棒!现在就不会调用 changeNumFilters() 101 次了。但是,这仅是一次有效的,在调用 click 方法之后,需要使用 bind 方法将 click 方法添加回到每个复选框。清单 2 显示了更新之后的小部件。
清单 2. 经过优化的小部件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// handles the selection/unselection of all checkboxes
function selectAll()
{
   var checked = $("#selectall").attr("checked");
   selectable.unbind("click", changeNumFilters);
   selectable.each(function(){
      var subChecked = $(this).attr("checked");
      if (subChecked != checked)
      {
          $(this).click();
      }
   });
   selectable.bind("click", changeNumFilters);
   changeNumFilters();
   }




通过这些优化之后,复选框的运行速度提高到约 900 毫秒,从而大大改进了性能。这些改进源于返回去检查您的算法正在做什么,以及贯穿代码的操作。您可以仅调用函数 1 次,而不是 100 次。通过在本系列的其他文章中不断改进该函数,您最后会让它变得更快、更高效。但不一定非得这么做,我还发现一个最快的算法,以前从来没有透露过。此外,如果我过早地向您展示这个最快的算法,我就不能将其作为本文的题材了。希望它能使您看到在代码中使用 bind/unbind 特性带来的好处(如果没有更好的方法的话)。
记住:在不希望触发默认事件时才使用 bind/unbind,或作为向页面元素添加或删除事件的临时方法
清单 3 显示了编写该算法的最快方法(如果您的代码中有这个小部件)。它运行该函数仅需 40 毫秒,远远胜过之前的其他方法。               
清单 3. 使用超快算法的小部件
1
2
3
4
5
6
7
8
function selectAll()
{
   var checked = $("#selectall").attr("checked");
   selectable.each(function(){
      $(this).attr("checked", checked);
   });
   changeNumFilters();
   }






欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0