分享人:程仲夏
目录
1.背景介绍
2.知识剖析
3.常见问题
4.解决方案
5.编码实战
6.扩展思考
7.参考文献
8.更多讨论
JavaScript与HTML之间的交互是通过事件实现的。事件就是文档或浏览器窗口中发生的一些特定的交互动作。 它是用户或浏览器自身执行的某种动作,如click,load和mouseover都是事件的名字。
事件是javaScript和DOM之间交互的桥梁。
你若触发,我便执行——事件发生,调用它的处理函数执行相应的JavaScript代码给出响应。 典型的例子有:页面加载完毕触发load事件;用户单击元素,触发click事件。
事件流描述的是从页面中接收事件的顺序。
当浏览器发展到第四代时(IE4及Netscape4),浏览器开发团队遇到了一个很有意思的问题:页面的哪一部分会拥有某个特定的事件? 可以想象画在一张纸上的一组同心圆。如果你把手指放在圆心上,那么你的手指指向的不是同一个圆,而是纸上的所有圆。
IE和网景两家公司的浏览器开发团队在看待浏览器事件方面还是一致的。如果单击了某个按钮,他们都认为单击事件不仅仅发生在按钮上。 在单击按钮的同时,也单击了按钮的容器元素,甚至也单击了整个页面。
IE提出的是冒泡流,而网景提出的是捕获流,后来在W3C组织的统一之下,JS支持了冒泡流和捕获流, 但是目前低版本的IE浏览器还是只能支持冒泡流(IE6,IE7,IE8均只支持冒泡流),所以为了能够兼容更多的浏览器,建议大家使用冒泡流。
IE的事件流叫做事件冒泡(event bubbling),即事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播。也就是子级元素先触发,父级元素后触发。
网景团队提出的另一种事件流叫事件捕获(event capturing)。 事件捕获的思想是先由最上一级的节点先接收事件,然后向下传播到具体的节点。 也就是父级元素先触发,子级元素后触发。
DOM标准采用捕获+冒泡。两种事件流都会触发DOM的所有对象,从document对象开始,也在document对象结束。
DOM标准规定事件流包括三个阶段:
(1)事件捕获阶段
(2)处于目标阶段
(3)事件冒泡阶段
首先发生的是事件捕获,然后是实际的目标接收到事件,最后阶段是冒泡阶段。
可以自己选择绑定事件时采用事件捕获还是事件冒泡,方法就是绑定事件时通过addEventListener函数, 它有三个参数,第三个参数若是true,则表示采用事件捕获,若是false,则表示采用事件冒泡。
element.addEventListener(event, function, useCapture)
event:字符串,指定事件名。(不要使用 "on " 前缀。 例如,使用 "click " ,而不是使用 "onclick "。)
function:指定要事件触发时执行的函数。
useCapture:可选。布尔值,指定事件是否在捕获或冒泡阶段执行。(true - 事件句柄在捕获阶段执行;false- false- 默认。事件句柄在冒泡阶段执行)
IE只支持事件冒泡,不支持事件捕获,它也不支持addEventListener函数,不会用第三个参数来表示是冒泡还是捕获,它提供了另一个函数attachEvent。
element.attachEvent("onclick ", doSomething2);
addEventListener允许在同一个元素上添加多个事件处理程序,如下所示:
结果:先输出“Div”,再输出“myDiv-false”,最后输出“myDiv-true”。
在目标对象上同时绑定捕获阶段/冒泡阶段事件处理程序,触发目标对象时属于DOM事件流中的目标阶段。
目标阶段事件的执行顺序:先注册的先执行,后注册的后执行。也就是说,在目标对象上绑定的函数是采用捕获,还是采用冒泡,都没有什么关系,因为冒泡和捕获只是对父元素上的函数执行顺序有影响,对自己没有什么影响。
默认情况下,多个事件处理函数会按照DOM事件流模型中的顺序执行。如果子元素上发生某个事件,不需要执行父元素上注册的事件处理函数,那么我们可以停止捕获和冒泡,避免没有意义的函数调用。
IE8以及以前可以通过 window.event.cancelBubble=true阻止事件的继续传播;
IE9+/FF/Chrome通过event.stopPropagation()阻止事件的继续传播。
结果:先输出“Div1-true”,再输出“Div3-true”,最后输出“Div3-false”。不会输出“Div1-false”
因为当事件传播到Div3上的处理函数时,通过stopPropagation阻止了事件的继续传播,所以不会继续传播到冒泡阶段。
参考2:js之事件冒泡和事件捕获详细介绍
感谢大家观看
BY : 郭婷婷 | 程仲夏