jQuery技术

捕获与冒泡

字号+ 作者:H5之家 来源:H5之家 2015-11-24 15:07 我要评论( )

本文中的JavaScript事件是指:在浏览器中,DOM标准提供的JavaScript事件集与接口集。 在项目开发中通常会使用类似jQuery的工具来绑定事件处理函数, 也可以设置

向作者提问

DOM Level 2 Event与jQuery源码:捕获与冒泡 0 0

本文中的JavaScript事件是指:在浏览器中,DOM标准提供的JavaScript事件集与接口集。

在项目开发中通常会使用类似jQuery的工具来绑定事件处理函数, 也可以设置捕获,或者中断事件流,正如这篇文章锁讨论的:jQuery事件:bind、delegate、on的行为与性能。 本文来讨论DOM标准中是如何规定这些JavaScript事件的,以及jQuery源码中DOM事件的实现方式。

JavaScript 事件

首先我们来回顾一下DOM事件的行为,事件从发生开始经历了三个阶段:

如何中断事件传播,以及禁止事件发生时的浏览器默认行为,参考:jQuery事件:bind、delegate、on的行为与性能

图片来源:

DOM标准中,定义了一系列的JavaScript事件,以及事件接口。其中,DOM Level 0 Event提供了类似onclick的属性来支持事件, DOM Level 2 Event提供了addEventListener, removeEventListener, dispatchEvent,还有IE<9的attachEvent。

两种事件处理模型的区别在于,

  • 前者(onclick)是一次性的事件处理,而且是通过操作DOM元素的属性来完成,因而只能绑定一个处理函数。
  • 后者(addEventListener)更加高级,不仅可以添加多个事件处理函数,还支持事件的捕获。
  • DOM Level 0 Event

    DOM Level 0 Event从Netscape浏览器开始就有支持,最初是通过在HTML中写入onclick属性来完成事件绑定:

    后来随着Web技术的进步,我们可以在JavaScript定义并且绑定事件了。此后我们可以做到事件处理和页面展示的分离, 在不支持JavaScript的浏览器中,以及搜索引擎看来,页面变得更加地兼容。请看:

    即时支持在JS中绑定事件,DOM Level 0 事件也存在一些问题。例如:

    是因为el.onclick的本质是对DOM元素属性的赋值,后一次时间绑定会使得前一次事件绑定失效。

    addEventListener

    2000年11月,W3C发布了DOM (Document Object Model) Level 2 Event,提供了更复杂的事件处理模型:

    在版本小于9的IE中,通过attachEvent来添加事件处理函数。然而从IE11开始,attachEvent已经不受支持,天煞的IE啊:

    MSDN attachEvent: AttachEvent is no longer supported. Starting with Internet Explorer 11, use addEventListener.

    通过addEventListener添加任意多个事件处理函数,第三个参数用来设置是否捕获(请看下一节)来自子元素的事件,默认为false。

    这样,两个事件处理函数都会得到执行。

    removeEventListener

    DOM Level 2 Event还提供了removeEventListener(type, listener[, useCapture])方法,用来移除事件处理函数。callback是必选参数!capture默认值为false:

    如果同一个监听事件分别为“事件捕获”和“事件冒泡”注册了一次,一共两次,这两次事件需要分别移除。两者不会互相干扰。

    捕获与冒泡

    本文最开始已经给出了事件处理的三个阶段:捕获、目标、冒泡。在DOM Level 2 Event中, 如果addEventListener第三个参数为true则为添加捕获阶段的事件处理函数,否则为添加冒泡阶段的事件处理函数。

    如果当前对象就是目标对象本身时,添加的事件处理函数只在目标阶段起作用,第三个参数无效。

    来看例子吧:

    为元素l1添加了一个捕获阶段的处理函数l1 captured,一个冒泡阶段的处理函数l1 bubbling。为l2添加了一个目标阶段的事件处理函数。 运行结果是:

    l1 capture l2 target l2 target, invalid capture l1 bubbling

    其中,l2 target, invalid capture设置了捕获,但因为当前对象就是目标对象,捕获无效。该函数仍然作用于目标阶段。 既然捕获失效,那么它的执行顺序就按照注册事件的顺序了,不会因为它设置了无效的捕获而提前得到执行。

    DispatchEvent

    target.DispatchEvent(event)也是DOM Level 2 Event提供的方法。用来从target开始分发事件event。 例如,我们可以创建一个clickDOM事件:

    会产生与点击完全相同的输出:

    l1 capture l2 target l2 target, invalid capture l1 bubbling

    如果用l1来dispatchEvent会怎样?

    l1 capture l1 bubbling

    因为l1确实拥有子元素,所以事件仍然会下行和冒泡。但事件的target并非l2,所以l2不会触发目标阶段的事件处理函数。

    jQuery Event 源码

    好了好了,DOM Level 2 Event的事件处理模型算是清楚了,在DOM Level 3 Event的Working Draft中, 仍然沿袭了三阶段的事件处理流程。接着我们来看jQuery的那些事件处理函数是怎样实现的。

    我们知道,jQuery中的bind, delegate, live等最终都是通过.on()来实现的。来看它的声明:

    这个selector是在当前元素的上下文中查找的,见jquery-2.1-stable/src/event.js第434行: jQuery( sel, this ).index( cur ) >= 0。

    on方法定义在jquery-2.1-stable/src/event.js中(766行), 最终调用addEventListener方法(122行)来添加事件处理函数:

    在2.1版本中已经找不到attachEvent方法了,jQuery放弃了版本<9的IE。。 不过在旧版本的jQuery中,仍然可以看到对IE的支持。例如在jquery-1.11-stable/src/events.js中:

    另外值得注意的是,jQuery的on方法实现中,addEventListener的第三个参数总是false。 即jQuery事件代理是借助事件冒泡实现的,并未使用事件捕获机制。

    再看与on对应的.off(),它的声明为:

    off方法的实现在jquery-2.1-stable/src/event.js822行,最终调用removeEventListener方法(619行)来移除事件处理函数:

    注意这里设置了第三个参数为false,因为on绑定的都是非捕获事件处理函数,自然off也只需要移除非捕获的事件处理函数。


    原文:

     

    1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

    相关文章
    • 7个有用的jQuery小技巧

      7个有用的jQuery小技巧

      2016-02-26 13:02

    • jQuery制作select双向选择列表

      jQuery制作select双向选择列表

      2016-02-26 11:00

    • 全面详细的jQuery常见开发技巧手册

      全面详细的jQuery常见开发技巧手册

      2016-02-26 10:02

    • 强大的jQuery移动插件Top 10

      强大的jQuery移动插件Top 10

      2016-02-25 09:05

    网友点评
    t