jQuery事件编写进阶

来源:互联网 发布:学生开淘宝店怎么样 编辑:程序博客网 时间:2024/05/16 09:48

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只选要关心具体事件处理函数的实现,不需要再手动添加延迟代码来改善性能。这样编写代码,结构良好,代码更清晰易懂,复用性也高。

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 和上司暧昧被同事发现怎么办 减肥不吃晚餐饿了怎么办 小孩晚饭吃多了怎么办 减肥晚上不吃饭饿了怎么办 两个人在一起性格不合怎么办 赌在你身上输了怎么办 苹果7lcould满了怎么办 e招贷不用了怎么办 牙活动了怎么办还疼 30岁掉了一颗牙怎么办? 在淘宝上交话费交错了怎么办 演出队在小区旁边扰民怎么办 雷雨天加了油怎么办 戴ok镜眼睛重影怎么办 乌龟背上长白色的花纹怎么办? 全自动洗衣机里面掉个硬币怎么办 跆拳道课上孩子乱动说话怎么办? 孩子不愿意上跆拳道课了怎么办 车座位里面倒了汤怎么办 腿被棍子打肿了怎么办 刚买的手机碎屏怎么办 被木棍么么打到头项怎么办 大王卡用到40g怎么办 王卡40g用完了怎么办 父亲把母亲打成重伤怎么办 狗狗脖子摔歪了怎么办 吃鸡游戏中重伤怎么办 吃鸡游戏摔伤了怎么办 现在没能力偿还网贷怎么办 上海找夜场工作被骗了怎么办? 买了烂尾的楼盘怎么办 孕七个月蛀牙疼怎么办 宝宝只吃一边奶怎么办 实房付了定金后悔了怎么办 开车时遇到意外事故时怎么办 没干过影楼门市怎么办 uplay下载游戏速度0k怎么办 缓刑期间被别人打成轻伤怎么办 缓刑期间被别人打了怎么办 有缓刑被别人打怎么办 检察院不予立案怎么办公安局取保