平时浏览这么多技术文章,如过不去实践、深入弄透它,这个技术点很快就会在脑海里模糊。要加深印象,就得好好过一遍。重要的事情说三遍,重要的知识写一遍。
开发过程中我们都希望使用别人成熟的框架,因为站在巨人的肩膀上会使得我们开发的效率大幅度提升。不过,我们也应该、必须了解其基本原理。比如DOM事件,jquery框架帮我们为我们封装和抽象了各浏览器的差异行为,为事件处理带来了极大的便利。不过浏览器逐步走向统一和标准化,我们可以更加安全地使用官方规范的接口。因为只有获得众多开发者的芳心,浏览器才会走得更远。正如我们现在使用低版本浏览器打开某些页面时,会告知我们要用chrome等高级浏览器访问。不过这是一个革命的过程,为了让我们的webPage更好地服务更多的人,现在我们还不得不对这些历史遗留问题做更好的兼容。要做好兼容,除了依赖框架,我们得理解其基本原理。
DOM事件三个阶段
当一个DOM事件被触发时,它不仅仅只是单纯地在本身对象上触发一次,而是会经历三个不同的阶段:
As the next step, the event object MUST complete one or more event phases. This specification defines three event phases: capture phase, target phase and bubble phase. Event objects complete these phases in the specified order using the partial propagation paths as defined below. A phase MUST be skipped if it is not supported, or if the event object's propagation has been stopped. For example, if the Event.bubbles attribute is set to false, the bubble phase will be skipped, and if Event.stopPropagation() has been called prior to the dispatch, all phases MUST be skipped.
- The capture phase: The event object MUST propagate through the target's ancestors from the Window to the target's parent. This phase is also known as the capturing phase. Event listeners registered for this phase MUST handle the event before it reaches its target.
- The target phase: The event object MUST arrive at the event object's event target. This phase is also known as the at-target phase. Event listeners registered for this phase MUST handle the event once it has reached its target. If the event type indicates that the event MUST NOT bubble, the event object MUST halt after completion of this phase.
- The bubble phase: The event object propagates through the target's ancestors in reverse order, starting with the target's parent and ending with the Window. This phase is also known as the bubbling phase. Event listeners registered for this phase MUST handle the event after it has reached its target.
-
捕获阶段:先由文档的根节点document往事件触发对象,从外向内捕获事件对象;
-
目标阶段:到达目标事件位置(事发地),触发事件;
-
冒泡阶段:再从目标事件位置往文档的根节点方向回溯,从内向外冒泡事件对象。

引用来源:http://www.w3.org/TR/DOM-Level-3-Events/#event-flow
事件捕获与事件冒泡先后执行顺序就显而易见了。
打开在线编辑器:http://jsbin.com/goqede/edit?html,css,js,output
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> #outer{ text-align: center; width: 400px; height: 400px; background-color: #ccc; margin: 0 auto; } #middle{ width: 250px; height: 250px; background-color: #f00; margin: 0 auto; } #inner{ width: 100px; height: 100px; background-color: #0f0; margin: 0 auto; } </style> </head> <body> <div id='outer'> <span>outer</span> <div id='middle'> <span>middle</span> <div id='inner'> <span>inner</span> </div> </div> </div> <script> function $(element){ return document.getElementById(element); } function on(element,event_name,handler,use_capture){ if(addEventListener){ $(element).addEventListener(event_name,handler,use_capture); } else{ $(element).attachEvent('on'+event_name,handler); } } on("outer","click",o_click_c,true); on("middle","click",m_click_c,true); on("inner","click",i_click_c,true); on("outer","click",o_click_b,false); on("middle","click",m_click_b,false); on("inner","click",i_click_b,false); function o_click_c(){ console.log("outer_捕获"); alert("outer_捕获"); } function m_click_c(){ console.log("middle_捕获"); alert("middle_捕获"); } function i_click_c(){ console.log("inner_捕获"); alert("inner_捕获"); } function o_click_b(){ console.log("outer_冒泡"); alert("outer_冒泡"); } function m_click_b(){ console.log("middle_冒泡"); alert("middle_冒泡"); } function i_click_b(){ console.log("inner_冒泡"); alert("inner_冒泡"); } </script> </body> </html>
当我们点击inner的时候结果是:
outer_捕获 middle_捕获 inner_捕获 inner_冒泡 middle_冒泡 outer_冒泡
由此可见:确实是先由外向内事件捕获,一直到事发元素,在由内向外冒泡到根节点上
tips:
当事件触发在目标阶段时,会根据事件注册的先后顺序执行,在其他两个阶段注册顺序不影响事件执行顺序。也就是说如果该处既注册了冒泡事件,也注册了捕获事件,则按照注册顺序执行。
浙公网安备 33010602011771号