JavaScript跨瀏覽器綁定事件函數的優化


    JavaScript作為一門基於事件驅動的語言(特別是用在DOM操作的時候),我們常常需要為DOM綁定各種各樣的事件。然而,由於低版本的IE的不給力,在綁定事件和移除事件監聽上都與眾不同,我們常常需要自己封裝一個跨瀏覽器綁定(移除)事件的函數。跨瀏覽器添加(移除)DOM事件的一種非常經典的實現代碼如下:

//跨瀏覽器添加事件
function addHandler(target, eventType, handler) {
  if(target.addEventListener) { //DOM2 events
    target.addEventListener(eventType, handler, false);
  } else { //IE
    target.attachEvent("on" + eventType, handler);
  }
}
 
//跨瀏覽器移除事件
function removeHanler(target, eventType, handler) {
  if(target.removeEventListener) { //DOM2 events
    target.removeEventListener(eventType, handler, false);
  } else { //IE
    target.detachEvent("on", eventType, handler);
  }
}

    上面代碼的實現思路是,首先判斷瀏覽器是否支持DOM2的事件,如果支持,就用addEventListener()進行添加事件,用removeEventListener來移除事件。如果不支持,那么默認就是低版本的ie瀏覽器了,並使用ie特有的方法。

    乍一看,上面的代碼好像已經充分優化了。隱藏的性能問題在於 每次函數調用時都會做重復工作——檢測瀏覽器的類型。這是比較消耗性能,特別是你綁定大量事件,反復調用的時候。事實上,這是不必要的,我們只需要判斷一次就行的了。因為一旦頁面加載完成后,瀏覽器的類型已經是確定了的,不可能說,現在是IE,然后瀏覽着瀏覽着突然就會變成了chrome的了。所以,我們應該對上面代碼進行優化,使其只需要檢測一次瀏覽器。有兩種方法可以實現只檢測一次,下面分別來探討一下這兩種方法。
  第一種是,在第一次調用添加(移除)事件函數的時候,檢測並決定使用哪種方法來綁定或者移除事件,然后重寫函數,用一個包含正確操作的新的函數覆蓋舊的函數, 並且在舊的函數最后調用該這個新的函數。上面代碼改寫后如下:
//添加事件
function addHandler(target, eventType, handler) {
 
  //檢測瀏覽器類型,並且重寫addHanler方法
  if(target.addEventListener) { //DOM2
    addHandler = function(target, eventType, handler) {
      target.addEventListener(eventType, handler, false);
    };
  } else { //IE
    addHandler = function(target, eventType, handler) {
      target.attachEvent("on" + eventType, handler);
    };
  }
   
  //調用新的函數
  addHandler(target, eventType, handler);
}
 
//移除事件removeHanler
function removeHandler(target, eventType, handler) {
 
  //檢測瀏覽器類型,並且重寫removeHandler方法
  if(target.removeEventListener) { //DOM2
    removeHandler = function(target, eventType, handler) {
      target.removeEventListener(eventType, handler, false);
    };
  } else { //IE
    removeHandler = function(target, eventType, handler) {
      target.detachEvent("on" + eventType, handler);
    };
  }
 
  //調用新的函數
  removeHandler(target, eventType, handler);
}

    需要注意的是,我們在兩個函數的最后一行,都調用了被重寫了的新函數,比如addHandler(target, eventType, handler);和removeHandler(target, eventType, handler);這是必要的,因為我們用新的函數覆蓋了舊的函數,必須要在舊的函數里調用新的函數它才會執行一次

    還有一種優化方法是,提前檢測瀏覽器類型,並把正確的操作函數賦值給一個變量(或者說是使用函數表達式)。我們可以使用一個三目條件運算符(?...:)來實現,代碼如下:
//綁定事件
var addHandler = document.body.addEventListener ?
          function(target, eventType, handler) { //DOM2
            target.addEventListener(eventType, handler,false);
          } :
          function(target, eventType, handler) { //IE
            target.attachEvent("on" + eventType, handler);
          };
//移除事件 var removeHandler = document.body.removeEventListener ?             function(target, eventType, handler) { //DOM2               target.removeEventListener(eventType, handler, false);             } :             function(target, eventType, handler) { //IE               target.detachEvent("on" + eventType, handler);             }

    這種方法,比前面比前面那種更加的“積極”,因為他是在函數調用之前就已經去檢測瀏覽器類型了,調用的時候馬上就可以正確的去綁定事件。

PS:
參考資料: Nicbolas C.Zakas 《High Performance JavaScript》;chapter 8 ;Don’t Repeat Work
該書目前好像只有英文版而還沒有中文版的。如果有需要的可以Google一下,下載個電子版的來看一下
 
 
 


免責聲明!

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



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