06 jquery进阶_进阶jQuery

06 jquery进阶

有关jQuery的本系列文章使您在创建基于JavaScript的Web应用程序方面发挥了巨大作用。 即使您在开始阅读这些文章之前从未听说过jQuery,到目前为止,您应该已经掌握了该语言的所有技能和背景知识,可以使用jQuery生成良好的Web应用程序。 但是,有时一个好的应用程序还不够。 有时您需要一个出色的Web应用程序。 这需要一些额外的步骤,即您添加到应用程序中的步骤,以确保它可以在大型应用程序和小型应用程序中平稳运行,并且看起来恰好适合每个用户。 它们是您添加的使您的Web应用程序更富光泽的最后一层。

在本文中,我将讨论对代码的基于性能的改进,但是我还将讨论jQuery库中某些人可能会忽略的内容。 这些项目在复杂的应用程序中很重要,它们是对任何人的应用程序都至关重要的插件,它们是使您的Web应用程序更易于编码的不错的设计技巧。 最后,在上一节中,我将讨论jQuery 1.3的一些新功能,该功能是最近发布的,并向库中添加了一些新功能。

第一个示例应用程序

可以在本文所附的示例应用程序中找到本文的大多数技巧(请参阅可下载的资源 ),这是一个简单的电子邮件Web应用程序。 它看起来应该很熟悉,因为它与我在本系列的第一篇文章中介绍的一样。 但是,您应该看到它与第一篇文章相距甚远,性能如何提高,以及经过最后的改进如何将其变成了一个非常出色的Web应用程序。

图1.示例应用程序
邮件Web应用程序的屏幕截图,显示了一个典型的邮箱,其中的侧边栏为“收件箱”和“已发送”,顶部的“撰写”或“删除”按钮,以及带有可单击消息的收件箱内容列表。

绑定/取消绑定

在“事件”模块中,有两个函数,分别称为bind()unbind() ,它们出现在表面上以复制所有其他事件方法的工作。 毕竟,如果您可以简单地将click()方法附加到页面元素,为什么您需要在其上调用bind("click") ? 这只是浪费按键。 好吧,事实证明这些功能在某些情况下很方便,并且如果使用得当,它们可以极大地提高应用程序的性能。 这些功能确实使您能够将事件附加到某些页面元素,就像模块中的众多事件方法一样,但是它们还允许您从页面元素中删除这些事件。 你为什么想做这个? 好,让我们看一下Web应用程序,看看如何在这种情况下使用它们。

图2.绑定/取消绑定示例
该图显示了收件箱消息列表的一部分,并在各个元素上带有符号。 “全选/取消全选”复选框位于左上方。每个消息行旁边都有单独的复选框。消息“您有5条已选择的消息”在每个复选框选择中都会更新,将已选中复选框的总行数相加。

清单1显示了设置它的代码,它是我最初对其进行改进之前编写的:

清单1.优化之前的小部件
$(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();
   }

该代码应该看起来相对简单,因为它与我在几篇文章中使用的小部件几乎相同。 您在第一篇文章中以基本形式展示了“全选/取消全选”小部件。 在性能文章中,您了解了如何通过缓存选择查询并最小化CLASS搜索的使用来提高其性能。 但是,仍然存在问题。 在具有100行的表中按下“全选/取消全选”复选框时,您会发现性能很差。 实际上,在我的浏览器中,有了此代码,完成全部选择的平均时间为3.4秒。 这根本不是很敏感。 即使经过了所有的优化,您仍然有一些不可接受的地方。

让我们在这里进一步深入算法,看看是否有问题。 您遍历页面上的每个复选框,并查看其当前的“已选中”状态是否与“全选/取消全选”复选框相同。 如果不是,则在其上调用“单击”,以使其与“全选/取消全选”复选框的状态匹配。 不过,请稍等...您还向这些复选框附加了一个函数,因此每次单击都将调用changeNumFilters()函数。 在仔细检查之后,您已经建立了一种算法,该算法可能调用101次changeNumFilters() 。 难怪性能这么差。 显然,您不需要每次单击都更新选定消息的计数,您可以在过程结束时执行一次。 在同时单击复选框的同时,如何防止调用此方法?

好吧,当然, unbind()方法是起作用的地方。 您可能会看到这种情况的到来。 通过调用unbind()被点击复选框之前,将停止呼叫click()依次从调用changeNumFilter()方法。 这很棒! 这就是你想要的。 现在不会被调用101次。 但是,当然,这只能使用一次,因此,在使用完bind方法调用click之后,必须将click方法附加到每个复选框。 请参见清单2中的更新版本。

清单2.优化后的小部件
// 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毫秒内运行,这在性能上有很大的提高。 这完全是退后一步,然后仔细考虑您的算法在做什么,以及您的操作将如何遍历代码。 不必一次调用一个函数,而只需调用一次即可。 万岁! 在看了这么多文章的功能之后,您终于使它尽可能快和高效。 好吧,不是真的。。。事实证明,有一种超快速的方法来运行此算法,直到现在我一直在向您介绍。 此外,如果我立即为您提供了快速算法,那么我将无法将该功能用作这些文章的课程。 希望这种情况使您对使用代码中的bind / unbind功能的好处大开眼界(如果没有捷径的话)。

切记:在您不希望触发默认事件的情况下,请使用bind / unbind,或者将其临时附加或删除页面元素中的事件

清单3显示了编写此算法的超快方法,如果您自己的代码中有此小部件。 它在40毫秒内运行此功能,与我们尝试过的其他功能相比非常快。

清单3.具有超快速算法的小部件
function selectAll()
{
   var checked = $("#selectall").attr("checked");
   selectable.each(function(){
      $(this).attr("checked", checked);
   });
   changeNumFilters();
   }

现场/死亡

jQuery 1.3版本的两个重要新增功能是live()die()函数。 通过一个示例可以最好地看出它们在精心设计的Web应用程序中的作用。 想象一下,将一个双击附加到表中的每个单元格上。 作为经验丰富的jQuery老手,您知道应该在document.ready()函数中创建此设置,如清单4所示。

清单4.设置一个双击
$("tr.messageRow").dblclick(function() {
   if ($(this).hasClass("mail_unread"))
   {
      $(this).removeClass("mail_unread");
   }
   });

这种设计只有一个问题。 是的,它使用一个messageRow类将双击事件附加到表中的每一行。 但是,如果您向表中添加新行呢? 例如,当您有其他消息使用Ajax加载到页面中而不重新加载页面时,这些行可能会出现。 这就带来了一个问题,因为所编写的代码无法正常工作。 您创建的事件已绑定到页面加载时存在的所有现有tr.messageRow元素。 它与您在页面生存期内创建的任何新tr.messageRow没有绑定。 像这样编写代码的人会很失望地发现自己的代码行不通。 初学者jQuery程序员甚至可能花几个小时来进行令人头疼的调试,以弄清楚他们的代码为什么不起作用,然后才在jQuery文档中发现这一事实。 (是的,那是我去年)。

在jQuery 1.3之前,有三种方法可以解决此问题,但都不是一种优雅的方法(对于继续使用jQuery 1.2.x的人来说,这些方法仍然有效)。 第一种是重新初始化技术,每次添加新元素时,它都会将事件简单地重新附加到所选元素。 第二个是利用我们在上一节中看到的bind / unbind方法。 在清单5中都可以看到它们。

清单5.将事件附加到新元素的解决方法
// first technique to deal with "hot" page elements, added during the page's
// lifetime
$("#mailtable tr #"+message.id).addClass("messageRow")
   .dblclick(function() {
   if ($(this).hasClass("mail_unread"))
   {
      $(this).removeClass("mail_unread");
   }

// second technique to deal with "hot" page elements
$("#mailtable tr #"+message.id).addClass("messageRow")
   .bind("dblclick", (function() {
   if ($(this).hasClass("mail_unread"))
   {
      $(this).removeClass("mail_unread");
      }

如您所知,这两种技术都不是很优雅。 您将重复代码。 并且,您将不得不寻找可以将新的页面元素添加到页面的所有可能的点,并在那时处理“热点元素”问题。 那不是编程的好方法。 此外,这是jQuery。 它应该使我们的工作变得异常简单。 它应该为我们做一切。

幸运的是,有一个插件似乎可以解决这些问题。 它称为LiveQuery插件,它使您可以将某些页面元素绑定到事件,但以“实时”方式进行,因此所有页面元素,包括在页面创建时存在的元素和在页面创建期间创建的元素。生命周期(例如通过Ajax调用)将触发事件发生。 对于UI开发人员来说,这是一个非常聪明且重要的插件,因为它使处理动态页面与处理静态页面一样容易。 对于Web应用程序开发人员来说,它确实是那些“必须具备”的插件之一。

jQuery核心团队非常认同此插件的重要性,因此将其合并到1.3版本中。 现在,此“实时”功能已成为jQuery核心的一部分,因此任何开发人员都可以利用该功能。 几乎在1.3核心代码中完全复制了该插件,减去了一些在1.3的第一个发行版中没有引起关注的事件。 我敢打赌这些丢失的事件将出现在jQuery的下一版本中。 让我们看一下如何使用它来更改您的代码。

清单6.“实时”事件模型
$("tr.messageRow").live("dblclick", function() {
   if ($(this).hasClass("mail_unread"))
   {
      $(this).removeClass("mail_unread");
      }

在代码中进行小的更改,双击页面上的所有tr.messageRow元素都会触发此代码。 如上文所述,如果仅使用dblclick()函数,则不会出现这种情况。 因此,我强烈建议您考虑对大多数事件方法使用live()方法。 实际上,我必须说,任何通过Ajax或用户交互动态创建页面元素的页面都必须使用live()函数而不是其他事件方法。 只是在编码易用性与编码之间进行了很大的权衡。 可能的错误,这是一个明智的决定。

切记:将事件附加到动态页面元素时,请始终使用live()方法。 这使您的事件像页面元素一样动态。

Ajax队列/同步

对服务器的Ajax调用的使用正在成为Web 2.0公司进行自我评估的标准。 正如我们在此进行了无休止的讨论,在jQuery中使用Ajax与正常调用方法调用一样简单。 这意味着您可以像调用客户端JavaScript函数一样轻松地调用任何服务器端Ajax函数。 但是,这种好处有一些不太理想的副作用,如果对服务器的Ajax调用过多,则可能会发生这些副作用。 如果Web应用程序因Ajax调用而变得异常复杂,则肯定会出现问题。

第一个问题是某些浏览器限制了到服务器的打开连接数。 在Internet Explorer中,当前版本仅允许2个打开的并发连接到服务器。 Firefox允许8个连接,但仍然是开放连接的限制。 如果Web应用程序使Ajax调用失控,则它肯定可以具有2个以上的打开连接,尤其是在服务器端调用耗时的情况下。 Web应用程序设计器的设计不当,甚至是对自己的请求失去控制的用户,都可能导致此问题。 无论如何,这都不是一个好的状态,并且您不想在任何情况下浏览器都在决定允许哪些连接以及不允许哪些连接。

此外,由于调用是异步的(Ajax中为“ A”),因此不能保证从服务器返回的返回顺序与发送时的顺序相同。 等等...什么? 是的,如果您大约同时进行2个Ajax调用,则不能保证服务器的响应将以相同的顺序返回。 因此,如果您的第二个电话取决于您的第一个电话,那么您可能不走运。 设想一个场景,您的第一个调用检索数据,而第二个调用在客户端以某种方式处理数据。 如果第二次调用返回的速度比第一次Ajax调用快,则您的代码可能会导致错误。 您无法保证响应速度。 将此问题乘以4,您会看到问题开始Swift出现。

jQuery的创建者认识到这是一个潜在的问题,但也认识到Web应用程序仅在大约1%的时间内会出现问题。 但是,对于那些占1%的开发人员,他们需要一个解决方案。 他创建了一个插件,该插件可通过创建Ajax Queue和Ajax Sync来解决此问题。 两者的功能非常相似:队列一次将Ajax调用一次,等待另一个返回后再开始下一个调用。 Sync会立即将它们发送出去,但仅在前一个函数已经返回时才返回到调用函数。

这通过控制客户端上的Ajax调用以及控制和调节响应如何发送回客户端代码来解决过载问题。 现在,您可以确定知道响应返回到客户端的顺序,从而使您能够编写可预测事件顺序的代码。 让我们看一下该插件的工作方式,以及如何在清单7中的示例中在代码中使用它。请记住,该插件是为1%的条件而设计的,在这种情况下,多个Ajax调用具有重要的信息取决于以前的Ajax调用。 该示例不是其中的一个示例,但是它仍然可以让您看到如何使用该插件(很难创建一个很好的真实示例,其中需要此插件,并且仍然很容易理解)。

清单7. Ajax队列
var newRow = "<tr id='?'>" +
             "<td><input type=checkbox value='?'></td>" +
             "<td>?</td>" +
             "<td>?</td>" +
             "<td>?</td>" +
             "<td>?</td></tr>";
   
   
$("#mailtable").everyTime(30000, "checkForMail", function(){

   // by using the Ajax Queue here, we can be sure that we will check for mail
   // every 30 seconds, but ONLY if the previous mail check has already returned.
   // This actually would be beneficial in a mail application, if one check for
   // new mail takes longer than 30 seconds to respond, we wouldn't want the
   // next Ajax call to kick off, because it might duplicate messages (depending
   // on the server side code).
   // So, by using the Ajax Queue plug-in, we can ensure that our Web client
   // is only checking for new mail once, and will never overlap itself.

    $.ajaxQueue({
         url: "check_for_mail.jsp",
         success: function(data)
         {
           var message = eval('(' + data + ')');
           if (message.id != 0)
           {
             var row = newRow.replace("?", message.id);
             row = row.replace("?", message.id);
             row = row.replace("?", message.to);
             row = row.replace("?", message.from);
             row = row.replace("?", message.subject);
             row = row.replace("?", message.sentTime);
             $("#mailtable tbody").prepend(row);
             $("#mailtable #"+message.id).addClass("mail_unread").addClass("messageRow");
             $("#mailtable #"+message.id+ " td").addClass("mail");
             $("#mailtable :checkbox").addClass("selectable");
            }
          }
          });

切记:如果您的应用程序有多个可以相互重叠的Ajax调用,请使用Ajax Queue或Ajax Sync。

第二个示例Web应用程序

我将使用另一个小部件来解决本文中的最后三件事,在我深入研究其背后的代码之前,我想对其进行展示和解释。 这是熟悉的401K小部件,你在以前的一篇文章中看到了一个(见相关主题的链接的文章)。 但是,这次有一个细微的差别,因为我在同一页面上两次包含了小部件。 它附加到两个单独的表。 这带来了几个有趣的观点。 图3显示了小部件的外观:

图3. 401k小部件
屏幕快照显示了401k小部件的两个版本,并带有说明“输入您希望将自己的401k捐款放入的百分比分配”。在其下方是带有不同投资选择的许多行,以及一个文本输入框和一个百分号。底部是一行,显示总计和所有文本框的总和。最上面的示例显示了各种数字条目,最底端的红色显示为64,因为它应该加到100。最下面的示例显示值已更改,并且行已根据数字条目自动从高到低排序共有65个,但仍为红色。

在此小部件中,我正在做一些事情。 第一个是对文本字段求和,并确定它们是否加起来总计为100。如果它们不总计为100,我向用户显示错误指示,表明他们没有正确使用窗口小部件。 其次,在每个选择接收输入之后,我对每个选择进行排序。 通过这种方式,具有最高百分比的投资分配将始终“渗透”到表格的顶部。 您可以在图3中看到这一点,其中显示了按百分比数字排序的选择。 最后,为了使其看起来很酷,我将添加一些条纹。

产生此小部件HTML代码令人惊讶地是斯巴达式的。 清单8显示了它的全部内容。

清单8. 401k小部件HTML
<p><table width=300 class="percentSort" cellpadding=0 cellspacing=0>
<tbody>
  <tr><td>S&P 500 Index</td>
  <td><input type=text> %</td></tr>
  <tr><td>Russell 2000 Index</td>
  <td><input type=text> %</td></tr>
  <tr><td>MSCI International Index</td>
  <td><input type=text> %</td></tr>
  <tr><td>MSCI Emerging Market Index</td>
  <td><input type=text> %</td></tr>
  <tr><td>REIT Index</td>
  <td><input type=text> %</td></tr>
</tbody>
<tfoot>
</tfoot>
</table>

在jQuery中设置小部件

很少HTML内容直接进入本部分,该部分集中于在jQuery代码本身内设置窗口小部件及其所需的所有代码的想法。 当您将事件附加到事物上时,并且对于某些简单的事情(例如在某些情况下附加类),您显然已经习惯了。 但是,对于某些人来说,这又向前迈进了一步。 这些小部件的所有设置代码都将包含在jQuery代码本身中。 我可以给您提供有关角色分离的所有常见建议,让HTML设计人员完成工作,让JavaScript编码人员完成工作,但您已经听到了一百万遍了。 我将在这里再添加一件事,那就是“类装饰”的想法,许多插件作者也开始使用它。 查看清单8中HTML代码,只需将percentSort类附加到表中,就可以转换表的全部功能和外观。 这实际上是您设计的任何小部件的目标,使添加和删除小部件就像向其添加类一样简单。

让我们看一下我用来在jQuery中设置小部件的几个步骤。 通过查看这些步骤,您可以开始了解清单9中的这种设计模式。

清单9. jQuery小部件代码
$(document).ready(function() {

  // the first step is to find all the tables on the page with
  // a class of percentSort.  These are all the tables we want to
  // convert into our widget.
  // After we find them, we need to loop through them and take some
  // actions on them
  // At the conclusion of this block of code, each table that's going to
  // be a percentSort widget will have been transformed

  $("table.percentSort").each(function(i){

     // each table needs a unique ID, for namespace issues (discussed later)
     // we can simply create a uniqueID from the loop counter

     $(this).attr("id", "percentSort-"+i);

     // within each table, let's highlight every other row in the table, to
     // give it that "zebra" look

     $(this).find("tbody > tr").filter(":odd").addClass("highlight");

     // because each table needs to show the "Total" to the user, let's create a new
     // section of the table in the footer.  We'll add a row in the table footer
     // to display the words "Total" and a span for the updated count.

     $("#"+$(this).attr("id") + " tfoot")
          .append("<tr><td>Total</td><td>
          <span></span> %</td></tr>");

     // finally, let's add the CLASS of "percentTotal" to the span we just
     // created above.  We'll use this information later to display
     // the updated totals

     $("#"+$(this).attr("id") + " tfoot span").addClass("percentTotal");
  });

  // now the second step, after we've completed setting up the tables themselves
  // is to set up the individual table rows.
  // We can similarly sort through each of them, taking the appropriate actions
  // on each of them in turn.
  // Upon completion of this block of code, each row in each table will be
  // transformed for our widget

  $("table.percentSort tbody > tr").each(function(i){

     // get the namespace (to be discussed in the next section)

     var NAMESPACE = $(this).parents("table.percentSort").attr("id");

     // attach a unique ID to this row.  We can use the loop counter
     // to ensure the ID is unique on the page (which is a must on every page)

     $(this).attr("id", "row"+i);

     // now, within this row of the table, we need to find the text input, because
     // we need to attach a class to them.  We utilize the namespace, and also
     // find the :text within the table row, and then attach the correct class

     $("#"+$(this).attr("id") + " :text").addClass("percent");

     // Finally, we attach a unique ID to each of the text inputs, and we do this by
     // making it a combination of the table name and the row name.

     $("#"+$(this).attr("id") + " .percent").
               attr("id", NAMESPACE + "-" + $(this).attr("id"));
  });


  // Finally, because we know we only want numerical inputs, we restrict the text entry
  // to just numbers.  We must do this now, because up until this point, the page
  // contained no elements with the CLASS "percent"
  $(".percent").numeric();

从该示例可以看到,您确实可以在jQuery代码HTML代码中引入很多功能。 这种设计的好处应该是显而易见的,并且遵循角色分离,代码重用等原则。 您还将在小部件插件中看到这种类型的设计,因为它们采用了您看似简单HTML标记并将其转换为插件设计用于的任何小部件。 本质上,这也是您在这里所做的,编写一个插件将一个简单的表变成一个排序和求和表。

切记:在jQuery代码本身中设置尽可能多的代码,并尽可能少地使用HTML。

命名空间

使用这种类型的设计以及使用jQuery本身,最令人困惑的方面之一就是正确了解代码在其中运行的名称空间。 这就是为什么这个示例如此出色的原因,因为它以非常明显的方式提出了这个问题。 当您知道页面上的每个ID和类时,编写jQuery代码可能非常简单明了。 毕竟这就是它的设计目的。 当您不确定页面上有多少个类,或者它们开始相互重叠时,会发生什么? 在此示例中,您可以立即看到此问题。 有两个完全相同的小部件! 一切都是重叠的。 看起来,当您不考虑名称空间问题时会发生什么。 您的小部件开始相互干扰,最终根本无法正常工作。

图4.忽略名称空间问题
屏幕快照显示了401k小部件的两个版本,并带有说明“输入您希望将自己的401k捐款放入的百分比分配”。在其下方是带有不同投资选择的许多行,以及一个文本输入框和一个百分号。底部是一行,显示总计和所有文本框的总和。顶部的示例显示了两个数字条目,底部的总计为22,红色显示为红色,因为它应加到100。底部的示例显示所有文本框均已清除,但总数仍显示为22,仍然为红色。

发生这种情况是因为您只是在调用$(".percentTotal")类的代码时就忽略了应该在错误代码中专门更新哪个窗口小部件。 因为您在同一页面上有多个表,所以页面上将有percentTotal类的多个实例。 是的,如果页面上只有这些表之一,则可以认为该表仅存在一次。 但是,随着页面变得更加高级,并且窗口小部件变得更加可重用,应该将这种假设抛诸脑后。 有人可能会问:“为什么不在这里使用ID?” 那不会解决问题:毕竟,您会给它提供什么ID? 您不能使用“ percentTotal”,因为那样会造成歧义。 您不能使用“ percentTotal-1”,因为那实际上并不意味着页面上的任何内容。 (毕竟,这些数字都是由您随意创建的。)您可以在其中包含的表上附加一些引用,例如“ percentTotal-percentSort1”,这将是一种解决方案,但这会使事情变得过于复杂。 jQuery具有非常复杂且非常易于使用的选择语法,因此不需要这些类型的混合命名方案。 为什么在这里重新制作轮子? 让我们使用jQuery的选择引擎为您解决名称空间问题。

通常,在此小部件中,问题的核心是确定操作发生在哪个小部件中。当您在一个文本字段中输入数字时,请问问自己,jQuery如何知道文本输入到哪个文本字段? 您当然可以在代码中将事件附加到“百分比”类上,并且可以在代码内使用$(this)引用该事件。 这就引出了下一个问题:jQuery如何知道它发生在哪个窗口小部件中,因此您可以更新适当的percentTotal字段? 嗯.....我想不是,至少不容易。 那就对了。 虽然您的代码很优雅,但是您可以在页面上以“百分比”类将事件附加到每个文本字段,如果您仅忽略事件发生所在的包含窗口小部件,这是不明智的。

之所以将此问题称为命名空间问题,是因为您对小部件的命名不明确,这可能会导致问题。 为了使jQuery代码正常工作,每个名称都必须在其自己的空间中明确定义,因此需要使用名称空间。 您必须编写避免名称重叠的代码,以便每个小部件都可以独立存在。 您应该能够在同一页面上添加同一窗口小部件的多个实例,而无需重叠任何名称。 本质上,每个小部件都必须独立放置在页面上。

没有解决该命名空间问题的正确方法,因此,我将介绍我的解决方案,您可以在自己的代码中使用该解决方案,也可以阅读该问题并创建自己的更好的解决方案。 我喜欢此代码的原因是因为它使用简单(仅1行),并且使您可以控制自己的名称空间。 看一下清单10。

清单10.命名空间解决方案
// our event is attached to EVERY input text field with a CLASS of "percent"
// this makes our code look good, but can lead to namespace issues
$("table.percentSort input.percent").keyup(function(){

   // this simple line can establish a namespace for us, by getting the unique
   // ID attached to our table (the table is considered the "container" for
   // our widget.  It could be anything, depending on your specific code.)
   // We pass the CLASS of our widget to the parents() function, because
   // that effectively encapsulates the widget

   var NAMESPACE = "#" + $(this).parents("table.percentSort").attr("id");

   // with the namespace established, we can use the jQuery selection
   // syntax to use this namespace as our prefix for all of our remaining
   // searches.  Notice how the ambiguity is removed for our search
   // by CLASS of "percent" and "percentTotal"
   // This solves our namespace issues

   var sum = $(NAMESPACE + " input.percent").sum();
   var totalField = $(NAMESPACE + " .percentTotal");

因此,只需添加一行代码,就可以封装小部件并防止其与其他小部件实例(甚至是不幸的是,对于ID或类使用相同名称的其他小部件)重叠功能(通常是错误地) )。 这种类型的编码在插件代码中非常常见。 编写良好的插件时会考虑到名称空间问题,而您会发现编写不良的插件将忽略它们。 如本例所示,在您自己的代码中使用它相对简单,如果页面变得更加复杂,它可以节省大量时间。 出于这个原因,我建议您立即开始考虑名称空间问题的jQuery代码,并将此解决方案用于所有自己的编码。

切记:启动自己的jQuery代码时,请始终从包含的名称空间解决方案开始。 您可以使用上面的解决方案,也可以创建自己的解决方案。 这将使您的代码变得越来越复杂,而不会成为问题。

1.3新增功能

在本文的最后一节中,我想介绍jQuery 1.3版本中引入的新功能。 就性能而言,1.3版本是一个很大的版本,仅出于这个原因,您应该在自己的代码中升级到此版本级别。 但是,对核心代码进行了一些小的补充,可以帮助您改进自己的代码。

1.3内核的第一个附加功能是我在本文中讨论过的live() / die()函数。 正如您所知,这些可能是最重要的补充,因为它们赢得了本文的整个章节。 1.3核心的另一个主要添加是jQuery.Event类,该类将在页面上发生的事件封装在Object中。 这对于事件密集型应用程序非常有益,因为它提供了一个包含良好的对象,可以中继您需要的有关事件的所有信息。 信息,例如类型,目标,X和Y坐标,甚至是时间戳。 该信息可能在1.3之前可用,但没有得到足够的文档记录,当然也没有很好地封装。 最后,1.3版本的最后一个功能对开发人员来说是透明的,但是仍然值得注意。 在此版本中,不再存在浏览器嗅探,其中存在针对浏览器或版本的特定if语句。 您可以想象意大利面代码在处理它必须支持的所有浏览器时使用。 这也给每个jQuery版本增加了一定程度的衰减,因为浏览器总是会进入和退出使用状态。 相反,它们在与浏览器类型/版本无关的同时检测浏览器中的功能。 这意味着随着新浏览器的创建,旧浏览器的消失,不再需要更新jQuery版本。 适用于不想每年升级其jQuery版本以及所需测试的网站。

结论

这结束了本文的结尾,为您提供了一些有关如何将优质jQuery代码变成优质jQuery代码的提示。 jQuery非常易于使用(并且对独立JavaScript进行了这样的改进),因此编写良好的jQuery代码非常容易。 大多数开发人员可以在几分钟内启动并运行。 但是,编写好的代码和好的代码是有区别的。 随着页面复杂度的提高,出色的jQuery代码会关注性能。 很棒的jQuery代码会考虑页面的前进方向,而不是现在的位置,并针对该期望进行编码。 很棒的jQuery代码是为可能的最复杂的应用程序设计的,然后轻松地处理您向它抛出的简单内容。

本文向您介绍了5个概念,这些概念可以帮助您的优秀jQuery代码成为出色的jQuery代码。 第一个概念是使用bind() / unbind()方法。 当您不希望将事件附加到页面生命周期的代码中时,这些方法在将事件附加/分离到页面元素上非常有用。 这在性能情况下很重要,在这种情况下,事件可能会在整个页面中波动,或者可以在某些用户界面情况下使用。 第二个概念是1.3中新live() / die()功能的用法。 这些功能使您的事件是动态的,就像页面元素一样。 随着页面元素被添加到您的Web应用程序中,这些功能使您的代码可以随页面一起增长,而在此版本之前是不可能的。 您希望事件处理与页面一样动态。 第三个附加功能是Ajax Queue / Sync插件,该插件可用于控制和控制您对服务器的Ajax调用,以防它们可能失去控制(从客户端的角度来看)以及它们的顺序。返回很重要。 第四个建议是在jQuery代码中编写尽可能多的页面设置代码。 这使您HTML编写起来更简单,并且在设置页面时为您提供了更多功能。 最后,最后一步是在代码中利用名称空间解决方案(我的或您自己的),以防止小部件重叠功能并在页面上引起错误。 每个页面元素和小部件都应该是独立的,并且不会干扰页面的其他方面,并且此解决方案可以防止这种情况。

这五个花絮绝非难事。 实际上,对于其中的4个,它就像更改一行代码一样简单。 但是,了解如何在您的代码中使用这些解决方案很重要。 像其他所有内容一样,如果使用不当,它们将对您的代码无济于事,甚至可能会伤害您的代码。 我的建议是在页面上开始对jQuery进行编码后立即开始使用这5件事。 就像每个开发人员都可以告诉您的那样,功能爬坡是我们生活的标准组成部分。 您不需要重新设计整个Web应用程序,因为一开始您的决策很差,或者由于经理的要求而被迫更改某些东西。 在编写代码时,请牢记一个出色的应用程序,并使用这些建议将您带到那里。

最后,这结束了我的jQuery系列文章的第二个周期。 这最后5篇文章使您提高了jQuery熟练程度,到现在,您应该已经可以使用该库创建任何类型的应用程序。 我的最终建议是只是暂时使用该代码并进行试验。 您不仅可以学到很多东西,还可以在网络上创建下一个有趣的东西!


翻译自: https://www.ibm.com/developerworks/web/library/wa-aj-advjquery2/index.html

06 jquery进阶

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值