`

DOM2和IE的事件传播机制(捕捉,起泡)

阅读更多

 

当事件发生在某个文档节点上时(即事件目标),目标的事件处理程序就会被触发。此外目标的每个祖先节点也有机会处理该事件。
2级DOM的事件传播包含三个阶段:

  1. 捕捉阶段(capturing),事件从顶级文档树节点一级一级向下遍历,直到到达该事件的目标节点。
  2. 到达事件的目标节点,执行目标节点的时间处理程序。
  3. 事件起泡(bubbling),事件从目标节点一级一级向上上溯,直到顶级文档树节点。

相应的,2级DOM通过下面的两个函数给节点对象添加和删除事件处理函数。
      addEventListener(eventType, handler, propagate);
      removeEventListener(eventType, handler, propagate);
三个参数意思分别如下:

  1. eventType: 即事件类型(不加on)。比如:"click"。
  2. handler: 事件处理函数。传入参数即为事件对象event。
  3. 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>

 

  • 大小: 70.3 KB
  • 大小: 75.8 KB
  • 大小: 74.4 KB
  • 大小: 66.7 KB
2
0
分享到:
评论

相关推荐

    Html dom _BOM 模型 _事件处理机制 _面向对象基础

    以上内容中包含了对DOM中各种对象的属性和方法的使用,BOM模型的核心对象window及其常用方法,JavaScript中的事件处理机制,包括事件是如何产生的、事件对象的特性以及事件冒泡现象,以及面向对象编程的基础知识,...

    两个精典的DOM查看器 IEDOM & DevToolBar

    与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事件(ppt)DOM事件(ppt)DOM事件(ppt)DOM...

    javascript防止事件传播

    JavaScript防止事件传播是一种常见的前端开发技术,用于控制事件在DOM(文档对象模型)层次中的传播方式。事件传播包括三个阶段:捕获阶段、目标阶段和冒泡阶段。了解这三个阶段对于掌握如何阻止事件传播至关重要。 ...

    ie事件捕获控件 捕获ie浏览器到打开链接等等的事件

    这种技术的核心在于事件模型,它是JavaScript和DOM(文档对象模型)交互的重要机制。 事件模型分为三个阶段:冒泡、目标和捕获。在IE浏览器中,事件通常从最具体的元素(如一个按钮)开始,然后向上冒泡到更不具体...

    IEDevToolBarSetup +IEDOM

    DevToolBar 和 IEDOM 都是Web开发的利器,只要装一个就好了,感觉功能差不多,为了方便起见 一起传上来了。 安装后打开IE浏览器,工具栏中出现箭头(DevToolBar)或查找(IEDOM )的按钮,点击就可以十分方便的...

    IE 下dom查看器

    IE DOM查看器是开发人员在IE环境下调试和优化网页布局、事件处理以及动态内容更新的重要工具。 **描述:“在IE下面DOM查看,很方便,也很容易上手”** 在IE浏览器中,DOM查看器的易用性使得初学者也能快速掌握其...

    javascript dom2 源码及pdf

    在JavaScript DOM2中,事件处理分为两个级别:事件目标和事件流。事件目标是指事件实际发生的地方,而事件流包括冒泡和捕获两种模式。你可以通过`addEventListener()`和`removeEventListener()`方法来添加和移除事件...

    chrome根据dom找到dom上的事件.zip

    Chrome浏览器作为一款广泛使用的Web浏览器,提供了强大的开发者工具来帮助开发者进行网页调试和优化,其中包括查找并分析DOM节点上的事件监听器。本教程将围绕“如何在Chrome中根据DOM找到DOM上的事件”这一主题展开...

    IE与Firefox的事件区别

    在不同的浏览器环境下,事件处理的实现机制有所差异,尤其是在Internet Explorer(IE)和Firefox之间。本文将深入探讨这些差异,以帮助开发者更好地理解和解决跨浏览器的兼容性问题。 首先,我们要了解事件流的概念...

    javascript事件捕获机制【深入分析IE和DOM中的事件模型】

    4. 阻止事件传播和默认行为:在实际应用中,可能需要根据业务逻辑的需求,阻止事件冒泡或阻止事件默认行为。 掌握这些知识点对于提升前端开发能力,实现复杂交互非常有帮助。实际操作中,可能还需要参考一些在线...

    深入理解JS DOM事件机制

    最后,事件开始冒泡,即从目标元素向上回传至最外层的父元素,沿途经过每个节点,直到事件传播完成。 2. 事件冒泡: 事件冒泡是IE浏览器最初实现的事件模型,也是大多数现代浏览器的默认行为。在这种模式下,事件...

    javascript为DOM绑定事件 兼容

    为 DOM 绑定事件需要考虑浏览器的兼容性问题,我们可以使用不同的方式来绑定事件,包括直接为 Element 对象绑定事件、使用 W3C 的 addEventListener 和 IE 的 attachEvent 方法,以及自定义绑定函数等。

    IE DOM Microsoft 浏览器插件

    IE DOM Inspector 是一款 Microsoft 浏览器插件(非开源)。能对动态的HTML DOM 和网页内容进行查看和修改。你能在你的浏览器内直接浏览、拖动、更新动态的HTML DOM。

    IEWebDeveloperV2&IE DOM Inspector下载

    IE DOM Insepctor 博文链接:https://love2java.iteye.com/blog/208889

    dom4j基于事件流解析大XML的文件 示例

    2. **性能**:DOM4J不仅支持DOM解析,还支持SAX和STAX解析,后者在处理大型XML文件时能有效减少内存占用。 3. **内存效率**:SAX解析器采用事件驱动模型,只在需要时处理XML元素,避免了内存不足的问题。 4. **易用...

    DOM文档和Javascript的IE和Firefox兼容性

    使用`event.stopPropagation()`和`event.stopImmediatePropagation()`来控制事件传播,确保在不同浏览器中行为一致。 3. **CSS样式操作**: - IE浏览器有自己的style属性,如`element.styleExpression`,而其他...

    JS中dom0级事件和dom2级事件的区别介绍

    JS中的DOM0级事件和DOM2级事件是两种不同的事件绑定机制,它们在浏览器的事件处理方式上存在本质的区别。 首先,我们来探讨什么是DOM0级事件。在早期的JavaScript版本中,所有的事件监听几乎都是通过DOM0级方式实现...

    DOM事件总结(教辅)

    DOM事件总结(教辅)DOM事件总结(教辅)DOM事件总结(教辅)DOM事件总结(教辅)DOM事件总结(教辅)DOM事件总结(教辅)DOM事件总结(教辅)DOM事件总结(教辅)DOM事件总结(教辅)DOM事件总结(教辅)DOM事件...

Global site tag (gtag.js) - Google Analytics