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,能夠用。