本章节主要包括以下四个方面:
- 什么是事件流
- 事件冒泡
- 事件捕获
- W3C事件流(DOM事件流)
什么是事件流
定义:
1.事件流
描述的是从页面中接收事件的顺序,也可理解为事件在页面中传播的顺序。2.
事件
就是用户或浏览器自身执行的某种动作。诸如click(点击)、load(加载)、mouseover(鼠标悬停)。3.
事件处理程序
响应某个事件的函数就叫事件处理程序(或事件侦听器)。
JS事件流最早要从IE和网景公司的浏览器大战说起,IE提出的是冒泡流,而网景提出的是捕获流,后来在W3C组织的统一之下,JS支持了冒泡流和捕获流,但是目前低版本的IE浏览器还是只能支持冒泡流(IE6,IE7,IE8均只支持冒泡流),所以为了能够兼容更多的浏览器,建议大家使用冒泡流。
事件冒泡
微软提出了名为事件冒泡的事件流。事件冒泡可以形象地比喻为把一颗石头投入水中,泡泡会一直从水底冒出水面。也就是说,事件会从最内层的元素开始发生,一直向上传播,直到document对象,事件的传递应该是:p -> div -> body -> html -> document。
事件捕获
网景提出另一种事件流名为事件捕获与事件冒泡相反,事件会从最外层开始发生,直到最具体的元素。事件捕获顺序应该是:document -> html -> body -> div -> p
W3C事件流(DOM事件流)
当一个DOM事件被触发的时候,他并不是只在它的起源对象上触发一次,而是会经历三个不同的阶段。简而言之:事件一开始从文档的根节点流向目标对象(捕获阶段),然后在目标对向上被触发(目标阶段),之后再回溯到文档的根节点(冒泡阶段)如图所示(图片来自W3C):
事件捕获阶段(Capture Phase)
事件从文档的根节点出发,随着DOM树的结构向事件的目标节点流去。途中经过各个层次的DOM节点,并在各节点上触发捕获事件,直到到达时间的目标节点。捕获阶段的主要任务是简历传播路径,在冒泡阶段,时间会通过这个路径回溯到文档根节点。
例如,通过下面的这个函数来给节点设置监听,可以通过将;设置成true来为事件的捕获阶段添加监听回调函数。
1 | element.removeEventListener(<event-name>, <callback>, <use-capture>); |
而,在实际应用中,我们并没有太多使用捕获阶段监听的用例,但是通过在捕获阶段对事件的处理,我们可以阻止类似click事件在某个特定元素上被触发。如下:
1 | var form=document.querySeletor('form'); |
如果你对这种用法不是很了解的话,建议设置为false或者undefined,从而在冒泡阶段对事件进行监听,这也是常用的方法。
目标阶段(Target Phase)
当事件到达目标节点时,事件就进入了目标阶段。事件在目标节点上被触发,然后逆向回流,直到传播到最外层的文档节点。
对于多层嵌套的节点,鼠标和指针事件经常会被定位到最里层的元素上。假设,你在一个div元素上设置了click的监听函数,而用户点击在了这个div元素内部的p元素上,那么p元素就是这个时间的目标元素。事件冒泡让我们可以在这个div或者更上层的元素上监听click事件,并且时间传播过程中触发回调函数。
冒泡阶段(Bubble Phase)
事件在目标事件上触发后,并不在这个元素上终止。它会随着DOM树一层层向上冒泡,直到到达最外层的根节点,一直向上传播,直到document对象。也就是说,同一事件会一次在目标节点的父节点,父节点的父节点…直到最外层的节点上触发。
绝大多数事件是会冒泡的,但并非所有的。
示例代码
1 | <!DOCTYPE html> |
结论:当点击页面中心浅蓝色部分的时候,先从最不具体的节点捕获事件,先弹出wrap,接着弹出outer。接着处于目标阶段,先弹出123,再弹出inner。紧接着,事件处于冒泡阶段,先弹出456,再弹出789。因此我们可以得出结论,当容器元素及嵌套元素,即在捕获阶段
又在冒泡阶段
调用事件处理程序时:事件按DOM事件流的顺序执行事件处理程序,当事件处于目标阶段时,事件调用顺序决定于绑定事件的书写顺序。
提示:
- 所有现代浏览器都支持事件冒泡,但在具体实现中略有差别
- 由于老版本浏览器不支持使用事件捕获。建议使用事件冒泡。
- 尽管“DOM2级事件”标准规范明确规定事件捕获阶段不会涉及事件目标,但是在IE9、Safari、Chrome、Firefox和Opera9.5及更高版本都会在捕获阶段触发事件对象上的事件。结果,就是有两次机会在目标对象上面操作事件。
- 并非所有的事件都会经过冒泡阶段 。所有的事件都要经过捕获阶段和处于目标阶段,但是有些事件会跳过冒泡阶段:如,获得输入焦点的focus事件和失去输入焦点的blur事件。
##