本文介紹一些JavaScript事件綁定的常用方法及其優缺點,同時在最后展示一個由 Dean Edwards 寫的一個比較完美的事件綁定方案。
傳統方式
element.onclick = function(e){ // ... };
- 傳統綁定的優點
- 非常簡單和穩定,可以確保它在你使用的不同瀏覽器中運作一致
- 處理事件時,this關鍵字引用的是當前元素,這很有幫組
- 傳統綁定的缺點
- 傳統方法只會在事件冒泡中運行,而非捕獲和冒泡
- 一個元素一次只能綁定一個事件處理函數。新綁定的事件處理函數會覆蓋舊的事件處理函數
- 事件對象參數(e)僅非IE瀏覽器可用
W3C方式
element.addEventListener('click', function(e){ // ... }, false);
- W3C綁定的優點
- 該方法同時支持事件處理的捕獲和冒泡階段。事件階段取決於addEventListener最后的參數設置:false (冒泡) 或 true (捕獲)。
- 在事件處理函數內部,this關鍵字引用當前元素。
- 事件對象總是可以通過處理函數的第一個參數(e)捕獲。
- 可以為同一個元素綁定你所希望的多個事件,同時並不會覆蓋先前綁定的事件
- W3C綁定的缺點
- IE不支持,你必須使用IE的attachEvent函數替代。
IE方式
element.attachEvent('onclick', function(){ // ... });
- IE方式的優點
- 可以為同一個元素綁定你所希望的多個事件,同時並不會覆蓋先前綁定的事件。
- IE方式的缺點
- IE僅支持事件捕獲的冒泡階段
- 事件監聽函數內的this關鍵字指向了window對象,而不是當前元素(IE的一個巨大缺點)
- 事件對象僅存在與window.event參數中
- 事件必須以ontype的形式命名,比如,onclick而非click
- 僅IE可用。你必須在非IE瀏覽器中使用W3C的addEventListener
Dean Edwards的方案(addEvent/removeEvent庫)
function addEvent(elementment, type, handler) { // 為每個事件處理函數賦予一個獨立的ID if(!handler.$$guid) handler.$$guid = addEvent.guid++; // 為元素建立一個事件類型的散列表 if(!elementment.events) elementment.events = {}; // 為每對元素/事件建立一個事件處理函數的散列表 var handlers = elementment.events[type]; if(!handlers) { handlers = elementment.events[type] = {}; // 存儲已有的事件處理函數(如果已存在一個) if(elementment["on" + type]) { handlers[0] = elementment["on" + type]; } } // 在散列表中存儲該事件函數 handlers[handler.$$guid] = handler; // 賦予一個全局事件處理函數來出來所有工作 elementment["on" + type] = handleEvent; } // 創建獨立ID的計數器 addEvent.guid = 1; function removeEvent(elementment, type, handler) { // 從散列表中刪除事件處理函數 if(elementment.events && elementment.events[type]) { delementte elementment.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.$$handerEvent = handlers[i]; if(this.$$handlerEvent(event) === fasle) { returnValue = false; } } return returnValue; } // 增加一些IE事件對象缺乏的方法 function fixEvent(event) { event.preventDefault = fixEvent.preventDefault; event.stopPropagation = fixEvent.stopPropagation; return event; } fixEvent.preventDefault = function() { this.returnValue = false; } fixEvent.stopPropagation = function() { this.cancelBubble = true; }
- addEvent的優點
- 可以在所有瀏覽器中工作,就算是更古老無任何支持的瀏覽器
- this關鍵字可以在所有的綁定函數中使用,指向的是當前元素
- 中和了所有防止瀏覽器默認行為和阻止事件冒泡的各種瀏覽器特定函數
- 不管瀏覽器類型,事件對象總是作為第一個對象傳入
- addEvent的缺點
- 僅工作在冒泡階段(因為它深入使用事件綁定的傳統方式)
《精通JavaScript》讀書筆記