支持DOM0、DOM2的瀏覽器和IE瀏覽器實現事件處理程序的不一樣,除了體如今添加事件處理程序的不一樣上,還體如今event對象的實現差別上,包括具體的屬性和方法。
在觸發DOM上的某個事件時,都會產生一個event對象,這個對象包含着全部與事件有關的信息。一旦事件處理程序執行完成,event對象就會被銷燬。全部瀏覽器對event的支持方式包括:DOM事件對象和IE事件對象。javascript
兼容 DOM 的瀏覽器會將一個 event 對象傳入到事件處理程序中。不管指定事件處理程序時使用什麼方法(DOM0 級或 DOM2 級) ,都會傳入 event 對象。java
var btn = document.getElementById("myBtn"); btn.onclick = function(event){ alert(event.type); //"click" }; btn.addEventListener("click", function(event){ alert(event.type); //"click" }, false);
在經過 HTML 特性指定事件處理程序時,變量 event 中保存着 event 對象:web
<input type="button" value="Click Me" onclick="alert(event.type)"/>
(1) type, String; 只讀; 被觸發的事件的類型,如click。
(2) currentTarget, Element,只讀,其事件處理程序當前正在處理事件的那個元素;
(3) target, Element, 只讀, 事件的目標;
在事件處理程序內部,對象 this 始終等於 currentTarget 的值(註冊事件處理程序的元素),而 target 則只包含事件的實際目標(事件直接觸發的元素)。若是直接將事件處理程序指定給了目標元素,則 this、 currentTarget 和 target 包含相同的值。可是考慮到有時候會使用事件冒泡機制,事件直接觸發的元素不必定是事件綁定的元素,例如:瀏覽器
//按鈕在body中,事件會冒泡到body document.body.onclick = function(event){ alert(event.currentTarget === document.body); //true alert(this === document.body); //true alert(event.target === document.getElementById("myBtn")); //true };
當單擊這個例子中的按鈕時, this 和 currentTarget 都等於 document.body,由於事件處理程序是註冊到這個元素上的。然而, target 元素卻等於按鈕元素,由於它是 click 事件真正的目標。因爲按鈕上並無註冊事件處理程序,結果 click 事件就冒泡到了 document.body,在那裏事件才獲得了處理。安全
(4) preventDefault()方法:阻止特定事件的默認行爲。例如,連接的默認行爲就是在被單擊時會導航到其 href 特性指定的 URL。app
var link = document.getElementById("myLink"); link.onclick = function(event){ event.preventDefault(); };
(5) stopPropagation()方法:用於當即中止事件在 DOM 層次中的傳播,即取消進一步的事件捕獲或冒泡。這個屬性在jQuery中很重要。函數
(6) eventPhase 屬性:能夠用來肯定事件當前正位於事件流的哪一個階段。若是是在捕獲階段調用的事件處理程序,那麼 eventPhase 等於 1;若是事件處理程序處於目標對象(直接點擊對象,通常是最內層對象)上,則 eventPhase 等於 2;若是是在冒泡階段調用的事件處理程序, eventPhase 等於 3。這裏要注意的是,儘管「處於目標」發生在冒泡階段,但 eventPhase 仍然一直等於 2。測試
var btn = document.getElementById("myBtn"); btn.onclick = function(event){ alert(event.eventPhase); //2 ,最內元素在事件傳播結束後觸發 }; document.body.addEventListener("click", function(event){ alert(event.eventPhase); //1,DOM2事件觸發使用true參數是在傳播階段觸發 }, true); document.body.onclick = function(event){ alert(event.eventPhase); //3,DOM0事件在冒泡階段觸發 };
當單擊這個例子中的按鈕時,首先執行的事件處理程序是在捕獲階段觸發的添加到 document.body中的那一個,結果會彈出一個警告框顯示錶示 eventPhase 的 1。接着,會觸發在按鈕上註冊的事件處理程序,此時的 eventPhase 值爲 2。最後一個被觸發的事件處理程序,是在冒泡階段執行的添加到document.body 上的那一個,顯示 eventPhase 的值爲 3。而當 eventPhase 等於 2 時,this、target和 currentTarget 始終都是相等的。this
IE中event對象的訪問方式取決於綁定事件處理程序的方法:
1)DOM0級方法: event對象做爲window對象的一個屬性存在。spa
var btn = document.getElementById("myBtn"); btn.onclick = function(){ var event = window.event; alert(event.type); //"click" };
2)若是事件處理程序是經過attachEvent()添加的,就有一個event對象做爲事件處理程序的參數。
var btn = document.getElementById("myBtn"); alert(typeof attachEvent); btn. attachEvent("click", function(event){ alert(event.type); //"click" });
1)cancelBubble:默認值爲false,但將其設置爲true就能夠取消事件冒泡(與DOM中
的stopPropagation()方法的做用相同);
2)returnValue:默認值爲true,但將其設置爲false就能夠取消事件的默認行爲(與
DOM中的preventDefault()方法的做用相同);
3)srcElement:事件的直接目標(與DOM中的target屬性相同);
4)type:被觸發的事件的類型。
srcElement:由於事件處理程序的做用域是根據指定它的方式來肯定的, this 不必定老是等於事件目標。例如:
var btn = document.getElementById("myBtn"); btn.onclick = function(){ alert(window.event.srcElement === this); //DOM0級方法,true }; btn.attachEvent("onclick", function(event){ alert(event.srcElement === this); //false });
returnValue 屬性:只要將 returnValue 設置爲 false,就能夠阻止默認行爲。
var link = document.getElementById("myLink"); link.onclick = function(){ window.event.returnValue = false; };
cancelBubble 屬性:與 DOM 中的 stopPropagation()方法做用相同,都是用來中止事件冒泡的。因爲 IE 不支持事件捕獲,於是只能取消事件冒泡;但 stopPropagatioin()能夠同時取消事件捕獲和冒泡。例如:
//在單擊按鈕以後,只會顯示一個警告框。 var btn = document.getElementById("myBtn"); btn.onclick = function(){ alert("Clicked"); window.event.cancelBubble = true; }; document.body.onclick = function(){ alert("Body clicked"); };
可是在IE11發佈以後attachEvent函數被替換成了addEventListener。
var btn = document.getElementById("myBtn"); alert(typeof addEventListener);//function btn.addEventListener("click", function(event){ alert(event.type); //"click" });
IE11中srcElement屬性測試:
HTML:
<div id="wrapper"> <span id = "myBtn">the onlt one div</span> </div>
JavaScript:
var wrapper = document.getElementById("wrapper"); alert(typeof addEventListener); wrapper.addEventListener("click", function(event){ alert(event.target); //span alert(event.currentTarget); //div alert(event.srcElement); //span alert(this);//div });
結論:srcElement和target是相同的,都指向事件的直接元素,可是this和currentTarget都指向事件綁定元素。
若是須要阻止默認行爲,直接使用在addEventListener()中使用event.preventDefault()便可。根據以上,能夠得出初步的結論:在IE11瀏覽器中使用addEventListener()後,DOM2級event具備的屬性和方法均可以使用。
我在IE中使用addEventListener()並無遇到問題,可是網上有一些開發者在使用時會遇到問題,提供的解決方法有數種:
https://social.msdn.microsoft...
第一種是加入一些腳本:
<script language='javascript' for="testAxEvent" event="testEvent(szType, szValue)"> // Test 1 - statically load the script (This is the basis for the hack) // Works on IE8, IE9, IE10 and IE11 var MSG = document.getElementById("msg"); MSG.innerHTML = szType + " : " + szValue; </script>
第二種是把IE的internet選項-- >安全,點擊「將全部區域重置爲默認級別」。
var EventUtil = { //是否支持DOM2?是不是IE?是否支持DOM0?通常前兩個if包含了全部狀況 addHandler: function(element, type, handler){ if (element.addEventListener){ element.addEventListener(type, handler, false); } else if (element.attachEvent){ element.attachEvent("on" + type, handler); } else { element["on" + type] = handler; } }, //IE沒有event對象,所以使用window.event getEvent: function(event){ return event ? event : window.event; }, /*使用getEvent()方法獲得event對象後纔可使用getTarget()、 preventDefault()、stopPropagation()方法 */ //先檢測DOM0 DOM2的target屬性,而後檢測IE的srcElement屬性 getTarget: function(event){ return event.target || event.srcElement; }, //先檢測DOM0 DOM2的preventDefault(),再檢測IE的returnValue preventDefault: function(event){ if (event.preventDefault){ event.preventDefault(); } else { event.returnValue = false; } }, //是否支持DOM2?是不是IE?是否支持DOM0?通常前兩個if包含了全部狀況 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; } }, //先檢測DOM0 DOM2的stopPropagation(),再檢測IE的cancelBubble stopPropagation: function(event){ if (event.stopPropagation){ event.stopPropagation(); } else { event.cancelBubble = true; } } };
測試實例:
var but = document.getElementById("myButtun"); var handler = function(event){ event = EventUtil.getEvent(event); var target = EventUtil.getTarget(event); alert(target);// [object HTMLInputElement] }; EventUtil.addHandler(but, "click", handler);
固然,上述跨瀏覽器的事件對象所包含的屬性和方法並非必須的,在實際中能夠根據實際狀況適當刪減一些屬性和方法。可是,萬變不離其宗。