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

  • 相关阅读:
    数组塌陷现象
    深浅拷贝的区别
    冒泡排序,选择排序的应用
    JavaScript双重循环的嵌套
    Css Grid网格布局
    css3动画详细介绍
    Python tkinter Label Widget relief upload image
    XXXFD
    XXX1
    Python爬取一个简单网页的HTML代码
  • 原文地址:https://www.cnblogs.com/observernotes/p/4832011.html
Copyright © 2011-2022 走看看