attachEvent和addEventListener在前端開發過程中經常性的使用,他們都可以用來綁定腳本事件,取代在html中寫obj.onclick=method
。
相同點:
它們都是dom對象的方法,可以實現一種事件綁定多個事件處理函數。
obj = document.getElementById("testdiv"); obj.onclick=function(){alert('1');}; obj.onclick=function(){alert('2');}; obj.onclick=function(){alert('3');}; // 當使用上邊三句話進行事件綁定的時候,很明顯當點擊ID為testdiv對象時,只能執行
//最后一句腳本。因為onclick作為一個事件處理對象,只能賦一個值,后面的賦值自動覆
//蓋前面的
使用attachEvent和addEventListener時則可以實現多個事件處理函數的調用
obj = document.getElementById("testdiv"); obj.attachEvent('onclick',function(){{alert('1');}); obj.attachEvent('onclick',function(){{alert('2');}); obj.attachEvent('onclick',function(){{alert('3');});//點擊時,三個方法都會執行
obj = document.getElementById("testdiv"); obj.addEventListener('click',function(){{alert('1');},false); obj.addEventListener('click',function(){{alert(2');},false); obj.addEventListener('click',function(){{alert('3');},false);//點擊時,三個方法都會執行
不同點:
1.attachEvent是IE有的方法,它不遵循W3C標准,而其他的主流瀏覽器如FF等遵循W3C標准的瀏覽器都使用addEventListener,所以實際開發中需分開處理。
2.多次綁定后執行的順序是不一樣的,attachEvent是后綁定先執行,addEventListener是先綁定先執行。
obj = document.getElementById("testdiv"); obj.attachEvent('onclick',function(){{alert('1');}); obj.attachEvent('onclick',function(){{alert('2');}); obj.attachEvent('onclick',function(){{alert('3');}); //執行順序是alert(3),alert(2),alert(1);
obj = document.getElementById("testdiv"); obj.addEventListener('click',function(){{alert('1');},false); obj.addEventListener('click',function(){{alert('2');},false); obj.addEventListener('click',function(){{alert('3');},false); //點擊obj對象時,執行順序為alert('1'),alert('2'),alert('3');
3.綁定時間時,attachEvent必須帶on,如onclick,onmouseover等,而addEventListener不能帶on,如click,mouseover。這個區別在以上代碼中可見。
4.attachEvent僅需要傳遞兩個參數,而addEventListener需要傳遞三個參數,這里牽扯到“事件流”的概念。偵聽器在偵聽時有三個階段:捕獲階段、目標階段和冒泡階段。順序為:捕獲階段(根節點到子節點檢查是否調用了監聽函數)→目 標階段(目標本身)→冒泡階段(目標本身到根節點)。此處的參數確定偵聽器是運行於捕獲階段、目標階段還是冒泡階段。 如果將 useCapture 設置為 true,則偵聽器只在捕獲階段處理事件,而不在目標或冒泡階段處理事件。 如果useCapture 為 false,則偵聽器只在目標或冒泡階段處理事件。 要在所有三個階段都偵聽事件,請調用兩次 addEventListener,一次將 useCapture 設置為 true,第二次再將useCapture 設置為 false。
為了解決瀏覽器的兼容性可以寫如下代碼:
function addEvent(elm, evType, fn, useCapture) { if (elm.addEventListener) { // W3C標准 elm.addEventListener(evType, fn, useCapture); return true; } else if (elm.attachEvent) { //IE var r = elm.attachEvent(‘on‘ + evType, fn);//IE5+ return r; } else { elm['on' + evType] = fn;//DOM事件 } }
function addEvent(element, type, handler) { //為每一個事件處理函數分派一個唯一的ID if (!handler.$$guid) handler.$$guid = addEvent.guid++; //為元素的事件類型創建一個哈希表 if (!element.events) element.events = {}; //為每一個"元素/事件"對創建一個事件處理程序的哈希表 var handlers = element.events[type]; if (!handlers) { handlers = element.events[type] = {}; //存儲存在的事件處理函數(如果有) if (element["on" + type]) { handlers[0] = element["on" + type]; } } //將事件處理函數存入哈希表 handlers[handler.$$guid] = handler; //指派一個全局的事件處理函數來做所有的工作 element["on" + type] = handleEvent; }; //用來創建唯一的ID的計數器 addEvent.guid = 1; function removeEvent(element, type, handler) { //從哈希表中刪除事件處理函數 if (element.events && element.events[type]) { delete element.events[type][handler.$$guid]; } }; function handleEvent(event) { var returnValue = true; //抓獲事件對象(IE使用全局事件對象) event = event || fixEvent(window.event); //取得事件處理函數的哈希表的引用 var handlers = this.events[event.type]; //執行每一個處理函數 for (var i in handlers) { this.$$handleEvent = handlers[i]; if (this.$$handleEvent(event) === false) { returnValue = false; } } return returnValue; }; //為IE的事件對象添加一些“缺失的”函數 function fixEvent(event) { //添加標准的W3C方法 event.preventDefault = fixEvent.preventDefault; event.stopPropagation = fixEvent.stopPropagation; return event; }; fixEvent.preventDefault = function () { this.returnValue = false; }; fixEvent.stopPropagation = function () { this.cancelBubble = true; };
var addEvent = (function () { if (document.addEventListener) { return function (el, type, fn) { if (el.length) { for (var i = 0; i && el.length; i++) { addEvent(el[i], type, fn); } } else { el.addEventListener(type, fn, false); } }; } else { return function (el, type, fn) { if (el.length) { for (var i = 0; i && el.length; i++) { addEvent(el[i], type, fn); } } else { el.attachEvent('on' + type, function () { return fn.call(el, window.event); }); } }; } })();