addEventListener/attachEvent兼容IE瀏覽器與標準瀏覽器

標用準瀏覽器中可以使addEventListener()函數來給DOM元素綁定事件,使用removeEventListener()函數移除事件綁定,而IE6 IE7 IE8不支持addEventListener()和removeEventListener(),只能使用attachEvent()和detachEventListener()方法。IE從IE9開始支持addEventListener和removeEventListener.


addEventListener()和attachEvent()的區別主要有以下幾點:

  • addEventListener(type,handler,capture)有三個參數,其中type是事件名稱,如click,handler是事件處理函數,capture是否使用捕獲,是一個布爾值,一般爲false,這是默認值,所以第三個參數可以不寫
    attachEvent('on'+type,handler)有兩個參數,其中type是事件名稱,如click,第一個參數必須是onxxxx,handler是事件處理函數,IE6 IE7 IE8不支持事件捕獲的,只支持事件冒泡。
    關於事件冒泡:如果一個元素和它的各層上級素都設置了相同的事件,比如click事件,那麼冒泡是指,當用戶點擊鼠標後,先觸發最底層元素的click事件,然後依次逐層觸發上一級元素的click事件,就像泡泡從水底冒到水面一樣。
    而與事件冒泡相反,事件捕獲的順序是,從頁面的根元素開始依次逐層向下級觸發事件。
    IE6-8只支持事件冒泡不支持事件捕獲,Google Chrome/Firefox/Safari/Opera等標準瀏覽器支持事件捕獲和事件冒泡。
    如果只想在最底層執行事件處理函數,阻止向上級元素冒泡,也就是說如果要阻止事件冒泡,標準瀏覽器可以使用stopPropagation(),IE6 7 8可以使用cancelBubble=true
  • addEventListener綁定的事件是先綁定先執行,attachEvent綁定的事件是先綁定後執行
  • 在IE6 IE7 IE8瀏覽器中,使用了attachEvent或detachEvent後事件處事函數裏面的this指向window對象,而不是事件對象元素,文末有解決方案
  • 如果一個事件在綁定以後有解除綁定的需要,可以使用removeEventListener(),參數和addEventListener一樣,IE6 IE7 IE8使用detachEvent函數,參數和attachEvent一樣,注意,想要移除綁定的事件,則綁定事件時不能使用匿名函數,而需要將事件處事函數單獨寫成一個函數。否則無法移除綁定的事件函數,因爲只綁定的事件才能移除,匿名函數和匿名函數是互相不相同的,即使代碼完全一樣,但本質上同一匿名函數的代碼寫兩次就是兩個不同的函數。
    下面以addEventListener爲例


  1.         <a id="xc">點擊</a>
  2.         <script type="text/javascript">
  3.                 function handler(){
  4.                         alert(this.innerHTML);
  5.                 }
  6.                 var object=document.getElementById('xc');
  7.                 xc.addEventListener('click',handler,false);//添加事件
  8.                 xc.removeEventListener('click',handler,false);//移除事件
  9.                 /*下面這種使用匿名函數的方式添加的事件是不能移除的,因爲兩個匿名函數雖然代碼一樣,但本質上他們是兩個不同的函數
  10.                 xc.addEventListener('click',function(){
  11.                         alert(this.innerHTML);
  12.                 },false);
  13.                 xc.removeEventListener('click',function(){
  14.                         alert(this.innerHTML);
  15.                 },false);
  16.                 */
  17.         </script>


5.所添加的事件必須是事件對象支持的事件,比如給window對象添加click事件就不會成功,因爲window沒有click事件

6.解決IE6 IE7 IE8 attchEvent this指向window的方法:

要解決IE6 IE7 IE8 attachEvent this指向錯誤,有至少以下三種方法:

(1).使用事件處理函數.apply(事件對象,arguments),代碼如下
    以下代碼僅適用於IE6 IE7 IE8,這種方式的缺點是綁定的事件無法取消綁定,原因上面已經說了,匿名函數和匿名函數之間是互不相等的。

  1.   <a id="xc">點擊</a>
  2.         <script type="text/javascript">
  3.                 var object=document.getElementById('xc');
  4.                 function handler(){
  5.                         alert(this.innerHTML);
  6.                 }
  7.                 object.attachEvent('onclick',function(){
  8.                         handler.call(object,arguments);
  9.                 });
  10.         </script>


(2)使用事件源代替this關鍵字
以下代碼僅適用於IE6 IE7 IE8,這種方式完全忽略this關鍵字,但寫起來稍顯麻煩。

  1.  <a id="xc">點擊</a>
  2.         <script type="text/javascript">
  3.                 function handler(e){
  4.                         e=e||window.event;
  5.                         var _this=e.srcElement||e.target;
  6.                         alert(_this.innerHTML);
  7.                 }
  8.                 var object=document.getElementById('xc');
  9.                 object.attachEvent('onclick',handler);
  10.         </script>

(3)自己寫一個函數完全代替attachEvent/detachEvent,並且支持所有主流瀏覽器、解決IE6 IE7 IE8事件綁定導致的先綁定後執行問題。
下面是完美兼容addEventListener/removeEventListener和attachEvent/detachEvent的函數,支持Google Chrome/Firefox/Safari/Opera/IE 6 7 8 9 10 11等所有主流瀏覽器,能夠完美解決IE6 IE7 IE8 this指向錯誤,能夠糾正IE6 IE7 IE8中事件先綁定後執行的錯誤。
爲了避免代碼被編輯器修改,請下載附件測試。不要直接複製下面的代碼。
注意,本函數是全局函數,而不是DOM對象的成員方法。


<a id="xc">點擊</a>
<script type="text/javascript">
        /*
         * 添加事件處理程序
         * @param object object 要添加事件處理程序的元素
         * @param string type 事件名稱,如click
         * @param function handler 事件處理程序,可以直接以匿名函數的形式給定,或者給一個已經定義的函數名。匿名函數方式給定的事件處理程序在IE6 IE7 IE8中可以移除,在標準瀏覽器中無法移除。
         * @param boolean remove 是否是移除的事件,本參數是爲簡化下面的removeEvent函數而寫的,對添加事件處理程序不起任何作用
        */
        function addEvent(object,type,handler,remove){
                if(typeof object!='object'||typeof handler!='function') return;
                try{
                        object[remove?'removeEventListener':'addEventListener'](type,handler,false);
                }catch(e){
                        var xc='_'+type;
                        object[xc]=object[xc]||[];
                        if(remove){
                                var l=object[xc].length;
                                for(var i=0;i<l;i++){
                                        if(object[xc][i].toString()===handler.toString()) object[xc].splice(i,1);
                                }
                        }else{
                                var l=object[xc].length;
                                var exists=false;
                                for(var i=0;i<l;i++){                                                
                                        if(object[xc][i].toString()===handler.toString()) exists=true;
                                }
                                if(!exists) object[xc].push(handler);
                        }
                        object['on'+type]=function(){
                                var l=object[xc].length;
                                for(var i=0;i<l;i++){
                                        object[xc][i].apply(object,arguments);
                                }
                        }
                }
        }
        /*
         * 移除事件處理程序
        */
        function removeEvent(object,type,handler){
                addEvent(object,type,handler,true);
        }
</script>
<script type="text/javascript">
        function handler(){
                alert(this.innerHTML);
        }
        var object=document.getElementById('xc');
        addEvent(object,'click',handler);
        //如果要測試綁定事件,請先刪除下面這一行。
        removeEvent(object,'click',handler);
</script>


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章