前端事件系统(二)

本章将把重点放在于对于事件的委托机制,以及jquery的事件绑定方法作一些解析。本章并无什么比较难懂的地方,也尚未深刻到jQuery的事件系统内部。前端


事件委托

上一章讲了前端事件系统以及简单地对各个浏览器进行兼容的方法。对于要求不高的页面来讲,以前的简单事件注册,就能够很好的胜任各类各样的工做了。可是,试想一种状况。假若一个页面有着极大量的事件绑定的需求,那么咱们以前的事件系统,就不得不一个个的去绑定事件。这样对性能来讲,确定是一种灾难,同时,动态增长的节点没法完成绑定的工做。所以,咱们须要引入事件委托这一机制。jquery

冒泡与捕获

咱们知道dom的事件处理,分为捕获阶段,目标阶段,以及冒泡阶段三个部分。那么简单地讲一下这三个阶段吧,当咱们点击了一个a标签的时候,整个事件的流程大体是下面的阶段api

首先事件从dom树向下传送,逐个访问目标节点的祖先节点,同时将会对该事件的捕获事件监听器来进行检测,并执行,直到访问到目标节点,这一阶段就是咱们说的捕获阶段;到达目标节点(即a标签)后,就会执行该事件监听器,这一阶段也就是目标节点;最后事件将会从目标节点开始,从dom树往上传送,再依次访问目标节点的祖先节点,而且执行对应的非捕获事件的事件监听器,而且执行浏览器

委托的原理

既然有了冒泡和捕获的概念,那么事件委托的原理也很好理解了。事件委托利用了事件能够传播的这一特性,并不使用事件自己对于事件来进行处理,而是将对事件的处理任务交予了其祖先节点来进行处理。dom

这样作,减小了对于页面上的dom操做。好比你对ul下的li绑定事件,经过事件委托,你只须要对于ul绑定一次事件,而后使用事件传播的这一特性,li的事件来进行工做,这样,极大地减小了绑定量,并且即便是动态增长的li节点,也一样是能够去执行该事件的。函数


jQuery的事件绑定

那么终于来到了jQuery的部分。从这里开始也将对jQuery的事件部分,尽我的所能来作一个解析,以后出现jQuery的源码的版本为2.1.4,解析过程当中有不对的地方,欢迎打脸。性能

jQuery的事件绑定,有如下几种方法:学习

  • 直接用click,blur等事件名的方法
  • bind方法
  • delegate
  • live方法
  • one方法
  • on方法

那么咱们对上面几种方法来一一分析(本章暂不会对做为核心的on的源码来进行分析)this

  1. 直接用事件名进行事件绑定翻译

    便是直接采用相似.click(),.blur()的方式进行绑定

    那么jQuery中是如何作到的呢

    jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
        "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
        "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
    
        // Handle event binding
        jQuery.fn[ name ] = function( data, fn ) {
            return arguments.length > 0 ?
                this.on( name, null, data, fn ) :
                this.trigger( name );
        };
    });

    jQuery的实现很简单,将事件直接经过each方法加入jQuery.fn上,而后在内部根据参数的不一样直接对于jQuery的on或者trigger方法进行调用。

  2. bind方法

    bind方法用于为一个元素绑定一个事件处理程序

    先来看看jQuery中的实现吧

    bind: function( types, data, fn ) {
        return this.on( types, null, data, fn );
    }
  3. live方法

    live方法拿到前面来讲。这是jQuery如今已经不支持的方法。对于1.4.3以上的版本,推荐采delgate方法来,而对于1.7以上的版本,则推荐采用on方法来进行替代。具体采用live方法有什么弊端,jQuery的文档之中已经阐述的很是明白了,至于为何会出现这个问题,本着刻苦求知的精神……我还并无去看,附上翻译后的文档吧

    由于更高版本的jQuery提供了更好的方法,没有.live()方法的缺点,因此.live()方法再也不推荐使用。特别是,使用.live()出现的如下问题:

    • 在调用 .live() 方法以前,jQuery 会先获取与指定的选择器匹配的元素,这一点对于大型文档来讲是很花费时间的。
    • 不支持链式写法。例如,$("a").find(".offsite, .external").live( ... ); 这样的写法是不合法的,并不能像期待的那样起做用。
    • 因为全部的 .live() 事件被添加到 document 元素上,因此在事件被处理以前,可能会经过最长最慢的那条路径以后才能被触发。
    • 在移动 iOS (iPhone, iPad 和 iPod Touch) 上,对于大多数元素而言,click 事件不会冒泡到文档 body 上,而且若是不知足以下状况之一,就不能和 .live() 方法一块儿使用:
      • 使用原生的可被点击的元素,例如, a 或 button,由于这两个元素能够冒泡到 document。
      • 在 document.body 内的元素使用 .on() 或 .delegate() 进行绑定,由于移动 iOS 只有在 body 内才能进行冒泡。
      • 须要 click 冒泡到元素上才能应用的 CSS 样式 cursor:pointer (或者是父元素包含 document.documentElement)。可是依需注意的是,这样会禁止元素上的复制/粘贴功能,而且当点击元素时,会致使该元素被高亮显示。
    • 在事件处理中调用 event.stopPropagation() 来阻止事件处理被添加到 document 以后的节点中,是效率很低的。由于事件已经被传播到 document 上。
    • .live() 方法与其它事件方法的相互影响是会使人感到惊讶的。例如,$(document).unbind("click") 会移除全部经过 .live() 添加的 click 事件!

    源文档

  4. delegate方法

    delegate方法也就是咱们以前所提到的事件委托了。由于基于live以前的不少问题,jQuery在live以后的版本中增长了delgate方法(现在已经被on所取代)

    来看看如今的delegate是如何实现的吧

    delegate: function( selector, types, data, fn ) {
        return this.on( types, selector, data, fn );
    }
  5. one方法

    为元素添加事件。而且在元素上的事件只能够执行一次

    具体实现

    one: function( types, selector, data, fn ) {
        return this.on( types, selector, data, fn, 1 );
    }
  6. on方法

    on方法在这里不打算对源码进行阅读,由于能够看到,上面的全部方法都是对于on方法的调用。所以jQuery的事件系统,核心就在于on方法了。所以jQuery的on方法将在后面进行分析,而这里,只是对于on接口自己的一些说明。

    on方法提供了绑定事件全部的功能。其API是这样的

    .on( events [, selector ] [, data ], handler(eventObject) )

    其实最后还有一个one参数,假若传入了1,那么这个事件也就只执行一次,而实现的原理其实也就是使用off来解绑事件进行的操做了。

    而后来看下别的参数分别是作些什么的吧

    events:
    类型: String
    一个或多个空格分隔的事件类型和可选的命名空间,或仅仅是命名空间,好比"click", "keydown.myPlugin", 或者 ".myPlugin"。
    selector:
    类型: String
    一个选择器字符串,用于过滤出被选中的元素中能触发事件的后代元素。若是选择器是 null 或者忽略了该选择器,那么被选中的元素老是能触发事件。
    data:
    类型: Anything
    当一个事件被触发时,要传递给事件处理函数的event.data。
    handler(eventObject)
    类型: Function()
    事件被触发时,执行的函数。若该函数只是要执行return false的话,那么该参数位置能够直接简写成 false。

    所以再来对于前面五种方法来进行统一的分析。

    直接用事件名进行事件绑定的方法与bind的方法,直接对于selector参数赋值为了null,所以,对于采用这两种方法进行的事件绑定,其实自己是没有使用事件委托的,便是说并无冒泡的过程,所以,采用这种方法的绑定对性能会有必定的损耗。

    而delegate方法,传入了selector参数,所以,至关于也就是直接用on来实现的事件委托。

    one方法以前也讲了,因此再也不多说。


总结一下这章所讲的内容吧。本章对于事件绑定的几种方法(除on外),都进行了简单地讲解。与其说是对于jQuery源码的分析,倒不如说其实就是个简单地,对于jQuery使用的建议吧。jQuery绑定的核心仍是落在on方法上,同时,jQuery的事件系统的思想能够说是极为经典的。在下一章,咱们将对jQuery的事件系统进行更深刻一些的分析(在我捉急的水平范围以内)。第三章估计要难产了,我必定会努力作完这个系列的,也算是对我的前端学习的一点鞭策吧。

相关文章
相关标签/搜索