attachEvent和addEventListener


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);
                        });
                    }
                };
            }
        })();


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM