jQuery事件编写进阶

标签: 前端开发 jQuery事件进阶 jQuery基础教程 jQuery高级事件 | 发表时间:2013-02-28 18:57 | 作者:tiegen.zhutg
出处:http://www.aliued.cn

jQuery 事件编程进阶

事件委托,是一种优化DOM元素事件绑定的技巧,利用事件冒泡的原理,通过绑定事件到父元素,检查event触发元素的target,最终执行相应的事件函数处理,它的几个好处一般前端开发程序员都知道。在jQuery中,一般是delegate()方法和.live()方法,但是,如何选择事件委托的方法,或者在什么情况下用.live(),什么情况下用.delegate(),这个值得讲一讲:

live: function( types, data, fn ) {
      jQuery( this.context ).on( types, this.selector, data, fn );
      return this;
    }
delegate: function( selector, types, data, fn ) {
      return this.on( types, selector, data, fn );
}

查看这2个事件委托的源代码可知,live方法中,有个元素的执行环境,这个执行环境默认是document,所以,如果把live事件委托写在$(document).ready(function() {})之外,也是没有问题的。live()在某种情况下会引起性能问题,这主要包括2个方面:1.live()方法虽然避免了绑定事件处理到很多DOM元素,但是,它在一开始选择了文档中的所有元素,如果一个文档有很多的子节点,比如文档中的一个表有几十列,几百行表内容,而事件要绑定到这个表的某一行某一列,那么,live()方法在一开始选择这个表的所有行,所有列的时候,就是一个非常大的性能消耗,会导致脚本反应很迟钝。2.因为live()是绑定到document上面,所以会有大量的事件冒泡,事件冒泡要从嵌套最深的DOM元素往上一直冒到document上面,这样长路径的事件冒泡也是一个很昂贵的性能消耗。而采用.delegate(),事件绑定到$()函数的选择表达式元素上,因此页面的事件注册更加清晰,而事件冒泡更少。

由于初始化元素的选择和过度的事件冒泡,开发者们一般倾向于.delegate()方法,而摈弃.live()方法。但是,live()方法还是有其可用之处的,如果我们明智的使用它,过早的调用或者传递一个执行环境给它(即设置它的context),live()就会趋利避害,发挥它的优势所在。其中一个改善live()性能的方法是把live()移出$(document).ready()之外,加入live()事件注册的脚本是放在<head>结束标签之前,那么live()选择元素的工作就会非常少,因为那时,整个DOM还没有被加载注册,但document,这个live()的执行环境,却已经可用了。

(function($) {
   $('div.photo').live('mouseenter mouseleave',
    function(event) {
      var $details = $(this).find('.details');
      if (event.type == 'mouseenter') {
        $details.fadeTo('fast', 0.7);
       } else {
     $details.fadeOut('fast');
    }
});
})(jQuery);

由于我们不必等待整个DOM加载完毕,我们就可以立即确定mouseenter 和mouseleave 的事件行为将应用到<div>元素集上面,只要该元素集在页面中一被渲染显示就会起作用了。要理解这种事件注册技术的好处,我们可以想像一下要绑定一个事件处理函数来阻止一个链接元素的单击(click) 默认行为。如果我们直到整个DOM已经ready时,才绑定click事件注册函数,那我们就要冒着在click事件注册到那个链接元素之前,用户点击这个链接元素,从而导致浏览器离开当前页面,而没有采用ajax方式实现页面的无刷新来更新内容。Live()在早期注册,我们就有了事件早早绑定,却避免扫描整个DOM结构导致的性能消耗的好处。另一个使用.live()的技术是给它提供一个执行环境(context),类似于.delegate(),以此来减少事件冒泡。比如(‘div.photo’).live就改成$(‘div.photo’, $(‘#gallery’)[0]).live,这样的话,类似于.delegate(),$(‘div.photo’, $(‘#gallery’)[0]).live必须放在$(document).ready()函数里面,但这样也就失去了早期注册的那些好处。

在jQuery 1.9版本中,已经取消了live方法,但是这种在DOM加载早期,通过document事件委托绑定具体事件处理函数,避免jQuery扫描整个DOM结构导致的性能开销的编程思想确实有借鉴意义的。在jQuery 1.9中,上面用live的事件委托代码可以改写成:

(function($) {
   $(document).on('mouseenter mouseleave','div.photo'
    function(event) {
      var $details = $(this).find('.details');
      if (event.type == 'mouseenter') {
        $details.fadeTo('fast', 0.7);
       } else {
     $details.fadeOut('fast');
    }
});
})(jQuery);

如果把这段代码放在head结束标签之前,这样就不必等整个DOM加载完毕,通过document事件委托事先进行针对div.photo元素的处理的事件绑定,避免jQuery扫描整个DOM结构的性能开销。当然,div.photo元素最好是body标签的直接子元素,这样就可以减少事件冒泡的过程,如果div.photo在body下面嵌套比较深,则应该权衡一下是否在$(document).ready()采用delegate方法代替。

jQuery的特殊事件

jQuery的自定义事件,功能很强大,但是特殊事件跟自定义事件的结合使用,可以在框架层面来解决一些代码编写方面的问题,类似于java中的AOP切面编程。 延迟事件执行,我们来看下面一段代码:

$(document).ready(function() {
  var timer = 0;
  $window.scroll(function() {
   if (!timer) {
   timer = setTimeout(function() {
   checkScrollPosition();
   timer = 0;
   }, 250);
  }
  }).scroll();
});

这里给窗体滚动事件添加处理函数,这个处理函数在窗体滚动时每次延迟250毫秒执行。如果不加延迟,浏览器哪怕滚动一个像素,都会触发checkScrollPosition()函数的调用,浏览器反复调用checkScrollPosition()函数,可能会引起性能方面的问题而导致浏览器进入“假死状态”,常见的窗体类似事件有scroll, resize, 和 mousemove,给这些窗体事件添加处理函数,希望都能添加延迟代码,使事件延迟执行,减少函数调用次数,从而提升用户体验,给用户比较平滑的浏览器效果体验。通过jQuery的特殊事件和自定义事件的结合,我们能够优化上面的事件延迟代码,从而移除事件注册中的setTimeout()函数,类似于java中的切面编程。这样事件绑定中只要直接调用checkScrollPosition()方法,不再需要在外面再包装setTimeout函数。请看以下示例:

(function($) {
$.event.special.throttledScroll = {
  setup: function(data) {
   var timer = 0;
   $(this).bind('scroll.throttledScroll', function(event) {
    if (!timer) {
    timer = setTimeout(function() {
     $(this).triggerHandler('throttledScroll');
     timer = 0;
     }, 250);
    }
   });
  },
  teardown: function() {
   $(this).unbind('scroll.throttledScroll');
  }
 };
})(jQuery);
$(document).ready(function() {
   $window.bind('throttledScroll', checkScrollPosition).trigger('throttledScroll');
});

这样最大程度的简化了事件绑定的代码,并且给了我们一个良好的可复用的事件延迟机制。因为除了窗体可以绑定throttledScroll事件,页面中有滚动条的其他div元素也可以绑定throttledScroll事件,而事件延迟写在$.event.special.throttledScroll的setup函数里面,这样DOM只选要关心具体事件处理函数的实现,不需要再手动添加延迟代码来改善性能。这样编写代码,结构良好,代码更清晰易懂,复用性也高。

相关 [jquery 事件] 推荐:

Jquery手动触发事件

- - 博客园_首页
    废话不多说,直接贴代码:.     如果想触发一个id为input的文本框的blur事件,则可以这样写:.     相类似,如果想调用input的click事件,则可以这样写:.

jQuery事件编写进阶

- - 阿里巴巴(中国站)用户体验设计部博客
jQuery 事件编程进阶. 事件委托,是一种优化DOM元素事件绑定的技巧,利用事件冒泡的原理,通过绑定事件到父元素,检查event触发元素的target,最终执行相应的事件函数处理,它的几个好处一般前端开发程序员都知道. 在jQuery中,一般是delegate()方法和.live()方法,但是,如何选择事件委托的方法,或者在什么情况下用.live(),什么情况下用.delegate(),这个值得讲一讲:.

jQuery代码优化:基本事件篇

- - 可咔酷 | 网络杂货铺
jQuery对事件系统的抽象与优化也是它的一大特色. 本文仅从事件系统入手,简要分析一下jQuery为什么提供mouseenter和mouseleave事件,它们与标准的mouseover、mouseout事件有什么区别. 说到事件,就要追溯到网景与微软的“浏览器大战”了. 当时,事件模型还没有标准,两家公司的实现就是事实标准.

jQuery - 中文輸入法與KeyDown/KeyPress事件

- 晓刚 - 黑暗執行緒
最近專案中引用了Telerik ASP.NET擴充元件AutoComplete輸入欄位,測試時發現偶爾會不聽始喚,輸入文字時無法觸發資料查詢,在Javascript Source Code裡反覆追蹤測試,燃燒了可觀的寶貴春青,終於理出頭緒: 問題在中文輸入法!. 過去模糊地知道中文輸入在瀏覽器的鍵盤事件行為上有些特殊,但從未深究,這回算是比較清楚研究其中的差別.

jQuery捕获超链接事件进行局部刷新

- - Xiaoxia[PG]
使用Google的UI的时候,在当前页面打开一个超链接,网页会根据需要进行局部刷新,而不是替换整个页面. 当用户选择新窗口打开超链接的时候,超链接仍然可以到达预想的页面. /* 点击事件会在超链接跳转前发生 */. 这只是我用jQuery做的一个测试,不知道Google是怎么实现的. 例如,当点击一个超链接事件之后,页面通过iframe来进行局部刷新.

GA小技巧:使用jQuery来方便的布置事件跟踪代码

- - 标点符
Google Analytics的事件跟踪是个神器,基本上你能想到什么他就能帮你做什么. 但是按照Google Analytics的帮助文章中方法去布置可能会让你觉得麻烦. 以下为我使用的小技巧分享给大家. 如果你需要跟踪某几个链接在页面上的点击数. 事先给需要记录的点击链接上添加一个类. 跟踪地址.

10个用来处理键盘事件的JQuery插件和JS类库

- - JavaScript - Web前端 - ITeye博客
通常在web应用或者网站中,我们使用鼠标来控制元素或者执行导航,相对于桌面应用来说,使用web应用的快捷键次数可能会相对比较少,但是对于熟 练的专业人员来说,使用键盘可能更加容易并且更加快速,在今天这篇文章中,我们收集了10个jQuery的插件,帮助你创建各种基于键盘事件的web应 用,相信大家会喜欢的.

JQuery 选择器

- - CSDN博客Web前端推荐文章
}

点击我

.    像上面这样把JavaSript代码和HTML代码混杂在一起的做法同样也非常不妥,因为它并没有将网页内容和行为分离,所以才有JQuery选择器的学习.

点击我

. //给class为demo的元素添加行为.

jquery操作xml

- - CSDN博客Web前端推荐文章
jquery真的很强大,虽然一直在用jquery,不用一直都没有深入,这几天重新学习了一下,不得不感叹她的强大,已经让我深深入迷. 这里记录一下,她是怎么快速地操作xml的.. 这里我们有一个xml文件:. jquery如何操作呢,总的思想,就是和操作dom差不多的方法. 首先我们获取这个文件的内容:(我先引入jquery库哈).

jQuery JSONP跨域

- - Web前端 - ITeye博客
基于Jquery的Ajax跨域访问. 单点登录服务器(sso服务器). 登录网页项目的时候,由于使用了单点登录,所以页面会跳转到sso服务器,进行统一登录,. 现在需要在该界面增加令牌的认证,但是SSO服务器和令牌服务器部署在不同的服务器,且暂时没有要合并的可能,所以在SSO登录的时候必须要对令牌进行验证,就必须涉及到了跨域访问的问题.