根據(jù) W3C DOM 2 Events 描述,EventTarget 接口被所有支持 DOM 事件模型的節(jié)點(diǎn)(Node)實(shí)現(xiàn)。 該接口提供了 'addEventListener' 和 'removeEventListener' 方法,用來綁定或解綁一個(gè) EventListeners 接口到一個(gè) EventTarget。
DOM 2 Events 中定義了 Event 接口,用來提供事件的上下文信息,它提供了若干標(biāo)準(zhǔn)屬性和方法。 實(shí)現(xiàn) Event 接口的對(duì)象一般作為第一個(gè)參數(shù)傳入事件處理函數(shù),以用來提供當(dāng)前事件相關(guān)的一些信息。
DOM 2 事件模型允許 DOM 實(shí)現(xiàn)支持事件的多模塊,如果有必要,事件模型允許附加新的事件模塊。 為了共同使用性的目的,DOM 會(huì)定義一個(gè)包含低級(jí)別的,依賴設(shè)備的事件模塊、一個(gè) UI 邏輯事件模塊和一個(gè)文檔變化事件模塊的 UI 事件模塊。 第三方實(shí)現(xiàn)(比如瀏覽器廠商)在定義一個(gè)新類型事件的時(shí)候,事件名稱一定不能使用大小寫無關(guān)的 'DOM' 字符串作開頭,該前綴是為未來的 DOM 事件模塊保留的。
DOM 2 已經(jīng)定義了一個(gè) UI 事件類型模塊和一個(gè)鼠標(biāo)事件類型的模塊,它們分別對(duì)應(yīng) UIEvent 和 MouseEvent 接口。 這兩個(gè)接口提供了若干標(biāo)準(zhǔn)屬性和方法,以獲知事件發(fā)生時(shí)的一些信息。
關(guān)于 EventTarget 接口的詳細(xì)信息,請(qǐng)參考 DOM 2 Events 1.3. Event listener registration。
關(guān)于 Event 接口的詳細(xì)信息,請(qǐng)參考 DOM 2 Events 1.4. Event interface。
關(guān)于事件模塊的詳細(xì)信息,請(qǐng)參考 DOM 2 Events 1.6. Event module definitions。
各瀏覽器對(duì)元素綁定、解綁事件監(jiān)聽器的方法,事件對(duì)象的獲取,以及 Event 對(duì)象的實(shí)現(xiàn)上存在差異。
如果使用某瀏覽器特有的事件相關(guān)的屬性及方法編寫代碼,則可能造成兼容性問題,導(dǎo)致代碼報(bào)錯(cuò),功能失效。
| 所有瀏覽器 |
|---|
根據(jù) DOM 2 Events 中描述,節(jié)點(diǎn)使用 'addEventListener' 和 'removeEventListener' 方法綁定和解綁事件監(jiān)聽器,但 IE6 IE7 IE8 不支持這兩個(gè)方法, 而使用 'attachEvent' 和 'detachEvent' 方法作為替代方案,Opera 兩類方法都支持。Chrome Safari Firefox 只支持標(biāo)準(zhǔn)方法。
分析以下代碼:
<button id="add" type="button">add event listener test</button><button id="remove" type="button">remove event listener test</button><div id="info"></div><script type="text/javascript"> var add = document.getElementById("add"), remove = document.getElementById("remove"), showMsgA = function(){showMsg("attachEvent")}, showMsgB = function(){showMsg("addEventListener")}; if(add.attachEvent){ add.attachEvent("onclick",showMsgA); remove.attachEvent("onclick",removeE); } if(add.addEventListener){ add.addEventListener("click",showMsgB,false); remove.addEventListener("click",removeE,false); } function removeE(){ if(add.detachEvent){ add.detachEvent("onclick",showMsgA); showMsg("detachEvent"); } if(add.removeEventListener){ add.removeEventListener("click",showMsgB,false); showMsg("removeEventListener"); } } function showMsg(method){ document.getElementById("info").innerHTML += ("support " + method + "<br />"); }</script>依次點(diǎn)擊 'add event listener test' >> 'remove event listener test' >> 'add event listener test',測(cè)試各瀏覽器對(duì)這些方法的支持,結(jié)果如下:
| IE6 IE7 IE8 | ![]() |
|---|---|
| Opera | ![]() |
| Chrome Safari Firefox | ![]() |
關(guān)于 'addEventListener' 和 'attachEvent' 有幾點(diǎn)需要注意:
DOM 2 Events 中規(guī)定使用事件監(jiān)聽器的第一個(gè)參數(shù)作為事件對(duì)象,而 IE Opera Chrome Safari 還支持通過 window.event 獲取事件對(duì)象。
分析以下代碼:
<button type="button" id="attach">attachEvent</button><button type="button" id="addE">addEventListener</button><button type="button" id="byclick">onClick</button><br />INFO :<div id="info"></div><script type="text/javascript"> function $(id){return document.getElementById(id);} var attach = $("attach"), addE = $("addE"), byClick = $("byclick"); attach.attachEvent && attach.attachEvent("onclick", handler); addE.addEventListener && addE.addEventListener("click", handler, false); byClick.onclick = handler; function handler(){ var src = window === this ? window.event.srcElement : this, type = src.innerHTML; window.event && showMsg(window.event.type, type + " + window.event"); arguments[0] && showMsg(arguments[0].type, type + " + arguments[0]"); } function showMsg(type, msg){ $("info").innerHTML += (msg + "(type : " + type + ")<br />"); }</script>以上代碼組合不同的事件監(jiān)聽器綁定方式和事件對(duì)象獲取方法,測(cè)試各瀏覽器的支持程度。
依次點(diǎn)擊 'attachEvent' >> 'addEventListener' >> 'onClick',結(jié)果如下:
| IE6 IE7 IE8 | ![]() |
|---|---|
| Chrome Safari | ![]() |
| Opera | ![]() |
| Firefox | ![]() |
匯總測(cè)試結(jié)果如下表:1
| 事件對(duì)象獲取方式 | IE6 IE7 IE8 | Chrome Safari | Opera | Firefox |
|---|---|---|---|---|
| window.event | Y | Y | Y | N |
| arguments[0] | Y2 | Y | Y | Y |
注1: Y 表示支持該事件對(duì)象獲取方式,N 表示不支持。
注2: 部分支持。
從上表出可以看出:
IE 對(duì)事件對(duì)象的標(biāo)準(zhǔn)屬性和方法支持有限,針對(duì)大部分屬性和方法,IE 都提供了一套替代非標(biāo)準(zhǔn)的替代方案; 而 Firefox Chrome Safari Opera 除了全面支持事件對(duì)象的標(biāo)準(zhǔn)屬性和方法外,還在不同程度上支持了 IE 提供的非標(biāo)準(zhǔn)替代方案。
以下代碼檢測(cè)了 Event、UIEvent、MouseEvent 接口以及事件對(duì)象的非標(biāo)準(zhǔn)屬性在各瀏覽器下的支持程度:
<button type="button" id="iEvent">Interface Event</button><button type="button" id="iUIMouse">Interface UIEvent & MouseEvent</button><input type="text" id="nosK" /><p id="wrap" style="border:3px solid;padding:5px;width:500px;"><a id="nosCM" href="#"><img src="google.gif" alt="IE"/></a></p><br /><table border="1"> <tbody> <tr> <th>Interface Event</th> <td id="einfo"></td> </tr> <tr> <th>Interface UIEvent<br/>&<br/>MouseEvent</th> <td id="minfo"></td> </tr> <tr> <th>Non-standard<br/>&<br/>click</th> <td id="ncinfo"></td> </tr> <tr> <th>Non-standard<br/>&<br/>mouseover mouseout</th> <td id="nminfo"></td> </tr> <tr> <th>Non-standard<br/>&<br/>keyCode</th> <td id="nkinfo"></td> </tr> </tbody></table><script type="text/javascript"> function $(id){return document.getElementById(id);} function addEvent(elem, type, handler, useCapture){ elem.addEventListener ? elem.addEventListener(type, handler, useCapture) : elem.attachEvent("on" + type, handler); } addEvent($("iEvent"), "click", handleEvent, false); addEvent($("iUIMouse"), "click", handleUIMouse, false); addEvent($("nosCM"), "click", handleNoSClick, false); addEvent($("wrap"), "click", function(){alert("P tag.");}, false); addEvent($("nosCM"), "mouseover", handldNoSMouse, false); addEvent($("nosCM"), "mouseout", handldNoSMouse, false); addEvent($("nosK"), "keydown", handleNoSKey, false); addEvent($("nosK"), "keypress", handleNoSKey, false); addEvent($("nosK"), "keyup", handleNoSKey, false); function handleEvent(e){ e = e || window.event; var props = { type : "type", target : "target", currentTarget : "currentTarget", eventPhase : "eventPhase", bubbles : "bubbles", cancelable : "cancelable", timeStamp : "timeStamp", initEvent : "initEvent", preventDefault : "preventDefault", stopPropagation : "stopPropagation" }; showMsg(props, e, $("einfo")); } function handleUIMouse(e){ e = e || window.event; var props = { view : "view", detail : "detail", initUIEvent : "initUIEvent", screenX: "screenX", screenY : "screenY", clientX : "clientX", clientY : "clientY", ctrlKey : "ctrlKey", shiftKey : "shiftKey", altKey : "altKey", metaKey : "metaKey", button : "button", relatedTarget : "relatedTarget", initMouseEvent : "initMouseEvent" } showMsg(props, e, $("minfo")); } function handleNoSClick(e){ e = e || window.event; e.returnValue = false; e.cancelBubble = true; var props = { cancelBubble : "cancelBubble", offsetX : "offsetX", offsetY : "offsetY", returnValue : "returnValue", srcElement : "srcElement", x : "x", y : "y" }; showMsg(props, e, $("ncinfo")); } function handldNoSMouse(e){ e = e || window.event; var props = { fromElement : "fromElement", toElement : "toElement" }; showMsg(props, e, $("nminfo")); } function handleNoSKey(e){ e = e || window.event; $("nkinfo").innerHTML += "<strong>" + e.type + "</strong> : " + e.keyCode + "<br/>"; } function showMsg(props, e, info){ var tmp = "", p, val; with(e){ for(p in props) { try{ val = eval(props[p]) + " [" + typeof eval(props[p]) + "]"; } catch (e) { val = undefined; } tmp += "<strong>" + p + "</strong> : " + val + "<br />" } } info.innerHTML = tmp; }</script>執(zhí)行以上測(cè)試代碼,分別點(diǎn)擊 'Interface Event' 按鈕、'Interface UIEvent & MouseEvent' 按鈕和圖片,鼠標(biāo)移到圖片上再移開,在文本框中輸入 'a',得到結(jié)果整理如下表:3
| Interface & Non-standard | Property & method | IE6 IE7 IE8 | Chrome Safari Opera | Firefox |
|---|---|---|---|---|
| Interface Event | type | Y | Y | Y |
| target | N | Y | Y | |
| currentTarget | N | Y | Y | |
| eventPhase | N | Y | Y | |
| bubbles | N | Y | Y | |
| cancelable | N | Y | Y | |
| timeStamp | N | Y | Y | |
| initEvent | N | Y | Y | |
| preventDefault | N | Y | Y | |
| stopPropagation | N | Y | Y | |
| Interface UIEvent | view | N | Y | Y |
| detail | N | Y | Y | |
| initUIEvent | N | Y | Y | |
| Interface MouseEvent | screenX | Y | Y | Y |
| screenY | Y | Y | Y | |
| clientX | Y | Y | Y | |
| clientY | Y | Y | Y | |
| ctrlKey | Y | Y | Y | |
| shiftKey | Y | Y | Y | |
| altKey | Y | Y | Y | |
| metaKey | N | Y | Y | |
| button | Y | Y | Y | |
| relatedTarget | N | Y | Y | |
| initMouseEvent | N | Y | Y | |
| Non-standard | cancelBubble | Y | Y | Y |
| offsetX | Y | Y | N | |
| offsetY | Y | Y | N | |
| returnValue | Y | Y | N | |
| srcElement | Y | Y | N | |
| x | Y | Y | N | |
| y | Y | Y | N | |
| fromElement | Y | Y | N | |
| toElement | Y | Y | N | |
| keyCode | Y | Y | Y |
注3: Y 代表事件對(duì)象支持該屬性或方法,N 代表不支持。
從上表中可以看出:
需要注意的是:
關(guān)于 IE 實(shí)現(xiàn)的事件對(duì)象非標(biāo)準(zhǔn)的屬性及方法的詳細(xì)信息,請(qǐng)參考 MSDN event Object。
關(guān)于 Firefox 對(duì)事件對(duì)象實(shí)現(xiàn)的詳細(xì)信息,請(qǐng)參考 MDC event。
如:
function addEvent(elem, type, handler, useCapture){ elem.addEventListener ? elem.addEventListener(type, handler, useCapture) : elem.attachEvent("on" + type, handler);}function removeEvent(elem, type, handler, useCapture){ elem.removeEventListener ? elem.removeEventListener(type, handler, useCapture) : elem.detachEvent("on" + type, handler);}在事件監(jiān)聽器中判斷傳入的第一個(gè)參數(shù)或 window.event 是否有效,如:
function handler(e){ e = e || window.event;}盡管 IE 對(duì)事件對(duì)象的標(biāo)準(zhǔn)屬性和方法支持有限,但它自己實(shí)現(xiàn)的事件模型也基本能夠替代或?qū)崿F(xiàn)標(biāo)準(zhǔn)屬性或方法的功能。
下表總結(jié)了部分與標(biāo)準(zhǔn)事件對(duì)象對(duì)應(yīng)的,或可以實(shí)現(xiàn)標(biāo)準(zhǔn)屬性或方法功能的非標(biāo)準(zhǔn)屬性:
| Standard | Non-standard |
|---|---|
| target | srcElement |
| preventDefault() | returnValue |
| stopPropagation() | cancelBubble |
| relatedTarget | fromElement toElement |
另,標(biāo)準(zhǔn)的 'clientX' 屬性和非標(biāo)準(zhǔn)的 'x' 屬性作用是相同的,同樣 'clientY' 和 'y' 也是。
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注