您的位置:首页 > Web前端 > JavaScript

javascript 事件模型

2016-02-28 22:00 549 查看
事件的触发有三个阶段

document 往事件触发地点,捕获前进,遇到相同注册事件立即触发执行
到达事件位置,触发事件(多谢 @糖果果 指出 问题 ,@update
14/2/19 如果该处既注册了冒泡事件,也注册了捕获事件,按照注册顺序执行)
事件触发地点往 document 方向,冒泡前进,遇到相同注册事件立即触发

这么说很多人比较迷糊,我们在注册事件的时候,通常使用的是 捕获 或者 冒泡 的 一种:

obj.addEventListener("click", func, true); // 捕获方式
obj.addEventListener("click", func, false); // 冒泡方式

“DOM2级事件”定义了两个方法,用于处理指定和删除事件处理程序的操作:addEventListener()
和removeEventListener()。所有DOM节点中都包含这两个方法,并且它们都接受3 个参数:要处
理的事件名、作为事件处理程序的函数和一个布尔值。最后这个布尔值参数如果是true,表示在捕获
阶段调用事件处理程序;如果是false,表示在冒泡阶段调用事件处理程序。

IE 实现了与DOM 中类似的两个方法:attachEvent()和detachEvent()。这两个方法接受相同
的两个参数:事件处理程序名称与事件处理程序函数。由于IE8 及更早版本只支持事件冒泡,所以通过
attachEvent()添加的事件处理程序都会被添加到冒泡阶段。

在IE 中使用attachEvent()与使用DOM0 级方法的主要区别在于事件处理程序的作用域。在使
用DOM0 级方法的情况下,事件处理程序会在其所属元素的作用域内运行;在使用attachEvent()方
法的情况下,事件处理程序会在全局作用域中运行,因此this 等于window。

捕获阶段(Capture Phase)

当我们在 DOM 树的某个节点发生了一些操作(例如单击、鼠标移动上去),就会有一个事件发射过去。这个事件从 Window 发出,不断经过下级节点直到目标节点。在到达目标节点之前的过程,就是捕获阶段(Capture Phase)。 所有经过的节点,都会触发这个事件。捕获阶段的任务就是建立这个事件传递路线,以便后面冒泡阶段顺着这条路线返回 Window。 监听某个在捕获阶段触发的事件,需要在事件监听函数传递第三个参数 [code]true

element.addEventListener(<event-name>, <callback>, true);
但一般使用时我们往往传递 false,会在后面说明原因。

目标阶段(Target Phase)

当事件跑啊跑,跑到了事件触发目标节点那里,最终在目标节点上触发这个事件,就是目标阶段。
需要注意的时,事件触发的目标总是最底层的节点。比如你点击一段文字,你以为你的事件目标节点在
div
上,但实际上触发在
<p>
<span>
等子节点上

冒泡阶段(Bubbling Phase)

当事件达到目标节点之后,就会沿着原路返回,由于这个过程类似水泡从底部浮到顶部,所以称作冒泡阶段。
在实际使用中,你并不需要把事件监听函数准确绑定到最底层的节点也可以正常工作。比如在上例,你想为这个
<div>
绑定单击时的回调函数,你无须为这个
<div>
下面的所有子节点全部绑定单击事件,只需要为
<div>
这一个节点绑定即可。因为发生它子节点的单击事件,都会冒泡上去,发生在
<div>
上面。

为什么不用第三个参数 true

介绍完上面三个事件触发阶段,我们来看下这个问题。
所有介绍事件的文章都会说,在使用
addEventListener
函数来监听事件时,第三个参数设置为
false
,这样监听事件时只会监听冒泡阶段发生的事件。
这是因为 IE 浏览器不支持在捕获阶段监听事件,为了统一而设置的,毕竟 IE 浏览器的份额是不可忽略的。
IE 浏览器在事件这方面与标准还有一些其他的差异,我们会在后面集中介绍。

使用事件代理(Event Delegate)提升性能

因为事件有冒泡机制,所有子节点的事件都会顺着父级节点跑回去,所以我们可以通过监听父级节点来实现监听子节点的功能,这就是事件代理。
使用事件代理主要有两个优势:
减少事件绑定,提升性能。之前你需要绑定一堆子节点,而现在你只需要绑定一个父节点即可。减少了绑定事件监听函数的数量。
动态变化的 DOM 结构,仍然可以监听。当一个 DOM 动态创建之后,不会带有任何事件监听,除非你重新执行事件监听函数,而使用事件监听无须担忧这个问题。

停止事件冒泡(stopPropagation)

所有的事情都会有对立面,事件的冒泡阶段虽然看起来很好,也会有不适合的场所。比较复杂的应用,由于事件监听比较复杂,可能会希望只监听发生在具体节点的事件。这个时候就需要停止事件冒泡。
停止事件冒泡需要使用事件对象的
stopPropagation
方法,具体代码如下:
element.addEventListener('click', function(event) {
event.stopPropagation();
}, false);[/code]在事件监听的回调函数里,会传递一个参数,这就是
Event
对象,在这个对象上调用
stopPropagation
方法即可停止事件冒泡。举个停止事件冒泡的应用实例:
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: