- 浏览: 60945 次
- 性别:
- 来自: 西安
文章分类
最新评论
DOM2和IE的事件传播机制(捕捉,起泡)
当事件发生在某个文档节点上时(即事件目标),目标的事件处理程序就会被触发。此外目标的每个祖先节点也有机会处理该事件。
2级DOM的事件传播包含三个阶段:
- 捕捉阶段(capturing),事件从顶级文档树节点一级一级向下遍历,直到到达该事件的目标节点。
- 到达事件的目标节点,执行目标节点的时间处理程序。
- 事件起泡(bubbling),事件从目标节点一级一级向上上溯,直到顶级文档树节点。
相应的,2级DOM通过下面的两个函数给节点对象添加和删除事件处理函数。
addEventListener(eventType, handler, propagate);
removeEventListener(eventType, handler, propagate);
三个参数意思分别如下:
- eventType: 即事件类型(不加on)。比如:"click"。
- handler: 事件处理函数。传入参数即为事件对象event。
- propagate: 是否只执行捕获和目标节点两个阶段。true的话,只执行1,2两个阶段;false的话,只指向2,3两个阶段。
IE的事件传播只包含上边的2和3两个阶段
相应的,IE通过下面两个函数给节点对象添加和删除事件处理函数。
attachEvent(eventType, handler);
detachEvent(eventType, handler);
参数意思同2级DOM对应的函数参数。
下面是程序的部分执行结果:
1. 开启捕捉过程,点击SetEventHandler按钮之后,点击Click Me按钮,观察捕捉过程中的事件响应
2. 开启阻止起泡过程,点击SetEventHandler按钮之后,点击Click Me按钮,观察起泡过程中的事件响应
以下是Sample的代码,分别给window, document, document.body, divOut, divIn和btnClick针对不同的浏览器追加了事件处理函数,并且在画面上列出执行时候的可配置项,动态模拟各种配置项对事件传播过程的影响,同时也将各种情况下的执行结果显示到了页面上。浏览器(Chrome, IE)。
<html> <head> <script type="text/javascript"> var disablePropagation = true; var cancelBubble = false; //Simple judge of browser var isIE = window.attachEvent ? true : false; //Short name for document.getElementById var byId = function(id) { return document.getElementById(id); } // Has event handler already been set. var isEventHandlerSetted = false; // value setted for Enable Propagate Checkbox at last time. var preisEnablePropagate = false; // event happend at last time. var preEvent = null; // Set Event Handler for elements function setEventHandler() { clearTrace(); // remove setted event handlers at last time if (isEventHandlerSetted) { if (isIE) { window.detachEvent('onclick', prtDtlWindow); document.detachEvent('onclick', prtDtlDocument); document.body.detachEvent('onclick', prtDtlBody); byId('divOut').detachEvent('onclick', prtDtlDivOut); byId('divIn').detachEvent('onclick', prtDtlDivIn); byId('btnClick').detachEvent('onclick', prtDtlClickMeBtn); } else { window.removeEventListener('click', prtDtl, preisEnablePropagate); document.removeEventListener('click', prtDtl, preisEnablePropagate); document.body.removeEventListener('click', prtDtl, preisEnablePropagate); byId('divOut').removeEventListener('click', prtDtl, preisEnablePropagate); byId('divIn').removeEventListener('click', prtDtl, preisEnablePropagate); byId('btnClick').removeEventListener('click', prtDtl, preisEnablePropagate); } } // Add new event handlers according to new setting. var isEnablePropagate = byId("cbxEnablePropagate").checked; preisEnablePropagate = isEnablePropagate; if (isIE) { window.attachEvent('onclick', prtDtlWindow); document.attachEvent('onclick', prtDtlDocument); document.body.attachEvent('onclick', prtDtlBody); byId('divOut').attachEvent('onclick', prtDtlDivOut); byId('divIn').attachEvent('onclick', prtDtlDivIn); byId('btnClick').attachEvent('onclick', prtDtlClickMeBtn); } else { window.addEventListener('click', prtDtl, isEnablePropagate); document.addEventListener('click', prtDtl, isEnablePropagate); document.body.addEventListener('click', prtDtl, isEnablePropagate); byId('divOut').addEventListener('click', prtDtl, isEnablePropagate); byId('divIn').addEventListener('click', prtDtl, isEnablePropagate); byId('btnClick').addEventListener('click', prtDtl, isEnablePropagate); } isEventHandlerSetted = true; } // a series of event handler for IE function prtDtlWindow() { prtDtl(window.event, window); } function prtDtlDocument() { prtDtl(window.event, document); } function prtDtlBody() { prtDtl(window.event, document.body); } function prtDtlDivOut() { prtDtl(window.event, byId ('divOut')); } function prtDtlDivIn() { prtDtl(window.event, byId ('divIn')); } function prtDtlClickMeBtn() { prtDtl(window.event, byId ('btnClick')); } // print detail formatted event handler execution info. function prtDtl(e, currentTarget) { if (!isSameEvent(preEvent, e)) { clearTrace(); } var target = null; var curTarget = null; if (isIE) { target = e.srcElement; curTarget = currentTarget } else { target = e.target; curTarget = e.currentTarget; } if (!isSameEvent(preEvent, e)) trace(target, true); trace(curTarget, false); if (isIE) { /* when I hold e directively ussing preEvent, preEvent's srcElement.id is the same as e's srcElement.id even when I click again. So I use preEvent to hold e's srcElement.id directively. (It seems the preEvent and e always share the same reference, but this is conflict with the result [preEvent === e] which returns false.) Maybe IE uses a completely different logic when compare Event Object I guess, who hnows.*/ //preEvent = e; preEvent = target.id; } else { preEvent = e; } var isCclBubble = byId("cbxCclBubble").checked; var isEnablePropagate = byId("cbxEnablePropagate").checked; if (isCclBubble || isEnablePropagate) { stopEvent(e, curTarget); } } function trace(t, isTarget) { var targetName = ""; if (t === window) { targetName = "Window"; } else if (t === document) { targetName = "Document"; } else if (t.getAttribute != null){ targetName = t.getAttribute('detail'); } else { for (var p in t) { if (p.indexof('name') != -1) { targetName = p; break; } } } var traceTxt = byId('traceArea'); if (isTarget) { var browser = "Not IE"; if (isIE) browser = "IE"; traceTxt.value += ("Your Browser is " + browser + ". \n"); traceTxt.value += ("Event Target is [" + targetName + "]. \n\n\n"); } else { traceTxt.value += ("[" + targetName + "]'s handling function called. \n"); } } function stopEvent(e, curTarget) { var stopAtWindow = byId("cbxWindow").checked; var stopAtDocument = byId("cbxDocument").checked; var stopAtBody = byId("cbxBody").checked; var stopAtOutDiv = byId("cbxOutDiv").checked; var stopAtInDiv = byId("cbxInDiv").checked; var stopAtClickMeBtn = byId("cbxClickMeBtn").checked; switch (curTarget) { case window: stopEventIn(e, stopAtWindow); break; case document: stopEventIn(e, stopAtDocument); break; case document.body: stopEventIn(e, stopAtBody); break; case byId("divOut"): stopEventIn(e, stopAtOutDiv); break; case byId("divIn"): stopEventIn(e, stopAtInDiv); break; case byId("btnClick"): stopEventIn(e, stopAtClickMeBtn); break; default: ; } } function stopEventIn(e, stop) { if (!stop) return; if (isIE) { e.cancelBubble = true; return; } e.stopPropagation(); } function clearTrace() { byId("traceArea").value = ""; } /* It is strange that IE create several event object for different elements' event handler. although user only click once. why????? TODO */ function isSameEvent(preEvent, e) { if (preEvent == null) { return false; } if (isIE) { /* It seems preEvent and e share same reference because that even when i click again and again, preEvent.srcElement.id always has the same value with e.srcElement.id */ // return (preEvent.srcElement.id == e.srcElement.id); return (preEvent == e.srcElement.id); } return preEvent===e; } </script> </head> <body detail="Body"> <table><tr> <td> <div id="divOut" detail="outter div" style="height:300; width:300; border:1 red solid"> <div id="divIn" detail="inner div" style="height:200; width:200; border:1 blue solid"> <button id="btnClick" type="button" detail="click me button">Click Me</button> </div> </div> </td> <td> <div id="divSet" detail="Setting div" style="height:300; width:300; border:1 red solid"> <table> <tr><td><button type="button" detail="Setting button" onclick="setEventHandler()">Set EventHandler</button></td></tr> <tr><td><label> <input id="cbxEnablePropagate" detail="Enable Propagate Checkbox" type="checkbox"/>Enable Propagate ?</label></td></tr> <tr><td><label><input id="cbxCclBubble" detail="Cancel Bubble Checkbox" type="checkbox"/>Cancel Bubble ?</label></td></tr> <tr><td><label><input id="cbxWindow" detail="Stop At Window Checkbox" type="checkbox"/>Stop At Window ?</label></td></tr> <tr><td><label><input id="cbxDocument" detail="Stop At Docuement Checkbox" type="checkbox"/>Stop At Docuement ?</label></td></tr> <tr><td><label><input id="cbxBody" detail="Stop At Body Checkbox" type="checkbox"/>Stop At Body ?</label></td></tr> <tr><td><label><input id="cbxOutDiv" detail="Stop At Outdiv Checkbox" type="checkbox"/>Stop At OutDiv ?</label></td></tr> <tr><td><label><input id="cbxInDiv" detail="Stop At InDiv Checkbox" type="checkbox"/>Stop At InDiv ?</label></td></tr> <tr><td><label><input id="cbxClickMeBtn" detail="Stop At Click me Button" type="checkbox"/>Stop At ClickMeBtn ?</label></td></tr> </table> <div> </td> <td> <div id="divTrace" style="height:300; width:300; border:1 red solid;"> <textarea id="traceArea" detail="TextArea" style="width:100%; height:100%"></textarea> </div> </td> </tr></table> </body> </html>
相关推荐
以上内容中包含了对DOM中各种对象的属性和方法的使用,BOM模型的核心对象window及其常用方法,JavaScript中的事件处理机制,包括事件是如何产生的、事件对象的特性以及事件冒泡现象,以及面向对象编程的基础知识,...
与IE DevToolBar类似,IE DOM Inspector允许用户直观地查看网页的DOM树,并可以方便地查看和修改元素属性、样式和事件。它特别适合于分析复杂的网页布局和交互,帮助开发者快速找出潜在的问题。虽然IE DOM Inspector...
DOM事件(ppt)DOM事件(ppt)DOM事件(ppt)DOM事件(ppt)DOM事件(ppt)DOM事件(ppt)DOM事件(ppt)DOM事件(ppt)DOM事件(ppt)DOM事件(ppt)DOM事件(ppt)DOM事件(ppt)DOM事件(ppt)DOM事件(ppt)DOM...
JavaScript防止事件传播是一种常见的前端开发技术,用于控制事件在DOM(文档对象模型)层次中的传播方式。事件传播包括三个阶段:捕获阶段、目标阶段和冒泡阶段。了解这三个阶段对于掌握如何阻止事件传播至关重要。 ...
这种技术的核心在于事件模型,它是JavaScript和DOM(文档对象模型)交互的重要机制。 事件模型分为三个阶段:冒泡、目标和捕获。在IE浏览器中,事件通常从最具体的元素(如一个按钮)开始,然后向上冒泡到更不具体...
DevToolBar 和 IEDOM 都是Web开发的利器,只要装一个就好了,感觉功能差不多,为了方便起见 一起传上来了。 安装后打开IE浏览器,工具栏中出现箭头(DevToolBar)或查找(IEDOM )的按钮,点击就可以十分方便的...
IE DOM查看器是开发人员在IE环境下调试和优化网页布局、事件处理以及动态内容更新的重要工具。 **描述:“在IE下面DOM查看,很方便,也很容易上手”** 在IE浏览器中,DOM查看器的易用性使得初学者也能快速掌握其...
在JavaScript DOM2中,事件处理分为两个级别:事件目标和事件流。事件目标是指事件实际发生的地方,而事件流包括冒泡和捕获两种模式。你可以通过`addEventListener()`和`removeEventListener()`方法来添加和移除事件...
Chrome浏览器作为一款广泛使用的Web浏览器,提供了强大的开发者工具来帮助开发者进行网页调试和优化,其中包括查找并分析DOM节点上的事件监听器。本教程将围绕“如何在Chrome中根据DOM找到DOM上的事件”这一主题展开...
在不同的浏览器环境下,事件处理的实现机制有所差异,尤其是在Internet Explorer(IE)和Firefox之间。本文将深入探讨这些差异,以帮助开发者更好地理解和解决跨浏览器的兼容性问题。 首先,我们要了解事件流的概念...
4. 阻止事件传播和默认行为:在实际应用中,可能需要根据业务逻辑的需求,阻止事件冒泡或阻止事件默认行为。 掌握这些知识点对于提升前端开发能力,实现复杂交互非常有帮助。实际操作中,可能还需要参考一些在线...
最后,事件开始冒泡,即从目标元素向上回传至最外层的父元素,沿途经过每个节点,直到事件传播完成。 2. 事件冒泡: 事件冒泡是IE浏览器最初实现的事件模型,也是大多数现代浏览器的默认行为。在这种模式下,事件...
为 DOM 绑定事件需要考虑浏览器的兼容性问题,我们可以使用不同的方式来绑定事件,包括直接为 Element 对象绑定事件、使用 W3C 的 addEventListener 和 IE 的 attachEvent 方法,以及自定义绑定函数等。
IE DOM Inspector 是一款 Microsoft 浏览器插件(非开源)。能对动态的HTML DOM 和网页内容进行查看和修改。你能在你的浏览器内直接浏览、拖动、更新动态的HTML DOM。
IE DOM Insepctor 博文链接:https://love2java.iteye.com/blog/208889
2. **性能**:DOM4J不仅支持DOM解析,还支持SAX和STAX解析,后者在处理大型XML文件时能有效减少内存占用。 3. **内存效率**:SAX解析器采用事件驱动模型,只在需要时处理XML元素,避免了内存不足的问题。 4. **易用...
使用`event.stopPropagation()`和`event.stopImmediatePropagation()`来控制事件传播,确保在不同浏览器中行为一致。 3. **CSS样式操作**: - IE浏览器有自己的style属性,如`element.styleExpression`,而其他...
JS中的DOM0级事件和DOM2级事件是两种不同的事件绑定机制,它们在浏览器的事件处理方式上存在本质的区别。 首先,我们来探讨什么是DOM0级事件。在早期的JavaScript版本中,所有的事件监听几乎都是通过DOM0级方式实现...
DOM事件总结(教辅)DOM事件总结(教辅)DOM事件总结(教辅)DOM事件总结(教辅)DOM事件总结(教辅)DOM事件总结(教辅)DOM事件总结(教辅)DOM事件总结(教辅)DOM事件总结(教辅)DOM事件总结(教辅)DOM事件...