zoukankan      html  css  js  c++  java
  • 前端事件系统(二)

    本章将把重点放在于对于事件的委托机制,以及jquery的事件绑定方法做一些解析。本章并没有什么比较难懂的地方,也还没有深入到jQuery的事件系统内部。


    事件委托

    上一章讲了前端事件系统以及简单地对各个浏览器进行兼容的方法。对于要求不高的页面来说,之前的简单事件注册,就可以很好的胜任各种各样的工作了。但是,试想一种情况。倘若一个页面有着极大量的事件绑定的需求,那么我们之前的事件系统,就不得不一个个的去绑定事件。这样对性能来说,肯定是一种灾难,同时,动态增加的节点无法完成绑定的工作。因此,我们需要引入事件委托这一机制。

    冒泡与捕获

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

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

    委托的原理

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

    这样做,减少了对于页面上的dom操作。比如你对ul下的li绑定事件,通过事件委托,你只需要对于ul绑定一次事件,然后使用事件传播的这一特性,li的事件来进行工作,这样,极大地减少了绑定量,而且即使是动态增加的li节点,也同样是可以去执行该事件的。


    jQuery的事件绑定

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

    jQuery的事件绑定,有以下几种方法:

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

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

    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的事件系统进行更深入一些的分析(在我捉急的水平范围之内)。第三章估计要难产了,我一定会努力做完这个系列的,也算是对个人前端学习的一点鞭策吧。

  • 相关阅读:
    poj 3616 Milking Time
    poj 3176 Cow Bowling
    poj 2229 Sumsets
    poj 2385 Apple Catching
    poj 3280 Cheapest Palindrome
    hdu 1530 Maximum Clique
    hdu 1102 Constructing Roads
    codeforces 592B The Monster and the Squirrel
    CDOJ 1221 Ancient Go
    hdu 1151 Air Raid(二分图最小路径覆盖)
  • 原文地址:https://www.cnblogs.com/observernotes/p/4832011.html
Copyright © 2011-2022 走看看