IE:的事件流是事件冒泡流。javascript
事件冒泡(event bubbling):事件由最具体的元素(嵌套最深的那个节点)接收,而后逐级向上传播到不具体的节点(文档)。明显的缺点就是在多个子元素上绑定事件,父元素节点会接受到全部的事件绑定,这是个很坑爹的体验。html
Netscape Communicator:的事件流是事件捕获流。java
事件捕获(event capuring):是不太具体的元素节点应该更早的接收到事件,而更具体的节点应该最后接收到事件。符合经常使用的模型和思考方式。chrome
Dom事件流:“Dom2级事件”规定了事件流包括三个阶段。(事件代理处理)浏览器
事件捕获阶段、处于事件阶段和事件冒泡阶段。即事件捕获为截获事件提供了机会,接着实际的目标接收到事件,最后冒泡阶段,在这个阶段对事件作出响应。dom
实际上这里已经显示了捕获要在冒泡以前。函数
大多的时候会把事件流添加到冒泡阶段,这样能够最大限度的兼容各类浏览器。此时DOM2级事件设为false。this
这里的捕获阶段不涉及事件目标。这个时候的事件冒泡或者是事件捕获使用,添加事件最后的限定true(捕获阶段)||false(冒泡阶段)来触发。若是不写是根据浏览器的特性来实现的。url
以下来验证:一个DOM元素绑定两个事件,一个冒泡,一个捕获,则事件会执行多少次,执行顺序如何。先捕获后冒泡。spa
//以下事件冒泡阶段触发 <div id='one'>1 <div id='two'>2 <div id='three'>3 <div id='four'>4 </div> </div> </div> </div> <script type='text/javascript'> var one=document.getElementById('one'); var two=document.getElementById('two'); var three=document.getElementById('three'); var four=document.getElementById('four'); one.addEventListener('click',function(){ alert('one'); },false);//表示在冒泡阶段触发事件 two.addEventListener('click',function(){ alert('two'); },false); three.addEventListener('click',function(){ alert('three'); },false); four.addEventListener('click',function(){ alert('four'); },false); </script> //点击4,依次会触发four、three、two、one。
<div id='one'>1 <div id='two'>2 <div id='three'>3 <div id='four'>4 </div> </div> </div> </div> <script type='text/javascript'> var one=document.getElementById('one'); var two=document.getElementById('two'); var three=document.getElementById('three'); var four=document.getElementById('four'); one.addEventListener('click',function(){ alert('one'); },true);//表示在捕获阶段触发事件 two.addEventListener('click',function(){ alert('two'); },true); three.addEventListener('click',function(){ alert('three'); },true); four.addEventListener('click',function(){ alert('four'); },true); </script>
//点击4则依次触发:one、two、three、four
<div id='one'>1 <div id='two'>2 <div id='three'>3 <div id='four'>4 </div> </div> </div> </div> <script type='text/javascript'> var one=document.getElementById('one'); var two=document.getElementById('two'); var three=document.getElementById('three'); var four=document.getElementById('four'); one.addEventListener('click',function(){ alert('one'); },true); two.addEventListener('click',function(){ alert('two,bubble'); },false);//这里的事件在冒泡阶段触发 two.addEventListener('click',function(){ alert('two,capture'); },true);//这里的事件在捕获阶段触发 three.addEventListener('click',function(){ alert('three,bubble'); },true); four.addEventListener('click',function(){ alert('four'); },true); </script> <!-- 执行顺序最终结果是:(chrome先捕获后冒泡)点击4,依次会触发 one、two,capture、three,bubble、four、two,bubble-->
<!-- 说明,同一个元素上绑定事件是先捕获,再冒泡。中间还有一个处于目标阶段 -->
事件是用户或浏览器自身执行的某种动做:如click、load、mouseover等,响应某个事件的函数称为事件处理程序(事件监听器)。
事件处理程序中的代码在执行时,有权访问全局做用域中的任何代码(匿名函数的做用域-全局)。
直接写在页面元素中,强耦合,摒弃。页面在前解析,js在后解析。
存在时差问题,可能在处理程序解析以前就触发了事件,会致使错误。
MouseEvent对象以下:
<input type="button" value = "click me" onclick = "console.log(event)"/>
这里的path保存着事件冒泡的顺序(具体到不具体),target保存着目标节点的信息,view保存着window对象的一些信息。
经过JavaScript指定事件处理程序的传统方式,就是将一个函数赋值给一个事件处理程序属性。这种方法被称为事件处理程序赋值,出如今第四代 Web 浏览器中。
每一个元素(包括 window 和 document)都有本身的事件处理程序属性,属性一般所有小写,如 onclick。将这种属性的值设置为一个函数,就能够指定事件处理程序。
<input type="button" value = "Dom0" id = "myBtn" /> <script type="text/javascript"> var btn = document.getElementById("myBtn"); btn.onclick = function(event){ console.log(event); } </script>
打印结果与上边无差。处理函数内部this指向元素节点。能够取到this.id。
删除事件,将事件处理函数置为null便可。
btn.onclick = null;
“DOM2级事件”定义了两个方法,用于处理指定和删除事件处理程序的操做:addEventListener()和removeEventListener() ;
它们接受3个参数:
要处理的事件名
做为事件处理程序的函数
一个布尔值:
true: 捕获阶段调用事件处理程序
false: 冒泡阶段调用
<input type="button" value = "Dom2" id = "myBtn2" /> <script type="text/javascript"> var btn = document.getElementById("myBtn2"); btn.addEventListener("click",function(event){ alert("Dom2"); console.log(event); },false); </script>
事件event与以前的无差。
能够添加多个事件,添加多个事件的时候,按添加的顺序依次执行。
移除事件要一一对应,注意因为匿名函数在内存中没有指向对象,因此添加以后没法移除,因此作好的作法就是先定义好声明的处理函数(或者函数表达式),在进行绑定和删除。
大部分时候都是把事件添加到冒泡(false)阶段,这样能够最大限度的兼容各类浏览器。
IE 实现了与 DOM 中相似的两个方法:attachEvent()和detachEvent()
接受两个参数:事件处理程序名称、事件处理程序函数
经过这种方法添加的事件处理程序会被添加到冒泡阶段。
<input type="button" value = "IE" id = "myBtn3" /> <script type="text/javascript"> var btn = document.getElementById("myBtn3"); btn.attachEvent("onclick",function(event){ alert("Clicked"); console.log(event); console.log(this) }); </script>
打印的结果不能展开:
在IE中使用 attachEvent() 与使用 DOM0 级方法的主要区别在于事件处理程序的做用域。
DOM0 级方法:在Dom0级事件当中,事件处理程序会在其所属的元素的做用于内运行。
attachEvent()方法:使用attachEvent()方法的状况下,事件处理程序会在全局做用域中运行。此时this 等于window。
固然,匿名函数不能被移除。
触发Dom上的某个事件的时候,会产生一个事件对象event,这个对象包含着与事件相关的信息,包含致使事件的元素、事件的类型及其余信息。
event对象包含着与建立它的特定事件有关的属性和方法。
事件对象的一些属性和方法:
主要的有:
cancelable:代表是否能够取消事件默认行为。
currentTarget:时间处理程序当前正在处理的那个元素。处理程序内部,对象this始终等于currentTarget的值。而target只包含事件的实际目标。
preventDefault():取消事件的默认行为。
target:事件目标。
stopPropagation(): 取消事件进一步的捕获或者冒泡。
只有在执行事件期间,event才存在,事件执行完成以后,event对象就会被销毁。
//写一个通用的事件侦听器函数 //跨浏览器事件对象 var EventUtil = { //页面加载完成以后,页面彻底加载以后执行。 readyEvent:function(fn){ if(document.addEventListener){ //标准浏览器 document.addEventListener('DOMContentLoaded',function(){ //注销事件,避免反复触发 document.removeEventListener('DOMContentLoaded',arguments.callee,false); //执行函数 fn(); },false); }else if(document.attachEvent){ //IE浏览器 document.attachEvent('onreadystatechange',function(){ if(document.readyState=='complete'){ document.detachEvent('onreadystatechange',arguments.callee); //执行函数 fn(); } }); } }, /* *attachEvent可使用匿名函数,但这样以后,detachEvent将没法卸载之。 *detachEvent所卸载的函数必须使用函数名。 */ //添加事件 addEvent:function(element,type,handler){ if(element.addEventListener){//非IE,DOM2 //事件类型、须要执行的函数、是否捕获 element.addEventListener(type,handler,false); }else if(element.attachEvent){//IE element.attachEvent('on'+type,handler); }else{ element['on'+type] = handler;//DOM0 } }, //移除事件 removeEvent:function(element,type,handler){ if(element.removeEventListener){ element.removeEventListener(type,handler,false); }else if(element.detachEvent){ element.detach('on'+type,handler); }else{ element['on'+type] = null; } }, //阻止事件冒泡(主要是事件冒泡,由于IE不支持事件捕获),用于当即中止事件在Dom层中的传播,即进一步取消事件的捕获或者冒泡。 stopPropagation:function(event){ if(event.stopPropagation){ event.stopPropagation();//W3C标准 }else{ event.canceBubble = true;//IE } }, //取消事件的默认行为, 如url的跳转等 preventDefault:function(event){ if(event.preventDefault){ event.preventDefault();//W3C标准 }else{ event.returnValue = false;//IE } }, //获取事件目标 getTarget:function(event){ return event.target||event.srcElement; }, //获取event对象的引用,获取事件的全部信息,确保随时能使用event; getEvent:function(event){ var event = event||window.event;//在Dom0级事件添加,event做为window对象的一个属性存在。 } };
// 定义一个函数处理多种类型的事件 var handler = function(event){ switch(event.type){ case "click": alert("Clicked"); break; case "mouseover": event.target.style.backgroundColor = "red"; break; case "mouseout": event.target.style.backgroundColor = ""; break; default: alert("test switch"); } };
//阻止事件冒泡的实例 var btnCancel = document.getElementById("btnCancel"); btnCancel.onclick = function(event){ alert("clicked222"); //这样以后,body上的事件就不会触发了,否则点一下,就会触发这两个事件。 EventUtil.stopPropagation(event); }; document.body.onclick = function(event){ //若是btnCancle上阻止了事件冒泡,那么body上的事件就不会被添加到btnCancle上。 alert("body clicked") }
获取一组元素的序号,原理是本身先要获取元素而后添加属性到标签中。点击事件的时候再获取自定义的属性。 两种方法,标签添加属性和使用自定义属性。 另:Dom0型事件的处理函数的this 等于 event.target属性。 <ul > <li class="a1">1</li> <li class="a2">2</li> <li class="a3">3</li> <li class="a4">4</li> <li class="a5">5</li> <li class="a6">6</li> </ul> var list = document.getElementsByTagName("li"); for(var i = 0,len = list.length;i<len;i++){ list[i].index = i;//方法1,比较好 list[i].setAttribute("data-index",i);//方法2 list[i].onclick = function(event){ console.log(this.getAttribute("data-index")); console.log(this.index); console.log(event); console.log(this==event.target); } } //固然事件也是能够绑定到父元素上 var ul = document.getElementsByTagName("ul"); ul[0].onclick = function(event){ console.log(event.target.index); }
一、window.event
表示当前的事件对象,IE的事件对象是window对象的一个属性。 FF:没有window.event对象。能够经过给函数的参数传递event对象。如onmousemove=domousemove(event)。
二、获取事件源
IE:srcElement;FF:target;
三、添加删除事件方法不一样
IE:element.attachEvent("onclick",function(){})
FF: element.addEventListener("click",function(){},false);
删除事件也是不一样的。
自定义DOM事件不是由DOM原生触发的,目的是让开发人员建立本身的事件。建立自定义事件,须要调用createEvent("CustomEvent");
且看以下实例:
var div = document.getElementById("myDiv"); var event; EventUtil.addHandler(div,"myevent",function(event){ alert("DIV: " + event.detail); }); EventUtil.addHandler(document,"myevent",function(event){ alert("DOCUMENT: " + event.detail); }); if(document.implementation.hasFeature("CustomEvents","3.0")){ event = document.createEvent("CustomEvent"); event.initCustomEvent("myevent",true,false,"hello world!");//对应参数:触发事件类型、事件是否冒泡、事件是否能够取消、任意值,保留在event对象的detail中 div.dispatchEvent(event); }
事件代理:
事件代理,具体实例,上边的ul元素绑定index,能够用。