js 捕获型事件、冒泡型事件、DOM事件流、事件委托
来源:互联网 发布:雪河二少捏脸数据 编辑:程序博客网 时间:2024/06/05 10:03
引言:
首先考虑这么一个问题,当在页面画很多同心圆,当你手机放在同心圆圆心的时候,你觉得你的手是放在所有圆内还是只是在你最近的那个圆。
那么还有一个问题,如果你觉得上面那个问题的答案是手指放在全部的圈内,那么你觉得应该怎么给圈排序的,是从最外面的圈开始还是从最近的圈开始呢?
一、事件流
其实说的问题就是接下来要说的事件流的问题了。当子节点和父节点都有点击事件,然后点击的是子节点,那么这时候先触发子节点还是父节点的事件呢?IE是这么想的,先触发子节点后触发父节点(冒泡型事件)。Netscape团队提出的来的却是先触发父节点(捕获型事件)。这就是事件流。
二、事件冒泡
IE事件流称为事件冒泡,即事件开始时由最具体的元素(文档中嵌层最深的那个节点)接受,然后逐次往上传播到较为不具体的节点(文档)。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xHTML1/DTD/xHTML1-transitional.dtd"><HTML XMLns="http://www.w3.org/1999/xHTML" lang="gb2312"><head><title></title><meta name="keywords" content="JS,事件冒泡,cancelBubble,stopPropagation" /><div id = "mydiv">Click</div></body></HTML>
比如我点击Click,那么事件会按照如下顺序传播:
div、body、html、document
三、捕获型事件
跟事件冒泡刚好相反,上述的例子顺序为:
document、html、body、div
事件捕获是很少人用的,冒泡用的比较多
四、DOM事件流(DOM2级事件)
DOM事件流有三个阶段:事件捕获阶段、处于目标阶段、事件冒泡阶段。其中事件捕获阶段不会接受事件
五、事件委托
既然说到了事件冒泡就说一个利用事件冒泡来做事件委托。
那么什么叫做事件委托呢?
对“事件处理程序过多”问题的解决方案就是事件委托,事件委托利用了事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件,例如click事件会一直冒泡到document层次,也就是说我们可以为整一个页面指定一个onclick事件处理程序,而不必为每一个可以单击的元素添加事件处理程序。
那么这么做有什么必要吗?
首先,添加到页面的事件处理程序数量直接关系到页面整体运行性能。原因一:每个函数都是一个对象,每一个对象都会占用内存,内存对象越多性能自然就差了。原因二:每次指定事件都需要访问dom节点,dom节点访问次数越多,会延迟整个页面的交互就绪事件。
看下面的一段代码:
<ul id="links"> <li id = "l1">1</li> <li id = "l2">2</li> <li id = "l3">3</li></ul><script> var EventUtil = { addHandler: function(element, type, handler){ //若浏览器支持addEventListener,则使用addEventListener来添加事件 if(element.addEventListener){ //DOM2级 element.addEventListener(type, handler, false); } else if(element.attachEvent){ //IE element.attachEvent("on" + type, handler); } else { //若以上两种添加事件的方法都不支持,则使用默认的行为来添加事件 element["on" + type] = handler; //DOM0 } }, //移除事件 removeHandler: function(element, type, handler){ if (element.removeEventListener){ element.removeEventListener(type, handler, false); } else if(element.detachEvent){ element.detachEvent("on" + type, handler); } else{ element["on" + type] = null; } }, getEvent :function (event) { return event ? event : window.event; }, getTarget :function (event) { return event.target || event.srcElement; }, stopPropagation: function (event) { if (event.stopPropagation){ event.stopPropagation(); } else { event.cancelBubble = true; } }, preventDefault: function (event) { if (event.preventDefault){ event.preventDefault(); } else { event.returnValue = false; } } } var links = document.getElementById('links'); EventUtil.addHandler(links, "click" ,function(event) { event = EventUtil.getEvent(event); var target = EventUtil.getTarget(event); switch(target.id) { case "l1" : document.title = "Change the document title"; break; case "l2" : location.href = "http:www.baidu.com"; break; case "l3" : alert ('l3'); break; } });
这段代码实现了三个不同li节点的点击事件,但是只有一个事件处理程序就可以了,节省函数的同时也节省了访问节点的次数。(注意应该选取target节点作为对象)
Tips:
这里用到了一个EventUtil 对象来处理跨浏览器事件处理程序。
主要有三种不同的事件处理程序:
1、DOM0级事件处理程序
这是一种传统的事件处理程序,就是将一个函数赋值给一个事件处理程序属性。
例如:
//添加var btn = document.getElementById("mybtn");btn.onclick = function (){ alert(this.id);}//删除btn.click = null;
2、DOM2级事件处理程序
使用addEventListener,removeEventListener指定或删除事件处理程序
//addEventListener(type,handler,false)//removeEventListener(type,handler,false)var btn = document.getElementById("mybtn");var handler = function (){ alert(this.id);}btn.addEventListener = ('click',handler,false);//删除btn.removeEventListener= ('click',handler,false);
3、IE事件处理程序
使用attachEvent,detachEvent指定或删除事件处理程序
//attachEvent(type,handler)//detachEvent(type,handler)var btn = document.getElementById("mybtn");var handler = function (){ alert(this.id);}btn.attachEvent= ('onclick',handler);//删除btn.detachEvent= ('onclick',handler);
事件对象event作为window对象的一个属性存在(DOM0和DOM2直接用event表示)
目标对象作为event中srcElement属性存在(DOM0和DOM2用event里面的target属性存在)
六、消除冒泡
可以用stopPropagation来消除冒泡行为,看一下经典例子
<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xHTML1/DTD/xHTML1-transitional.dtd"><HTML XMLns="http://www.w3.org/1999/xHTML" lang="gb2312"><head><title> 阻止JS事件冒泡传递(cancelBubble 、stopPropagation)</title><meta name="keywords" content="JS,事件冒泡,cancelBubble,stopPropagation" /><script> var EventUtil = { addHandler: function(element, type, handler){ //若浏览器支持addEventListener,则使用addEventListener来添加事件 if(element.addEventListener){ //DOM2级 element.addEventListener(type, handler, false); } else if(element.attachEvent){ //IE element.attachEvent("on" + type, handler); } else { //若以上两种添加事件的方法都不支持,则使用默认的行为来添加事件 element["on" + type] = handler; //DOM0 } }, //移除事件 removeHandler: function(element, type, handler){ if (element.removeEventListener){ element.removeEventListener(type, handler, false); } else if(element.detachEvent){ element.detachEvent("on" + type, handler); } else{ element["on" + type] = null; } }, getEvent :function (event) { return event ? event : window.event; }, getTarget :function (event) { return event.target || event.srcElement; }, stopPropagation: function (event) { if (event.stopPropagation){ event.stopPropagation(); } else { event.cancelBubble = true; } }, preventDefault: function (event) { if (event.preventDefault){ event.preventDefault(); } else { event.returnValue = false; } } } function doSomething (obj,evt) { alert(obj.id); var e=(evt)?evt:window.event; if (window.event) { e.cancelBubble=true;// ie下阻止冒泡 } else { //e.preventDefault(); EventUtil.stopPropagation(e);// 其它浏览器下阻止冒泡 }}</script></head><body><div id="parent1" onclick="alert(this.id)" style="width:250px;"> <p>This is parent1 div.</p> <div id="child1" onclick="alert(this.id)" style="width:200px;"> <p>This is child1.</p> </div> <p>This is parent1 div.</p></div><br /><div id="parent2" onclick="alert(this.id)" style="width:250px;"> <p>This is parent2 div.</p> <div id="child2" onclick="doSomething(this,event);" style="width:200px;"> <p>This is child2. Will bubble.</p> </div> <p>This is parent2 div.</p></div></body></HTML>
结果:
当点击parent1的时候只触发parent1,当点击child1的时候parent1和child1都会触发
当点击parent2的时候只触发parent2,当点击child2的时候只触发child2
说明child2的冒泡被取消了
- js 捕获型事件、冒泡型事件、DOM事件流、事件委托
- js事件冒泡,事件捕获,事件委托
- 事件冒泡、事件捕获、事件委托
- 事件冒泡、事件捕获与事件委托
- 【JS】事件冒泡&事件捕获
- js中的冒泡,捕获以及事件委托
- DOM事件流之事件冒泡&事件捕获
- 面试题-冒泡与捕获、事件委托、ie事件和dom模型事件、鼠标事件
- 事件以及事件捕获、事件冒泡、事件委托
- JavaScript事件冒泡,事件捕获,事件处理,事件委托
- js冒泡、捕获事件
- 事件冒泡与捕获&事件委托
- JS事件流(事件冒泡和事件捕获)
- JS中的事件绑定,事件捕获,事件冒泡以及事件委托,兼容IE
- JS中的事件绑定,事件捕获,事件冒泡以及事件委托,兼容IE
- JS中的事件绑定,事件捕获,事件冒泡以及事件委托,兼容IE
- 事件流:DOM事件与IE事件,事件冒泡与事件捕获
- dom事件冒泡和捕获
- 复制构造函数被调用的三种情况
- 每天laravel[002]-自动加载函数流程之bootstrap autoload.php
- ACM:A: 二叉树结点公共祖先
- Android运行项目出现UnsupportedMethodException
- 在C / C ++中清除输入缓冲区
- js 捕获型事件、冒泡型事件、DOM事件流、事件委托
- IO调度层
- 揭秘微信小程序
- Android产品研发(三)-->基类Activity
- POJ 1778 All Discs Considered 笔记
- Fckeditor使用方法
- 【飘红】继承了公共类中已经有的方法,再在实体类中写就是重写了
- 删除IIS Express上的网站
- 算法设计与应用基础:第十五周(2)